aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNils Achtergarde <[email protected]>2018-01-04 21:39:25 +0000
committerNils Achtergarde <[email protected]>2018-01-04 21:39:25 +0000
commitb36dc4d79f446ae69aeb85137663a4e0ca23eba2 (patch)
tree23d0ae5e94e874064143735c249a2ad2cb95ad16 /src
parentadded .gitignore with mocfiles-dir and objectfiles-dir (diff)
downloadgpg4usb-b36dc4d79f446ae69aeb85137663a4e0ca23eba2.tar.gz
gpg4usb-b36dc4d79f446ae69aeb85137663a4e0ca23eba2.zip
put *.h and *.cpp to src-subdirectory
Diffstat (limited to 'src')
-rw-r--r--src/aboutdialog.cpp92
-rw-r--r--src/aboutdialog.h73
-rw-r--r--src/attachments.cpp183
-rw-r--r--src/attachments.h68
-rw-r--r--src/attachmenttablemodel.cpp138
-rw-r--r--src/attachmenttablemodel.h56
-rw-r--r--src/editorpage.cpp108
-rw-r--r--src/editorpage.h101
-rwxr-xr-xsrc/fileencryptiondialog.cpp249
-rwxr-xr-xsrc/fileencryptiondialog.h118
-rw-r--r--src/findwidget.cpp135
-rw-r--r--src/findwidget.h42
-rw-r--r--src/gpgconstants.cpp31
-rw-r--r--src/gpgconstants.h40
-rw-r--r--src/gpgcontext.cpp835
-rw-r--r--src/gpgcontext.h183
-rw-r--r--src/helppage.cpp81
-rw-r--r--src/helppage.h50
-rw-r--r--src/keydetailsdialog.cpp225
-rw-r--r--src/keydetailsdialog.h87
-rw-r--r--src/keygendialog.cpp255
-rw-r--r--src/keygendialog.h93
-rw-r--r--src/keygenthread.cpp34
-rw-r--r--src/keygenthread.h56
-rw-r--r--src/keyimportdetaildialog.cpp160
-rw-r--r--src/keyimportdetaildialog.h55
-rw-r--r--src/keylist.cpp321
-rw-r--r--src/keylist.h76
-rwxr-xr-xsrc/keymgmt.cpp289
-rwxr-xr-xsrc/keymgmt.h92
-rw-r--r--src/keyserverimportdialog.cpp313
-rw-r--r--src/keyserverimportdialog.h89
-rw-r--r--src/main.cpp121
-rw-r--r--src/mainwindow.cpp1043
-rw-r--r--src/mainwindow.h374
-rw-r--r--src/mime.cpp243
-rw-r--r--src/mime.h134
-rwxr-xr-xsrc/quitdialog.cpp131
-rwxr-xr-xsrc/quitdialog.h50
-rwxr-xr-xsrc/settingsdialog.cpp716
-rwxr-xr-xsrc/settingsdialog.h217
-rw-r--r--src/textedit.cpp573
-rw-r--r--src/textedit.h275
-rw-r--r--src/verifydetailsdialog.cpp103
-rw-r--r--src/verifydetailsdialog.h48
-rw-r--r--src/verifykeydetailbox.cpp99
-rw-r--r--src/verifykeydetailbox.h47
-rw-r--r--src/verifynotification.cpp185
-rw-r--r--src/verifynotification.h109
-rw-r--r--src/wizard.cpp431
-rw-r--r--src/wizard.h167
51 files changed, 9794 insertions, 0 deletions
diff --git a/src/aboutdialog.cpp b/src/aboutdialog.cpp
new file mode 100644
index 0000000..3362342
--- /dev/null
+++ b/src/aboutdialog.cpp
@@ -0,0 +1,92 @@
+/*
+ * aboutdialog.cpp
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "aboutdialog.h"
+
+AboutDialog::AboutDialog(QWidget *parent)
+ : QDialog(parent)
+{
+ this->setWindowTitle(tr("About ")+ qApp->applicationName());
+
+ QTabWidget *tabWidget = new QTabWidget;
+ InfoTab *infoTab = new InfoTab;
+ TranslatorsTab *translatorsTab = new TranslatorsTab;
+
+ tabWidget->addTab(infoTab, tr("General"));
+ tabWidget->addTab(translatorsTab, tr("Translators"));
+
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok);
+ connect(buttonBox, SIGNAL(accepted()), this, SLOT(close()));
+
+ QVBoxLayout *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(tabWidget);
+ mainLayout->addWidget(buttonBox);
+ setLayout(mainLayout);
+
+ this->exec();
+}
+
+InfoTab::InfoTab(QWidget *parent)
+ : QWidget(parent)
+{
+ QPixmap *pixmap = new QPixmap(":gpg4usb-logo.png");
+ QString *text = new QString("<center><h2>" + qApp->applicationName() + " "
+ + qApp->applicationVersion() + "</h2></center>"
+ + tr("<center>This application allows simple encryption <br>"
+ "and decryption of text messages or files.<br>"
+ "It's licensed under the GPL v3<br><br>"
+ "<b>Developer:</b><br>"
+ "Bene, Heimer, Juergen, Nils, Ubbo<br><br>"
+ "If you have any questions or suggestions have a look<br/>"
+ "at our <a href=\"http://gpg4usb.cpunk.de/contact.php\">"
+ "contact page</a> or send a mail to our<br/> mailing list at"
+ " <a href=\"mailto:[email protected]\">[email protected]</a>.") + tr("<br><br> Built with Qt ") + qVersion()
+ + tr(" and GPGME ") + GpgME::GpgContext::getGpgmeVersion() +"</center>");
+
+ QGridLayout *layout = new QGridLayout();
+ QLabel *pixmapLabel = new QLabel();
+ pixmapLabel->setPixmap(*pixmap);
+ layout->addWidget(pixmapLabel, 0, 0, 1, -1, Qt::AlignCenter);
+ QLabel *aboutLabel = new QLabel();
+ aboutLabel->setText(*text);
+ aboutLabel->setOpenExternalLinks(true);
+ layout->addWidget(aboutLabel, 1, 0, 1, -1);
+ layout->addItem(new QSpacerItem(20, 10, QSizePolicy::Minimum,
+ QSizePolicy::Fixed), 2, 1, 1, 1);
+
+ setLayout(layout);
+}
+
+TranslatorsTab::TranslatorsTab(QWidget *parent)
+ : QWidget(parent)
+{
+ QFile translatorsFile;
+ translatorsFile.setFileName(qApp->applicationDirPath()+"/TRANSLATORS");
+ translatorsFile.open(QIODevice::ReadOnly);
+ QByteArray inBuffer = translatorsFile.readAll();
+
+ QLabel *label = new QLabel(inBuffer);
+ QVBoxLayout *mainLayout = new QVBoxLayout(this);
+ mainLayout->addWidget(label);
+
+ setLayout(mainLayout);
+}
+
diff --git a/src/aboutdialog.h b/src/aboutdialog.h
new file mode 100644
index 0000000..295ee6f
--- /dev/null
+++ b/src/aboutdialog.h
@@ -0,0 +1,73 @@
+/*
+ * aboutdialog.h
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef __ABOUTDIALOG_H__
+#define __ABOUTDIALOG_H__
+
+#include <QWidget>
+#include <QtGui>
+
+#include "gpgcontext.h"
+
+QT_BEGIN_NAMESPACE
+class QVBoxLayout;
+class QLabel;
+class QTabWidget;
+QT_END_NAMESPACE
+
+/**
+ * @brief Class containing the main tab of about dialog
+ *
+ */
+class InfoTab : public QWidget
+ {
+ Q_OBJECT
+
+ public:
+ InfoTab(QWidget *parent = 0);
+ };
+
+/**
+ * @brief Class containing the translator tab of about dialog
+ *
+ */
+class TranslatorsTab : public QWidget
+ {
+ Q_OBJECT
+
+ public:
+ TranslatorsTab(QWidget *parent = 0);
+ };
+
+ /**
+ * @brief Class for handling the about dialog
+ *
+ */
+class AboutDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ AboutDialog(QWidget *parent = 0);
+};
+
+#endif // __ABOUTDIALOG_H__
+
diff --git a/src/attachments.cpp b/src/attachments.cpp
new file mode 100644
index 0000000..1110464
--- /dev/null
+++ b/src/attachments.cpp
@@ -0,0 +1,183 @@
+/*
+ * attachments.cpp
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+/* TODO:
+ * - check content encoding (base64 / quoted-printable) and apply appropriate opperation (maybe already in mime.cpp)
+ * - check memory usage, use less copy operations / more references
+ * - possibility to clear attachment-view , e.g. with decryption or encrypting a new message
+ * - save all: like in thunderbird, one folder, all files go there
+ */
+
+/*
+ * - save, delete (clear) all
+ * - each line save & clear button
+ * - attached files to view-menu
+ * - also an open button, whichs should save file to tmp-folder, and open with correct app (via QDesktopServices)
+ */
+
+
+#include "attachments.h"
+
+Attachments::Attachments(QWidget *parent)
+ : QWidget(parent)
+{
+ table = new AttachmentTableModel(this);
+
+ tableView = new QTableView;
+ tableView->setModel(table);
+ tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
+ // only one entry should be selected at time
+ tableView->setSelectionMode(QAbstractItemView::SingleSelection);
+ tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ tableView->setFocusPolicy(Qt::NoFocus);
+ tableView->setAlternatingRowColors(true);
+ tableView->verticalHeader()->hide();
+ tableView->setShowGrid(false);
+ tableView->setColumnWidth(0, 300);
+ tableView->horizontalHeader()->setStretchLastSection(true);
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(tableView);
+ layout->setContentsMargins(0,0,0,0);
+ setLayout(layout);
+ createActions();
+
+}
+
+void Attachments::contextMenuEvent(QContextMenuEvent *event)
+{
+ QMenu menu(this);
+ menu.addAction(saveFileAct);
+ // enable open with only if allowed by user
+ if(settings.value("mime/openAttachment").toBool())
+ menu.addAction(openFileAct);
+
+ menu.exec(event->globalPos());
+}
+
+void Attachments::createActions()
+{
+ saveFileAct = new QAction(tr("Save File"), this);
+ saveFileAct->setToolTip(tr("Save this file"));
+ saveFileAct->setIcon(QIcon(":filesave.png"));
+ connect(saveFileAct, SIGNAL(triggered()), this, SLOT(slotSaveFile()));
+
+ openFileAct = new QAction(tr("Open File"), this);
+ openFileAct->setToolTip(tr("Open this file"));
+ openFileAct->setIcon(QIcon(":fileopen.png"));
+ connect(openFileAct, SIGNAL(triggered()), this, SLOT(slotOpenFile()));
+
+}
+
+void Attachments::slotSaveFile()
+{
+
+ QModelIndexList indexes = tableView->selectionModel()->selection().indexes();
+
+ if (indexes.size() < 1) {
+ return;
+ }
+
+ // only singe-selection possible now: TODO: foreach
+ MimePart mp = table->getMimePart(indexes.at(0).row());
+ QString filename = mp.header.getParam("Content-Type", "name");
+ // TODO: find out why filename is quoted
+ filename.chop(1);
+ filename.remove(0, 1);
+ // TODO: check if really base64
+ saveByteArrayToFile(QByteArray::fromBase64(mp.body), filename);
+
+}
+
+void Attachments::saveByteArrayToFile(QByteArray outBuffer, QString filename)
+{
+
+ //QString path="";
+ QString path = filename;
+ QString outfileName = QFileDialog::getSaveFileName(this, tr("Save File"), path);
+
+ if (outfileName.isEmpty()) return;
+
+ QFile outfile(outfileName);
+ if (!outfile.open(QFile::WriteOnly)) {
+ QMessageBox::warning(this, tr("File"),
+ tr("Cannot write file %1:\n%2.")
+ .arg(outfileName)
+ .arg(outfile.errorString()));
+ return;
+ }
+
+ QDataStream out(&outfile);
+ out.writeRawData(outBuffer.data(), outBuffer.length());
+ outfile.close();
+}
+
+/**
+ * WIP: TODO:
+ * - create attachments dir if not existing
+ * - ask for cleanup of dir on exit
+ * - remove code-duplication with saveByteArrayToFile
+ */
+void Attachments::slotOpenFile() {
+
+ // TODO: make attachmentdir constant or configurable
+ QString attachmentDir = qApp->applicationDirPath() + "/attachments/";
+ //QDir p = QDir(qApp->applicationDirPath() + "/attachments/");
+ if(!QDir(attachmentDir).exists()) {
+ QDir().mkpath(attachmentDir);
+ }
+
+ QModelIndexList indexes = tableView->selectionModel()->selection().indexes();
+ MimePart mp = table->getMimePart(indexes.at(0).row());
+
+// qDebug() << "mime: " << mp.header.getValue("Content-Type");
+
+ QString filename = mp.header.getParam("Content-Type", "name");
+ // TODO: find out why filename is quoted
+// qDebug() << "file: " << filename;
+ filename.chop(1);
+ filename.remove(0, 1);
+ filename.prepend(attachmentDir);
+
+ // qDebug() << "file: " << filename;
+ QByteArray outBuffer = QByteArray::fromBase64(mp.body);
+
+
+ QFile outfile(filename);
+ if (!outfile.open(QFile::WriteOnly)) {
+ QMessageBox::warning(this, tr("File"),
+ tr("Cannot write file %1:\n%2.")
+ .arg(filename)
+ .arg(outfile.errorString()));
+ return;
+ }
+
+ QDataStream out(&outfile);
+ out.writeRawData(outBuffer.data(), outBuffer.length());
+ outfile.close();
+ QDesktopServices::openUrl(QUrl("file://"+filename, QUrl::TolerantMode));
+}
+
+void Attachments::addMimePart(MimePart *mp)
+{
+ table->add(*mp);
+}
+
diff --git a/src/attachments.h b/src/attachments.h
new file mode 100644
index 0000000..5d72d9e
--- /dev/null
+++ b/src/attachments.h
@@ -0,0 +1,68 @@
+/*
+ * attachments.h
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef __ATTACHMENTS_H__
+#define __ATTACHMENTS_H__
+
+#include "attachmenttablemodel.h"
+#include <QtGui>
+#include <QWidget>
+
+QT_BEGIN_NAMESPACE
+class QTableView;
+class QHeaderView;
+class QVBoxLayout;
+class QMenu;
+class QMessageBox;
+class QContextMenuEvent;
+class QFileDialog;
+class QUrl;
+class QDesktopServices;
+class QSettings;
+class QApplication;
+QT_END_NAMESPACE
+
+class Attachments : public QWidget
+{
+ Q_OBJECT
+
+public slots:
+ void slotSaveFile();
+ void slotOpenFile();
+
+public:
+ Attachments(QWidget *parent = 0);
+ void addMimePart(MimePart *mp);
+
+private:
+ void createActions();
+ void saveByteArrayToFile(QByteArray outBuffer, QString filename);
+ QAction *saveFileAct;
+ QAction *openFileAct;
+ AttachmentTableModel *table;
+ QTableView *tableView;
+ QSettings settings;
+
+protected:
+ void contextMenuEvent(QContextMenuEvent *event);
+};
+
+#endif // __ATTACHMENTS_H__
diff --git a/src/attachmenttablemodel.cpp b/src/attachmenttablemodel.cpp
new file mode 100644
index 0000000..f0eadfc
--- /dev/null
+++ b/src/attachmenttablemodel.cpp
@@ -0,0 +1,138 @@
+/*
+ * attachmenttablemodel.cpp
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "attachmenttablemodel.h"
+
+/** compare with http://doc.qt.nokia.com/4.6/itemviews-addressbook.html
+ */
+
+AttachmentTableModel::AttachmentTableModel(QObject *parent) :
+ QAbstractTableModel(parent)
+{
+}
+
+AttachmentTableModel::AttachmentTableModel(QList<MimePart> mimeparts, QObject *parent) :
+ QAbstractTableModel(parent)
+{
+ listOfMimeparts = mimeparts;
+}
+
+
+void AttachmentTableModel::add(MimePart mp)
+{
+ listOfMimeparts.append(mp);
+ //QModelIndex changedIndex0 = createIndex(listOfMimeparts.size(), 0);
+ //QModelIndex changedIndex1 = createIndex(listOfMimeparts.size(), 1);
+
+ //emit(dataChanged(changedIndex0, changedIndex1));
+ // TODO: check the data-changed signal
+ reset();
+}
+
+MimePart AttachmentTableModel::getSelectedMimePart(QModelIndex index)
+{
+ return listOfMimeparts.at(index.row());
+}
+
+MimePart AttachmentTableModel::getMimePart(int index)
+{
+ return listOfMimeparts.at(index);
+}
+
+/*QList<MimePart> AttachmentTableModel::getSelectedMimeParts(QModelIndexList indexes){
+
+ foreach(QModelIndex index, indexes) {
+ qDebug() << "ir: "<< index.row();
+ }
+
+}*/
+
+int AttachmentTableModel::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+ return listOfMimeparts.size();
+}
+
+int AttachmentTableModel::columnCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+ return 2;
+}
+
+QVariant AttachmentTableModel::data(const QModelIndex &index, int role) const
+{
+
+ //qDebug() << "called, index: " << index.column();
+
+ if (!index.isValid())
+ return QVariant();
+
+ if (index.row() >= listOfMimeparts.size() || index.row() < 0)
+ return QVariant();
+
+ if (role == Qt::DisplayRole) {
+ MimePart mp = listOfMimeparts.at(index.row());
+
+ if (index.column() == 0)
+ return mp.header.getParam("Content-Type", "name");
+ if (index.column() == 1)
+ return mp.header.getValue("Content-Type");
+
+ }
+
+ // set icon
+ // TODO more generic matching, e.g. for audio
+ if (role == Qt::DecorationRole && index.column() == 0) {
+ MimePart mp = listOfMimeparts.at(index.row());
+ QString icon;
+ if (mp.header.getValue("Content-Type").startsWith("image")) {
+ icon = ":mimetypes/image-x-generic.png";
+ } else {
+ icon = mp.header.getValue("Content-Type").replace("/", "-");
+ icon = ":mimetypes/" + icon + ".png";
+ }
+ if (!QFile::exists(icon)) icon = ":mimetypes/unknown.png";
+ return QIcon(icon);
+ }
+
+ return QVariant();
+}
+
+QVariant AttachmentTableModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ //qDebug() << "called, section: " << section;
+ if (role != Qt::DisplayRole)
+ return QVariant();
+
+ if (orientation == Qt::Horizontal) {
+ switch (section) {
+ case 0:
+ return tr("Filename");
+
+ case 1:
+ return tr("Contenttype");
+
+ default:
+ return QVariant();
+ }
+ }
+ return QVariant();
+}
diff --git a/src/attachmenttablemodel.h b/src/attachmenttablemodel.h
new file mode 100644
index 0000000..bb019de
--- /dev/null
+++ b/src/attachmenttablemodel.h
@@ -0,0 +1,56 @@
+/*
+ * attachmenttablemodel.h
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef __ATTACHMENTTABLEMODEL_H__
+#define __ATTACHMENTTABLEMODEL_H__
+
+#include "mime.h"
+#include <QIcon>
+#include <QFile>
+#include <QAbstractTableModel>
+
+QT_BEGIN_NAMESPACE
+class QStandardItem;
+QT_END_NAMESPACE
+
+class AttachmentTableModel : public QAbstractTableModel
+{
+ Q_OBJECT
+
+public:
+ AttachmentTableModel(QObject *parent = 0);
+ AttachmentTableModel(QList<MimePart> mimeparts, QObject *parent = 0);
+
+ int rowCount(const QModelIndex &parent) const;
+ int columnCount(const QModelIndex &parent) const;
+ QVariant data(const QModelIndex &index, int role) const;
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const;
+
+ void add(MimePart mp);
+ MimePart getSelectedMimePart(QModelIndex index);
+ MimePart getMimePart(int index);
+ //QList<MimePart> getSelectedMimeParts(QModelIndexList indexes);
+
+private:
+ QList<MimePart> listOfMimeparts;
+};
+
+#endif // __ATTACHMENTTABLEMODEL_H__
diff --git a/src/editorpage.cpp b/src/editorpage.cpp
new file mode 100644
index 0000000..28926a9
--- /dev/null
+++ b/src/editorpage.cpp
@@ -0,0 +1,108 @@
+/*
+ * textpage.cpp
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "editorpage.h"
+
+EditorPage::EditorPage(const QString &filePath, QWidget *parent) : QWidget(parent),
+ fullFilePath(filePath)
+{
+ // Set the Textedit properties
+ textPage = new QTextEdit();
+ textPage->setAcceptRichText(false);
+
+ // Set the layout style
+ mainLayout = new QVBoxLayout();
+ mainLayout->setSpacing(0);
+ mainLayout->addWidget(textPage);
+ mainLayout->setContentsMargins(0,0,0,0);
+ setLayout(mainLayout);
+
+ setAttribute(Qt::WA_DeleteOnClose);
+ textPage->setFocus();
+
+ //connect(textPage, SIGNAL(textChanged()), this, SLOT(formatGpgHeader()));
+}
+
+const QString& EditorPage::getFilePath() const
+{
+ return fullFilePath;
+}
+
+QTextEdit* EditorPage::getTextPage()
+{
+ return textPage;
+}
+
+void EditorPage::setFilePath(const QString &filePath)
+{
+ fullFilePath = filePath;
+}
+
+void EditorPage::showNotificationWidget(QWidget *widget, const char *className)
+{
+ widget->setProperty(className,true);
+ mainLayout->addWidget(widget);
+}
+
+void EditorPage::closeNoteByClass(const char *className)
+{
+ QList<QWidget *> widgets = findChildren<QWidget *>();
+ foreach(QWidget * widget, widgets)
+ {
+ if (widget->property(className) == true) {
+ widget->close();
+ }
+ }
+}
+
+void EditorPage::slotFormatGpgHeader() {
+
+ QString content = textPage->toPlainText();
+
+ // Get positions of the gpg-headers, if they exist
+ int start = content.indexOf(GpgConstants::PGP_SIGNED_BEGIN);
+ int startSig = content.indexOf(GpgConstants::PGP_SIGNATURE_BEGIN);
+ int endSig = content.indexOf(GpgConstants::PGP_SIGNATURE_END);
+
+ if(start < 0 || startSig < 0 || endSig < 0 || signMarked) {
+ return;
+ }
+
+ signMarked = true;
+
+ // Set the fontstyle for the header
+ QTextCharFormat signFormat;
+ signFormat.setForeground(QBrush(QColor::fromRgb(80,80,80)));
+ signFormat.setFontPointSize(9);
+
+ // set font style for the signature
+ QTextCursor cursor(textPage->document());
+ cursor.setPosition(startSig, QTextCursor::MoveAnchor);
+ cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, endSig);
+ cursor.setCharFormat(signFormat);
+
+ // set the font style for the header
+ int headEnd = content.indexOf("\n\n", start);
+ cursor.setPosition(start, QTextCursor::MoveAnchor);
+ cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, headEnd);
+ cursor.setCharFormat(signFormat);
+
+}
diff --git a/src/editorpage.h b/src/editorpage.h
new file mode 100644
index 0000000..d5222cf
--- /dev/null
+++ b/src/editorpage.h
@@ -0,0 +1,101 @@
+/*
+ * textpage.h
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef __EDITORPAGE_H__
+#define __EDITORPAGE_H__
+
+#include "gpgconstants.h"
+#include <QTextEdit>
+#include <QtGui>
+
+QT_BEGIN_NAMESPACE
+class QVBoxLayout;
+class QHBoxLayout;
+class QString;
+class QLabel;
+QT_END_NAMESPACE
+
+/**
+ * @brief Class for handling a single tab of the tabwidget
+ *
+ */
+class EditorPage : public QWidget
+{
+ Q_OBJECT
+
+public:
+ /**
+ * @details Add layout and add plaintextedit
+ *
+ * @param filePath Path of the file handled in this tab
+ * @param parent Pointer to the parent widget
+ */
+ EditorPage(const QString &filePath = "", QWidget *parent = 0);
+
+ /**
+ * @details Get the filepath of the currently activated tab.
+ */
+ const QString& getFilePath() const;
+
+ /**
+ * @details Set filepath of currently activated tab.
+ *
+ * @param filePath The path to be set
+ */
+ void setFilePath(const QString &filePath);
+
+ /**
+ * @details Return pointer tp the textedit of the currently activated tab.
+ */
+ QTextEdit *getTextPage();
+
+ /**
+ * @details Show additional widget at buttom of currently active tab
+ *
+ * @param widget The widget to be added
+ * @param className The name to handle the added widget
+ */
+ void showNotificationWidget(QWidget *widget, const char *className);
+
+ /**
+ * @details Hide all widgets with the given className
+ *
+ * @param className The classname of the widgets to hide
+ */
+ void closeNoteByClass(const char *className);
+
+private:
+ QTextEdit *textPage; /** The textedit of the tab */
+ QVBoxLayout *mainLayout; /** The layout for the tab */
+ QWidget *notificationWidget; /** The notification widget shown at the buttom of the tab */
+ QMenu *verifyMenu; /** The menu in the notifiaction widget */
+ QString fullFilePath; /** The path to the file handled in the tab */
+ QLabel *verifyLabel; /** The label of the verify-notification widget */
+ bool signMarked; /** true, if the signed header is marked, false if not */
+
+private slots:
+ /**
+ * @details Format the gpg header in another font-style
+ */
+ void slotFormatGpgHeader();
+};
+
+#endif // __TEXTPAGE_H__
diff --git a/src/fileencryptiondialog.cpp b/src/fileencryptiondialog.cpp
new file mode 100755
index 0000000..38b7de5
--- /dev/null
+++ b/src/fileencryptiondialog.cpp
@@ -0,0 +1,249 @@
+/*
+ * fileencryptiondialog.cpp
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "fileencryptiondialog.h"
+
+FileEncryptionDialog::FileEncryptionDialog(GpgME::GpgContext *ctx, QStringList keyList, DialogAction action, QWidget *parent)
+ : QDialog(parent)
+
+{
+ mAction = action;
+ mCtx = ctx;
+ if (mAction == Decrypt) {
+ setWindowTitle(tr("Decrypt File"));
+ resize(500, 200);
+ } else if (mAction == Encrypt) {
+ setWindowTitle(tr("Encrypt File"));
+ resize(500, 400);
+ } else if (mAction == Sign) {
+ setWindowTitle(tr("Sign File"));
+ resize(500, 400);
+ } else if (mAction == Verify) {
+ setWindowTitle(tr("Verify File"));
+ resize(500, 200);
+ }
+
+ setModal(true);
+
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+ connect(buttonBox, SIGNAL(accepted()), this, SLOT(slotExecuteAction()));
+ connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+
+ QGroupBox *groupBox1 = new QGroupBox(tr("File"));
+
+ /* Setup input & Outputfileselection*/
+ inputFileEdit = new QLineEdit();
+ QPushButton *fb1 = new QPushButton("...");
+ connect(fb1, SIGNAL(clicked()), this, SLOT(slotSelectInputFile()));
+ QLabel *fl1 = new QLabel(tr("Input"));
+ fl1->setBuddy(inputFileEdit);
+
+ outputFileEdit = new QLineEdit();
+ QPushButton *fb2 = new QPushButton("...");
+ connect(fb2, SIGNAL(clicked()), this, SLOT(slotSelectOutputFile()));
+ QLabel *fl2 = new QLabel(tr("Output"));
+ fl2->setBuddy(outputFileEdit);
+
+ QGridLayout *gLayout = new QGridLayout();
+ gLayout->addWidget(fl1, 0, 0);
+ gLayout->addWidget(inputFileEdit, 0, 1);
+ gLayout->addWidget(fb1, 0, 2);
+ signFileEdit = new QLineEdit();
+ // verify does not need outfile, but signature file
+ if(mAction != Verify) {
+ gLayout->addWidget(fl2, 1, 0);
+ gLayout->addWidget(outputFileEdit, 1, 1);
+ gLayout->addWidget(fb2, 1, 2);
+ } else {
+ QPushButton *sfb1 = new QPushButton("...");
+ connect(sfb1, SIGNAL(clicked()), this, SLOT(slotSelectSignFile()));
+ QLabel *sfl1 = new QLabel(tr("Signature"));
+ sfl1->setBuddy(signFileEdit);
+
+ gLayout->addWidget(sfl1, 1, 0);
+ gLayout->addWidget(signFileEdit, 1, 1);
+ gLayout->addWidget(sfb1, 1, 2);
+ }
+ groupBox1->setLayout(gLayout);
+
+ /*Setup KeyList*/
+ mKeyList = new KeyList(mCtx);
+ mKeyList->hide();
+ mKeyList->setColumnWidth(2, 150);
+ mKeyList->setColumnWidth(3, 150);
+ mKeyList->setChecked(&keyList);
+
+ statusLabel = new QLabel();
+ statusLabel->setStyleSheet("QLabel {color: red;}");
+
+ QVBoxLayout *vbox2 = new QVBoxLayout();
+ vbox2->addWidget(groupBox1);
+ vbox2->addWidget(mKeyList);
+ vbox2->addWidget(statusLabel);
+ vbox2->addWidget(buttonBox);
+ vbox2->addStretch(0);
+ setLayout(vbox2);
+
+ if(action == Encrypt || action == Sign) {
+ slotShowKeyList();
+ }
+
+ exec();
+}
+
+void FileEncryptionDialog::slotSelectInputFile()
+{
+ QString path = "";
+ if (inputFileEdit->text().size() > 0) {
+ path = QFileInfo(inputFileEdit->text()).absolutePath();
+ }
+
+// QString infileName = QFileDialog::getOpenFileName(this, tr("Open File"), path, tr("Files") + tr("All Files (*)"));
+ QString infileName = QFileDialog::getOpenFileName(this, tr("Open File"), path);
+ inputFileEdit->setText(infileName);
+
+ // try to find a matching output-filename, if not yet done
+ if (infileName > 0
+ && outputFileEdit->text().size() == 0
+ && signFileEdit->text().size() == 0) {
+ if (mAction == Encrypt) {
+ outputFileEdit->setText(infileName + ".asc");
+ } else if (mAction == Sign) {
+ outputFileEdit->setText(infileName + ".sig");
+ } else if (mAction == Verify) {
+ signFileEdit->setText(infileName + ".sig");
+ } else {
+ if (infileName.endsWith(".asc", Qt::CaseInsensitive)) {
+ QString ofn = infileName;
+ ofn.chop(4);
+ outputFileEdit->setText(ofn);
+ } else {
+ outputFileEdit->setText(infileName + ".out");
+ }
+ }
+ }
+}
+
+void FileEncryptionDialog::slotSelectOutputFile()
+{
+ QString path = "";
+ if (outputFileEdit->text().size() > 0) {
+ path = QFileInfo(outputFileEdit->text()).absolutePath();
+ }
+
+ QString outfileName = QFileDialog::getSaveFileName(this, tr("Save File"),path, NULL ,NULL ,QFileDialog::DontConfirmOverwrite);
+ outputFileEdit->setText(outfileName);
+
+}
+
+void FileEncryptionDialog::slotSelectSignFile()
+{
+ QString path = "";
+ if (signFileEdit->text().size() > 0) {
+ path = QFileInfo(signFileEdit->text()).absolutePath();
+ }
+
+ QString signfileName = QFileDialog::getSaveFileName(this, tr("Open File"),path, NULL ,NULL ,QFileDialog::DontConfirmOverwrite);
+ signFileEdit->setText(signfileName);
+
+ if (inputFileEdit->text().size() == 0 && signfileName.endsWith(".sig", Qt::CaseInsensitive)) {
+ QString sfn = signfileName;
+ sfn.chop(4);
+ inputFileEdit->setText(sfn);
+ }
+
+}
+
+void FileEncryptionDialog::slotExecuteAction()
+{
+
+ QFile infile;
+ infile.setFileName(inputFileEdit->text());
+ if (!infile.open(QIODevice::ReadOnly)) {
+ statusLabel->setText( tr("Couldn't open file"));
+ inputFileEdit->setStyleSheet("QLineEdit { background: yellow }");
+ return;
+ }
+
+ QByteArray inBuffer = infile.readAll();
+ QByteArray *outBuffer = new QByteArray();
+ infile.close();
+ if ( mAction == Encrypt ) {
+ if (! mCtx->encrypt(mKeyList->getChecked(), inBuffer, outBuffer)) return;
+ }
+
+ if ( mAction == Decrypt ) {
+ if (! mCtx->decrypt(inBuffer, outBuffer)) return;
+ }
+
+ if( mAction == Sign ) {
+ if(! mCtx->sign(mKeyList->getChecked(), inBuffer, outBuffer, true)) return;
+ }
+
+ if( mAction == Verify ) {
+ QFile signfile;
+ signfile.setFileName(signFileEdit->text());
+ if (!signfile.open(QIODevice::ReadOnly)) {
+ statusLabel->setText( tr("Couldn't open file"));
+ signFileEdit->setStyleSheet("QLineEdit { background: yellow }");
+ return;
+ }
+ QByteArray signBuffer = signfile.readAll();
+ new VerifyDetailsDialog(this, mCtx, mKeyList, &inBuffer, &signBuffer);
+ return;
+ }
+
+ QFile outfile(outputFileEdit->text());
+ if (outfile.exists()){
+ QMessageBox::StandardButton ret;
+ ret = QMessageBox::warning(this, tr("File"),
+ tr("File exists! Do you want to overwrite it?"),
+ QMessageBox::Ok|QMessageBox::Cancel);
+ if (ret == QMessageBox::Cancel){
+ return;
+ }
+ }
+
+ if (!outfile.open(QFile::WriteOnly)) {
+ QMessageBox::warning(this, tr("File"),
+ tr("Cannot write file %1:\n%2.")
+ .arg(outputFileEdit->text())
+ .arg(outfile.errorString()));
+ return;
+ }
+
+ QDataStream out(&outfile);
+ out.writeRawData(outBuffer->data(), outBuffer->length());
+ outfile.close();
+ QMessageBox::information(0, "Done", "Output saved to " + outputFileEdit->text());
+
+ accept();
+}
+
+void FileEncryptionDialog::slotShowKeyList()
+{
+ mKeyList->show();
+}
+
+void FileEncryptionDialog::slotHideKeyList()
+{
+ mKeyList->hide();
+}
diff --git a/src/fileencryptiondialog.h b/src/fileencryptiondialog.h
new file mode 100755
index 0000000..af6edff
--- /dev/null
+++ b/src/fileencryptiondialog.h
@@ -0,0 +1,118 @@
+/*
+ * fileencryptiondialog.h
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef __FILEENCRYPTIONDIALOG_H__
+#define __FILEENCRYPTIONDIALOG_H__
+
+#include "gpgcontext.h"
+#include "keylist.h"
+#include "verifydetailsdialog.h"
+
+QT_BEGIN_NAMESPACE
+class QDialog;
+class QLineEdit;
+class QWidget;
+class QDialogButtonBox;
+class QLabel;
+class QPushButton;
+class QHBoxLayout;
+class QVBoxLayout;
+class QDebug;
+class QFileDialog;
+QT_END_NAMESPACE
+
+/**
+ * @brief
+ *
+ * @class FileEncryptionDialog fileencryptiondialog.h "fileencryptiondialog.h"
+ */
+class FileEncryptionDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+
+ enum DialogAction {
+ Encrypt,
+ Decrypt,
+ Sign,
+ Verify
+ };
+
+ /**
+ * @brief
+ *
+ * @fn FileEncryptionDialog
+ * @param ctx
+ * @param keyList
+ * @param parent
+ */
+ FileEncryptionDialog(GpgME::GpgContext *ctx, QStringList keyList, DialogAction action, QWidget *parent = 0);
+public slots:
+ /**
+ * @details
+ *
+ * @fn selectInputFile
+ */
+ void slotSelectInputFile();
+ /**
+ * @brief
+ *
+ * @fn selectOutputFile
+ */
+ void slotSelectOutputFile();
+ /**
+ * @brief
+ *
+ * @fn selectSignFile
+ */
+ void slotSelectSignFile();
+ /**
+ * @brief
+ *
+ * @fn executeAction
+ */
+ void slotExecuteAction();
+ /**
+ * @brief
+ *
+ * @fn hideKeyList
+ */
+ void slotHideKeyList();
+ /**
+ * @brief
+ *
+ * @fn showKeyList
+ */
+ void slotShowKeyList();
+
+private:
+ QLineEdit *outputFileEdit; /**< TODO */
+ QLineEdit *inputFileEdit; /**< TODO */
+ QLineEdit *signFileEdit; /**< TODO */
+ DialogAction mAction; /**< TODO */
+ QLabel *statusLabel; /**< TODO */
+protected:
+ GpgME::GpgContext *mCtx; /**< TODO */
+ KeyList *mKeyList; /**< TODO */
+
+};
+#endif // __FILEENCRYPTIONDIALOG_H__
diff --git a/src/findwidget.cpp b/src/findwidget.cpp
new file mode 100644
index 0000000..ff8de5a
--- /dev/null
+++ b/src/findwidget.cpp
@@ -0,0 +1,135 @@
+
+#include "findwidget.h"
+
+FindWidget::FindWidget(QWidget *parent, QTextEdit *edit) :
+ QWidget(parent)
+{
+ mTextpage = edit;
+ findEdit = new QLineEdit(this);
+ QPushButton *closeButton= new QPushButton(this->style()->standardIcon(QStyle::SP_TitleBarCloseButton),"",this);
+ QPushButton *nextButton= new QPushButton(QIcon(":button_next.png"), "");
+ QPushButton *previousButton= new QPushButton(QIcon(":button_previous.png"), "");
+
+ QHBoxLayout *notificationWidgetLayout = new QHBoxLayout(this);
+ notificationWidgetLayout->setContentsMargins(10,0,0,0);
+ notificationWidgetLayout->addWidget(new QLabel(tr("Find:")));
+ notificationWidgetLayout->addWidget(findEdit,2);
+ notificationWidgetLayout->addWidget(nextButton);
+ notificationWidgetLayout->addWidget(previousButton);
+ notificationWidgetLayout->addWidget(closeButton);
+
+ this->setLayout(notificationWidgetLayout);
+ connect(findEdit,SIGNAL(textEdited(QString)),this,SLOT(slotFind()));
+ connect(findEdit,SIGNAL(returnPressed()),this,SLOT(slotFindNext()));
+ connect(nextButton,SIGNAL(clicked()),this,SLOT(slotFindNext()));
+ connect(previousButton,SIGNAL(clicked()),this,SLOT(slotFindPrevious()));
+ connect(closeButton,SIGNAL(clicked()),this,SLOT(slotClose()));
+
+ // The timer is necessary for setting the focus
+ QTimer::singleShot(0, findEdit, SLOT(setFocus()));
+}
+
+void FindWidget::setBackground()
+{
+ QTextCursor cursor = mTextpage->textCursor();
+ // if match is found set background of QLineEdit to white, otherwise to red
+ QPalette bgPalette( findEdit->palette() );
+
+ if (!findEdit->text().isEmpty() && mTextpage->document()->find(findEdit->text()).position() < 0 ) {
+ bgPalette.setColor( QPalette::Base, "#ececba");
+ } else {
+ bgPalette.setColor( QPalette::Base, Qt::white);
+ }
+ findEdit->setPalette(bgPalette);
+}
+
+void FindWidget::slotFindNext()
+{
+ QTextCursor cursor = mTextpage->textCursor();
+ cursor = mTextpage->document()->find(findEdit->text(), cursor, QTextDocument::FindCaseSensitively);
+
+ // if end of document is reached, restart search from beginning
+ if (cursor.position() == -1) {
+ cursor = mTextpage->document()->find(findEdit->text(), cursor, QTextDocument::FindCaseSensitively);
+ }
+
+ // cursor should not stay at -1, otherwise text is not editable
+ // todo: check how gedit handles this
+ if(cursor.position() != -1) {
+ mTextpage->setTextCursor(cursor);
+ }
+ this->setBackground();
+}
+
+void FindWidget::slotFind()
+{
+ QTextCursor cursor = mTextpage->textCursor();
+
+ if (cursor.anchor() == -1) {
+ cursor = mTextpage->document()->find(findEdit->text(), cursor, QTextDocument::FindCaseSensitively);
+ } else {
+ cursor = mTextpage->document()->find(findEdit->text(), cursor.anchor(), QTextDocument::FindCaseSensitively);
+ }
+
+ // if end of document is reached, restart search from beginning
+ if (cursor.position() == -1) {
+ cursor = mTextpage->document()->find(findEdit->text(), cursor, QTextDocument::FindCaseSensitively);
+ }
+
+ // cursor should not stay at -1, otherwise text is not editable
+ // todo: check how gedit handles this
+ if(cursor.position() != -1) {
+ mTextpage->setTextCursor(cursor);
+ }
+ this->setBackground();
+}
+
+void FindWidget::slotFindPrevious()
+{
+ QTextDocument::FindFlags flags;
+ flags |= QTextDocument::FindBackward;
+ flags |= QTextDocument::FindCaseSensitively;
+
+ QTextCursor cursor = mTextpage->textCursor();
+ cursor = mTextpage->document()->find(findEdit->text(), cursor, flags);
+
+ // if begin of document is reached, restart search from end
+ if (cursor.position() == -1) {
+ cursor = mTextpage->document()->find(findEdit->text(), QTextCursor::End, flags);
+ }
+
+ // cursor should not stay at -1, otherwise text is not editable
+ // todo: check how gedit handles this
+ if(cursor.position() != -1) {
+ mTextpage->setTextCursor(cursor);
+ }
+ this->setBackground();
+}
+
+void FindWidget::keyPressEvent( QKeyEvent* e )
+{
+ switch ( e->key() )
+ {
+ case Qt::Key_Escape:
+ this->slotClose();
+ break;
+ case Qt::Key_F3:
+ if (e->modifiers() & Qt::ShiftModifier) {
+ this->slotFindPrevious();
+ } else {
+ this->slotFindNext();
+ }
+ break;
+ }
+}
+
+void FindWidget::slotClose() {
+ QTextCursor cursor = mTextpage->textCursor();
+
+ if ( cursor.position() == -1) {
+ cursor.setPosition(0);
+ mTextpage->setTextCursor(cursor);
+ }
+ mTextpage->setFocus();
+ close();
+}
diff --git a/src/findwidget.h b/src/findwidget.h
new file mode 100644
index 0000000..4e69fa6
--- /dev/null
+++ b/src/findwidget.h
@@ -0,0 +1,42 @@
+
+#ifndef FINDWIDGET_H
+#define FINDWIDGET_H
+
+#include "editorpage.h"
+
+#include <QWidget>
+
+/**
+ * @brief Class for handling the find widget shown at buttom of a textedit-page
+ */
+class FindWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ /**
+ * @brief
+ *
+ * @param parent The parent widget
+ */
+ explicit FindWidget(QWidget *parent, QTextEdit *edit);
+
+private:
+ void keyPressEvent( QKeyEvent* e );
+ /**
+ * @details Set background of findEdit to red, if no match is found (Documents textcursor position equals -1),
+ * otherwise set it to white.
+ */
+ void setBackground();
+
+ QTextEdit *mTextpage; /** Textedit associated to the notification */
+ QLineEdit *findEdit; /** Label holding the text shown in verifyNotification */
+ QTextCharFormat cursorFormat;
+
+private slots:
+ void slotFindNext();
+ void slotFindPrevious();
+ void slotFind();
+ void slotClose();
+};
+#endif // FINDWIDGET_H
diff --git a/src/gpgconstants.cpp b/src/gpgconstants.cpp
new file mode 100644
index 0000000..0d3306a
--- /dev/null
+++ b/src/gpgconstants.cpp
@@ -0,0 +1,31 @@
+/*
+ * gpgconstants.cpp
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "gpgconstants.h"
+#include <QString>
+
+const char* GpgConstants::PGP_CRYPT_BEGIN = "-----BEGIN PGP MESSAGE-----";
+const char* GpgConstants::PGP_CRYPT_END = "-----END PGP MESSAGE-----";
+const char* GpgConstants::PGP_SIGNED_BEGIN = "-----BEGIN PGP SIGNED MESSAGE-----";
+const char* GpgConstants::PGP_SIGNED_END = "-----END PGP SIGNATURE-----";
+const char* GpgConstants::PGP_SIGNATURE_BEGIN = "-----BEGIN PGP SIGNATURE-----";
+const char* GpgConstants::PGP_SIGNATURE_END = "-----END PGP SIGNATURE-----";
+
diff --git a/src/gpgconstants.h b/src/gpgconstants.h
new file mode 100644
index 0000000..e01083c
--- /dev/null
+++ b/src/gpgconstants.h
@@ -0,0 +1,40 @@
+/*
+ * gpgconstants.h
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef GPGCONSTANTS_H
+#define GPGCONSTANTS_H
+
+class QString;
+
+const int RESTART_CODE = 1000;
+
+class GpgConstants
+{
+public:
+ static const char* PGP_CRYPT_BEGIN;
+ static const char* PGP_CRYPT_END;
+ static const char* PGP_SIGNED_BEGIN;
+ static const char* PGP_SIGNED_END;
+ static const char* PGP_SIGNATURE_BEGIN;
+ static const char* PGP_SIGNATURE_END;
+};
+
+#endif // GPGCONSTANTS_H
diff --git a/src/gpgcontext.cpp b/src/gpgcontext.cpp
new file mode 100644
index 0000000..45e053b
--- /dev/null
+++ b/src/gpgcontext.cpp
@@ -0,0 +1,835 @@
+/*
+ * gpgcontext.cpp
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "gpgcontext.h"
+#include <unistd.h> /* contains read/write */
+#ifdef _WIN32
+#include <windows.h>
+#endif
+namespace GpgME
+{
+
+/** Constructor
+ * Set up gpgme-context, set paths to app-run path
+ */
+GpgContext::GpgContext()
+{
+ /** get application path */
+ QString appPath = qApp->applicationDirPath();
+
+ /** The function `gpgme_check_version' must be called before any other
+ * function in the library, because it initializes the thread support
+ * subsystem in GPGME. (from the info page) */
+ gpgme_check_version(NULL);
+
+ // TODO: Set gpgme_language to config
+ /*QSettings settings;
+ qDebug() << " - " << settings.value("int/lang").toLocale().name();
+ qDebug() << " - " << QLocale(settings.value("int/lang").toString()).name();*/
+
+ // the locale set here is used for the other setlocale calls which have NULL
+ // -> NULL means use default, which is configured here
+ setlocale(LC_ALL, "");
+
+ /** set locale, because tests do also */
+ gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL));
+ //qDebug() << "Locale set to" << LC_CTYPE << " - " << setlocale(LC_CTYPE, NULL);
+#ifndef _WIN32
+ gpgme_set_locale(NULL, LC_MESSAGES, setlocale(LC_MESSAGES, NULL));
+#endif
+
+ err = gpgme_new(&mCtx);
+
+ checkErr(err);
+ /** here come the settings, instead of /usr/bin/gpg
+ * a executable in the same path as app is used.
+ * also lin/win must be checked, for calling gpg.exe if needed
+ */
+#ifdef _WIN32
+ gpgBin = appPath + "/bin/gpg.exe";
+#else
+ gpgBin = appPath + "/bin/gpg";
+#endif
+
+ QSettings settings;
+ QString accKeydbPath = settings.value("gpgpaths/keydbpath").toString();
+ QString gpgKeys = appPath + "/keydb/"+accKeydbPath;
+
+ if (accKeydbPath != "") {
+ if (!QDir(gpgKeys).exists()) {
+ QMessageBox::critical(0,tr("keydb path"),tr("Didn't find keydb directory. Switching to gpg4usb's default keydb directory for this session."));
+ gpgKeys = appPath + "/keydb";
+ }
+ }
+
+ /* err = gpgme_ctx_set_engine_info(mCtx, GPGME_PROTOCOL_OpenPGP,
+ gpgBin.toUtf8().constData(),
+ gpgKeys.toUtf8().constData());*/
+#ifndef GPG4USB_NON_PORTABLE
+ err = gpgme_ctx_set_engine_info(mCtx, GPGME_PROTOCOL_OpenPGP,
+ gpgBin.toLocal8Bit().constData(),
+ gpgKeys.toLocal8Bit().constData());
+ checkErr(err);
+#endif
+
+ gpgme_engine_info_t engineInfo;
+ engineInfo = gpgme_ctx_get_engine_info(mCtx);
+
+
+ while (engineInfo !=NULL ) {
+ qDebug() << gpgme_get_protocol_name(engineInfo->protocol);
+ engineInfo=engineInfo->next;
+ }
+
+ /** Setting the output type must be done at the beginning */
+ /** think this means ascii-armor --> ? */
+ gpgme_set_armor(mCtx, 1);
+ /** passphrase-callback */
+ gpgme_set_passphrase_cb(mCtx, passphraseCb, this);
+
+ /** check if app is called with -d from command line */
+ if (qApp->arguments().contains("-d")) {
+ qDebug() << "gpgme_data_t debug on";
+ debug = true;
+ } else {
+ debug = false;
+ }
+
+ connect(this,SIGNAL(signalKeyDBChanged()),this,SLOT(slotRefreshKeyList()));
+ slotRefreshKeyList();
+}
+
+/** Destructor
+ * Release gpgme-context
+ */
+GpgContext::~GpgContext()
+{
+ if (mCtx) gpgme_release(mCtx);
+ mCtx = 0;
+}
+
+/** Import Key from QByteArray
+ *
+ */
+GpgImportInformation GpgContext::importKey(QByteArray inBuffer)
+{
+ GpgImportInformation *importInformation = new GpgImportInformation();
+ err = gpgme_data_new_from_mem(&in, inBuffer.data(), inBuffer.size(), 1);
+ checkErr(err);
+ err = gpgme_op_import(mCtx, in);
+ gpgme_import_result_t result;
+
+ result = gpgme_op_import_result(mCtx);
+ if (result->unchanged){
+ importInformation->unchanged = result->unchanged;
+ }
+ if (result->considered){
+ importInformation->considered = result->considered;
+ }
+ if (result->no_user_id){
+ importInformation->no_user_id = result->no_user_id;
+ }
+ if (result->imported){
+ importInformation->imported = result->imported;
+ }
+ if (result->imported_rsa){
+ importInformation->imported_rsa = result->imported_rsa;
+ }
+ if (result->unchanged){
+ importInformation->unchanged = result->unchanged;
+ }
+ if (result->new_user_ids){
+ importInformation->new_user_ids = result->new_user_ids;
+ }
+ if (result->new_sub_keys){
+ importInformation->new_sub_keys = result->new_sub_keys;
+ }
+ if (result->new_signatures){
+ importInformation->new_signatures = result->new_signatures;
+ }
+ if (result->new_revocations){
+ importInformation->new_revocations =result->new_revocations;
+ }
+ if (result->secret_read){
+ importInformation->secret_read = result->secret_read;
+ }
+ if (result->secret_imported){
+ importInformation->secret_imported = result->secret_imported;
+ }
+ if (result->secret_unchanged){
+ importInformation->secret_unchanged = result->secret_unchanged;
+ }
+ if (result->not_imported){
+ importInformation->not_imported = result->not_imported;
+ }
+ gpgme_import_status_t status = result->imports;
+ while (status != NULL) {
+ GpgImportedKey key;
+ key.importStatus = status->status;
+ key.fpr = status->fpr;
+ importInformation->importedKeys.append(key);
+ status=status->next;
+ }
+ checkErr(err);
+ emit signalKeyDBChanged();
+ gpgme_data_release(in);
+ return *importInformation;
+}
+
+/** Generate New Key with values params
+ *
+ */
+void GpgContext::generateKey(QString *params)
+{
+ err = gpgme_op_genkey(mCtx, params->toAscii().data(), NULL, NULL);
+ checkErr(err);
+ emit signalKeyDBChanged();
+}
+
+/** Export Key to QByteArray
+ *
+ */
+bool GpgContext::exportKeys(QStringList *uidList, QByteArray *outBuffer)
+{
+ size_t read_bytes;
+ gpgme_data_t out = 0;
+ outBuffer->resize(0);
+
+ if (uidList->count() == 0) {
+ QMessageBox::critical(0, "Export Keys Error", "No Keys Selected");
+ return false;
+ }
+
+ for (int i = 0; i < uidList->count(); i++) {
+ err = gpgme_data_new(&out);
+ checkErr(err);
+
+ err = gpgme_op_export(mCtx, uidList->at(i).toAscii().constData(), 0, out);
+ checkErr(err);
+
+ read_bytes = gpgme_data_seek(out, 0, SEEK_END);
+
+ err = readToBuffer(out, outBuffer);
+ checkErr(err);
+ gpgme_data_release(out);
+ }
+ return true;
+}
+
+gpgme_key_t GpgContext::getKeyDetails(QString uid)
+{
+ gpgme_key_t key;
+
+ // try secret
+ gpgme_get_key(mCtx, uid.toAscii().constData(), &key, 1);
+ // ok, its a public key
+ if (!key) {
+ gpgme_get_key(mCtx, uid.toAscii().constData(), &key, 0);
+ }
+ return key;
+}
+
+/** List all availabe Keys (VERY much like kgpgme)
+ */
+GpgKeyList GpgContext::listKeys()
+{
+ gpgme_error_t err;
+ gpgme_key_t key;
+
+ GpgKeyList keys;
+ //TODO dont run the loop more often than necessary
+ // list all keys ( the 0 is for all )
+ err = gpgme_op_keylist_start(mCtx, NULL, 0);
+ checkErr(err);
+ while (!(err = gpgme_op_keylist_next(mCtx, &key))) {
+ GpgKey gpgkey;
+
+ if (!key->subkeys)
+ continue;
+
+ gpgkey.id = key->subkeys->keyid;
+ gpgkey.fpr = key->subkeys->fpr;
+ gpgkey.expired = (key->expired != 0);
+ gpgkey.revoked = (key->revoked != 0);
+
+ if (key->uids) {
+ gpgkey.name = QString::fromUtf8(key->uids->name);
+ gpgkey.email = QString::fromUtf8(key->uids->email);
+ }
+ keys.append(gpgkey);
+ gpgme_key_unref(key);
+ }
+ gpgme_op_keylist_end(mCtx);
+
+ // list only private keys ( the 1 does )
+ gpgme_op_keylist_start(mCtx, NULL, 1);
+ while (!(err = gpgme_op_keylist_next(mCtx, &key))) {
+ if (!key->subkeys)
+ continue;
+ // iterate keys, mark privates
+ GpgKeyList::iterator it = keys.begin();
+ while (it != keys.end()) {
+ if (key->subkeys->keyid == it->id.toStdString())
+ it->privkey = true;
+ it++;
+ }
+
+ gpgme_key_unref(key);
+ }
+ gpgme_op_keylist_end(mCtx);
+
+ return keys;
+}
+
+/** Delete keys
+ */
+
+void GpgContext::deleteKeys(QStringList *uidList)
+{
+ QString tmp;
+ gpgme_key_t key;
+
+ foreach(tmp, *uidList) {
+ gpgme_op_keylist_start(mCtx, tmp.toAscii().constData(), 0);
+ gpgme_op_keylist_next(mCtx, &key);
+ gpgme_op_keylist_end(mCtx);
+ gpgme_op_delete(mCtx, key, 1);
+ }
+ emit signalKeyDBChanged();
+}
+
+/** Encrypt inBuffer for reciepients-uids, write
+ * result to outBuffer
+ */
+bool GpgContext::encrypt(QStringList *uidList, const QByteArray &inBuffer, QByteArray *outBuffer)
+{
+
+ gpgme_data_t in = 0, out = 0;
+ outBuffer->resize(0);
+
+ if (uidList->count() == 0) {
+ QMessageBox::critical(0, tr("No Key Selected"), tr("No Key Selected"));
+ return false;
+ }
+
+ //gpgme_encrypt_result_t e_result;
+ gpgme_key_t recipients[uidList->count()+1];
+
+ /* get key for user */
+ for (int i = 0; i < uidList->count(); i++) {
+ // the last 0 is for public keys, 1 would return private keys
+ gpgme_op_keylist_start(mCtx, uidList->at(i).toAscii().constData(), 0);
+ gpgme_op_keylist_next(mCtx, &recipients[i]);
+ gpgme_op_keylist_end(mCtx);
+ }
+ //Last entry in array has to be NULL
+ recipients[uidList->count()] = NULL;
+
+ //If the last parameter isnt 0, a private copy of data is made
+ if (mCtx) {
+ err = gpgme_data_new_from_mem(&in, inBuffer.data(), inBuffer.size(), 1);
+ checkErr(err);
+ if (!err) {
+ err = gpgme_data_new(&out);
+ checkErr(err);
+ if (!err) {
+ err = gpgme_op_encrypt(mCtx, recipients, GPGME_ENCRYPT_ALWAYS_TRUST, in, out);
+ checkErr(err);
+ if (!err) {
+ err = readToBuffer(out, outBuffer);
+ checkErr(err);
+ }
+ }
+ }
+ }
+ /* unref all keys */
+ for (int i = 0; i <= uidList->count(); i++) {
+ gpgme_key_unref(recipients[i]);
+ }
+ if (in) {
+ gpgme_data_release(in);
+ }
+ if (out) {
+ gpgme_data_release(out);
+ }
+ return (err == GPG_ERR_NO_ERROR);
+}
+
+/** Decrypt QByteAarray, return QByteArray
+ * mainly from http://basket.kde.org/ (kgpgme.cpp)
+ */
+bool GpgContext::decrypt(const QByteArray &inBuffer, QByteArray *outBuffer)
+{
+ gpgme_data_t in = 0, out = 0;
+ gpgme_decrypt_result_t result = 0;
+ QString errorString;
+
+ outBuffer->resize(0);
+ if (mCtx) {
+ err = gpgme_data_new_from_mem(&in, inBuffer.data(), inBuffer.size(), 1);
+ checkErr(err);
+ if (!err) {
+ err = gpgme_data_new(&out);
+ checkErr(err);
+ if (!err) {
+ err = gpgme_op_decrypt(mCtx, in, out);
+ checkErr(err);
+
+ if(gpg_err_code(err) == GPG_ERR_DECRYPT_FAILED) {
+ errorString.append(gpgErrString(err)).append("<br>");
+ result = gpgme_op_decrypt_result(mCtx);
+ checkErr(result->recipients->status);
+ errorString.append(gpgErrString(result->recipients->status)).append("<br>");
+ errorString.append(tr("<br>No private key with id %1 present in keyring").arg(result->recipients->keyid));
+ } else {
+ errorString.append(gpgErrString(err)).append("<br>");
+ }
+
+ if (!err) {
+ result = gpgme_op_decrypt_result(mCtx);
+ if (result->unsupported_algorithm) {
+ QMessageBox::critical(0, tr("Unsupported algorithm"), result->unsupported_algorithm);
+ } else {
+ err = readToBuffer(out, outBuffer);
+ checkErr(err);
+ }
+ }
+ }
+ }
+ }
+ if (gpg_err_code(err) != GPG_ERR_NO_ERROR && gpg_err_code(err) != GPG_ERR_CANCELED) {
+ QMessageBox::critical(0, tr("Error decrypting:"), errorString);
+ return false;
+ }
+
+ if (! settings.value("general/rememberPassword").toBool()) {
+ clearPasswordCache();
+ }
+
+ if (in) {
+ gpgme_data_release(in);
+ }
+ if (out) {
+ gpgme_data_release(out);
+ }
+ return (err == GPG_ERR_NO_ERROR);
+}
+
+/** Read gpgme-Data to QByteArray
+ * mainly from http://basket.kde.org/ (kgpgme.cpp)
+ */
+#define BUF_SIZE (32 * 1024)
+gpgme_error_t GpgContext::readToBuffer(gpgme_data_t in, QByteArray *outBuffer)
+{
+ int ret;
+ gpgme_error_t err = GPG_ERR_NO_ERROR;
+
+ ret = gpgme_data_seek(in, 0, SEEK_SET);
+ if (ret) {
+ err = gpgme_err_code_from_errno(errno);
+ checkErr(err, "failed dataseek in readToBuffer");
+ } else {
+ char *buf = new char[BUF_SIZE + 2];
+
+ if (buf) {
+ while ((ret = gpgme_data_read(in, buf, BUF_SIZE)) > 0) {
+ uint size = outBuffer->size();
+ outBuffer->resize(size + ret);
+ memcpy(outBuffer->data() + size, buf, ret);
+ }
+ if (ret < 0) {
+ err = gpgme_err_code_from_errno(errno);
+ checkErr(err, "failed data_read in readToBuffer");
+ }
+ delete[] buf;
+ }
+ }
+ return err;
+}
+
+/** The Passphrase window, if not provided by env-Var GPG_AGENT_INFO
+ * originally copied from http://basket.kde.org/ (kgpgme.cpp), but modified
+ */
+gpgme_error_t GpgContext::passphraseCb(void *hook, const char *uid_hint,
+ const char *passphrase_info,
+ int last_was_bad, int fd)
+{
+ GpgContext *gpg = static_cast<GpgContext*>(hook);
+ return gpg->passphrase(uid_hint, passphrase_info, last_was_bad, fd);
+}
+
+gpgme_error_t GpgContext::passphrase(const char *uid_hint,
+ const char * /*passphrase_info*/,
+ int last_was_bad, int fd)
+{
+ gpgme_error_t returnValue = GPG_ERR_CANCELED;
+ QString passwordDialogMessage;
+ QString gpgHint = QString::fromUtf8(uid_hint);
+ bool result;
+#ifdef _WIN32
+ DWORD written;
+ HANDLE hd = (HANDLE)fd;
+#endif
+
+ if (last_was_bad) {
+ passwordDialogMessage += "<i>"+tr("Wrong password")+".</i><br><br>\n\n";
+ clearPasswordCache();
+ }
+
+ /** if uid provided */
+ if (!gpgHint.isEmpty()) {
+ // remove UID, leave only username & email
+ gpgHint.remove(0, gpgHint.indexOf(" "));
+ passwordDialogMessage += "<b>"+tr("Enter Password for")+"</b><br>" + gpgHint + "<br>";
+ }
+
+ if (mPasswordCache.isEmpty()) {
+ QString password = QInputDialog::getText(QApplication::activeWindow(), tr("Enter Password"),
+ passwordDialogMessage, QLineEdit::Password,
+ "", &result);
+
+ if (result) mPasswordCache = password.toAscii();
+ } else {
+ result = true;
+ }
+
+ if (result) {
+
+#ifndef _WIN32
+ if (write(fd, mPasswordCache.data(), mPasswordCache.length()) == -1) {
+ qDebug() << "something is terribly broken";
+ }
+#else
+ WriteFile(hd, mPasswordCache.data(), mPasswordCache.length(), &written, 0);
+#endif
+
+ returnValue = GPG_ERR_NO_ERROR;
+ }
+
+#ifndef _WIN32
+ if (write(fd, "\n", 1) == -1) {
+ qDebug() << "something is terribly broken";
+ }
+#else
+ WriteFile(hd, "\n", 1, &written, 0);
+
+ /* program will hang on cancel if hd not closed */
+ if(!result) {
+ CloseHandle(hd);
+ }
+#endif
+
+ return returnValue;
+}
+
+/** also from kgpgme.cpp, seems to clear password from mem */
+void GpgContext::clearPasswordCache()
+{
+ if (mPasswordCache.size() > 0) {
+ mPasswordCache.fill('\0');
+ mPasswordCache.truncate(0);
+ }
+}
+
+// error-handling
+int GpgContext::checkErr(gpgme_error_t err, QString comment) const
+{
+ //if (err != GPG_ERR_NO_ERROR && err != GPG_ERR_CANCELED) {
+ if (err != GPG_ERR_NO_ERROR) {
+ qDebug() << "[Error " << comment << "] Source: " << gpgme_strsource(err) << " String: " << gpgErrString(err);
+ }
+ return err;
+}
+
+int GpgContext::checkErr(gpgme_error_t err) const
+{
+ //if (err != GPG_ERR_NO_ERROR && err != GPG_ERR_CANCELED) {
+ if (err != GPG_ERR_NO_ERROR) {
+ qDebug() << "[Error] Source: " << gpgme_strsource(err) << " String: " << gpgErrString(err);
+ }
+ return err;
+}
+
+QString GpgContext::gpgErrString(gpgme_error_t err) {
+ return QString::fromUtf8(gpgme_strerror(err));
+}
+
+/** export private key, TODO errohandling, e.g. like in seahorse (seahorse-gpg-op.c) **/
+
+void GpgContext::exportSecretKey(QString uid, QByteArray *outBuffer)
+{
+ qDebug() << *outBuffer;
+ // export private key to outBuffer
+ QStringList arguments;
+ arguments << "--armor" << "--export-secret-key" << uid;
+ QByteArray *err = new QByteArray();
+ executeGpgCommand(arguments, outBuffer, err);
+
+ // append public key to outBuffer
+ QByteArray *pubKey = new QByteArray();
+ QStringList keyList;
+ keyList.append(uid);
+ exportKeys(&keyList,pubKey);
+ outBuffer->append(*pubKey);
+}
+
+/** return type should be gpgme_error_t*/
+void GpgContext::executeGpgCommand(QStringList arguments, QByteArray *stdOut, QByteArray *stdErr)
+{
+ QStringList args;
+ args << "--homedir" << gpgKeys << "--batch" << arguments;
+
+ qDebug() << args;
+ QProcess gpg;
+ // qDebug() << "engine->file_name" << engine->file_name;
+
+ gpg.start(gpgBin, args);
+ gpg.waitForFinished();
+
+ *stdOut = gpg.readAllStandardOutput();
+ *stdErr = gpg.readAllStandardError();
+ qDebug() << *stdOut;
+}
+
+/***
+ * if sigbuffer not set, the inbuffer should contain signed text
+ *
+ * TODO: return type should contain:
+ * -> list of sigs
+ * -> valid
+ * -> errors
+ */
+gpgme_signature_t GpgContext::verify(QByteArray *inBuffer, QByteArray *sigBuffer) {
+
+ int error=0;
+ gpgme_data_t in;
+ gpgme_error_t err;
+ gpgme_signature_t sign;
+ gpgme_verify_result_t result;
+
+ err = gpgme_data_new_from_mem(&in, inBuffer->data(), inBuffer->size(), 1);
+ checkErr(err);
+
+ if (sigBuffer != NULL ) {
+ gpgme_data_t sigdata;
+ err = gpgme_data_new_from_mem(&sigdata, sigBuffer->data(), sigBuffer->size(), 1);
+ err = gpgme_op_verify (mCtx, sigdata, in, NULL);
+ } else {
+ err = gpgme_op_verify (mCtx, in, NULL, in);
+ }
+ error = checkErr(err);
+
+ if (error != 0) {
+ return NULL;
+ }
+
+ result = gpgme_op_verify_result (mCtx);
+ sign = result->signatures;
+ return sign;
+}
+
+/***
+ * return type should contain:
+ * -> list of sigs
+ * -> valid
+ * -> decrypted message
+ */
+//void GpgContext::decryptVerify(QByteArray in) {
+
+/* gpgme_error_t err;
+ gpgme_data_t in, out;
+
+ gpgme_decrypt_result_t decrypt_result;
+ gpgme_verify_result_t verify_result;
+
+ err = gpgme_op_decrypt_verify (mCtx, in, out);
+ decrypt_result = gpgme_op_decrypt_result (mCtx);
+
+ verify_result = gpgme_op_verify_result (mCtx);
+ */
+//}
+
+bool GpgContext::sign(QStringList *uidList, const QByteArray &inBuffer, QByteArray *outBuffer, bool detached) {
+
+ gpgme_error_t err;
+ gpgme_data_t in, out;
+ gpgme_sign_result_t result;
+ gpgme_sig_mode_t mode;
+
+ if (uidList->count() == 0) {
+ QMessageBox::critical(0, tr("Key Selection"), tr("No Private Key Selected"));
+ return false;
+ }
+
+ // at start or end?
+ gpgme_signers_clear(mCtx);
+
+ //gpgme_encrypt_result_t e_result;
+ gpgme_key_t signers[uidList->count()+1];
+
+
+ // TODO: do we really need array? adding one key in loop should be ok
+ for (int i = 0; i < uidList->count(); i++) {
+ // the last 0 is for public keys, 1 would return private keys
+ gpgme_op_keylist_start(mCtx, uidList->at(i).toAscii().constData(), 0);
+ gpgme_op_keylist_next(mCtx, &signers[i]);
+ gpgme_op_keylist_end(mCtx);
+
+ err = gpgme_signers_add (mCtx, signers[i]);
+ checkErr(err);
+ }
+
+ err = gpgme_data_new_from_mem(&in, inBuffer.data(), inBuffer.size(), 1);
+ checkErr(err);
+ err = gpgme_data_new (&out);
+ checkErr(err);
+
+ /*
+ `GPGME_SIG_MODE_NORMAL'
+ A normal signature is made, the output includes the plaintext
+ and the signature.
+
+ `GPGME_SIG_MODE_DETACH'
+ A detached signature is made.
+
+ `GPGME_SIG_MODE_CLEAR'
+ A clear text signature is made. The ASCII armor and text
+ mode settings of the context are ignored.
+ */
+
+ if(detached) {
+ mode = GPGME_SIG_MODE_DETACH;
+ } else {
+ mode = GPGME_SIG_MODE_CLEAR;
+ }
+
+ err = gpgme_op_sign (mCtx, in, out, mode);
+ checkErr (err);
+
+ if (err == GPG_ERR_CANCELED) {
+ return false;
+ }
+
+ if (err != GPG_ERR_NO_ERROR) {
+ QMessageBox::critical(0, tr("Error signing:"), QString::fromUtf8(gpgme_strerror(err)));
+ return false;
+ }
+
+ result = gpgme_op_sign_result (mCtx);
+ err = readToBuffer(out, outBuffer);
+ checkErr (err);
+
+ gpgme_data_release(in);
+ gpgme_data_release(out);
+
+ if (! settings.value("general/rememberPassword").toBool()) {
+ clearPasswordCache();
+ }
+
+ return (err == GPG_ERR_NO_ERROR);
+}
+
+/*
+ * if there is no '\n' before the PGP-Begin-Block, but for example a whitespace,
+ * GPGME doesn't recognise the Message as encrypted. This function adds '\n'
+ * before the PGP-Begin-Block, if missing.
+ */
+void GpgContext::preventNoDataErr(QByteArray *in)
+{
+ int block_start = in->indexOf(GpgConstants::PGP_CRYPT_BEGIN);
+ if (block_start > 0 && in->at(block_start - 1) != '\n') {
+ in->insert(block_start, '\n');
+ }
+ block_start = in->indexOf(GpgConstants::PGP_SIGNED_BEGIN);
+ if (block_start > 0 && in->at(block_start - 1) != '\n') {
+ in->insert(block_start, '\n');
+ }
+}
+
+/*
+ * isSigned returns:
+ * - 0, if text isn't signed at all
+ * - 1, if text is partially signed
+ * - 2, if text is completly signed
+ */
+int GpgContext::textIsSigned(const QByteArray &text) {
+ if (text.trimmed().startsWith(GpgConstants::PGP_SIGNED_BEGIN) && text.trimmed().endsWith(GpgConstants::PGP_SIGNED_END)) {
+ return 2;
+ }
+ if (text.contains(GpgConstants::PGP_SIGNED_BEGIN) && text.contains(GpgConstants::PGP_SIGNED_END)) {
+ return 1;
+ }
+ return 0;
+}
+
+QString GpgContext::beautifyFingerprint(QString fingerprint)
+{
+ uint len = fingerprint.length();
+ if ((len > 0) && (len % 4 == 0))
+ for (uint n = 0; 4 *(n + 1) < len; ++n)
+ fingerprint.insert(5 * n + 4, ' ');
+ return fingerprint;
+}
+
+void GpgContext::slotRefreshKeyList() {
+ mKeyList = this->listKeys();
+}
+
+/**
+ * note: privkey status is not returned
+ */
+GpgKey GpgContext::getKeyByFpr(QString fpr) {
+
+ //GpgKeyList list = this->listKeys();
+ foreach (GpgKey key, mKeyList) {
+ if(key.fpr == fpr) {
+ return key;
+ }
+ }
+
+ return GpgKey();
+}
+
+/**
+ * note: privkey status is not returned
+ */
+GpgKey GpgContext::getKeyById(QString id) {
+
+ //GpgKeyList list = this->listKeys();
+ foreach (GpgKey key, mKeyList) {
+ if(key.id == id) {
+ return key;
+ }
+ }
+
+ return GpgKey();
+}
+
+QString GpgContext::getGpgmeVersion() {
+ return QString(gpgme_check_version(NULL));
+}
+
+}
+
+
+
+
+
diff --git a/src/gpgcontext.h b/src/gpgcontext.h
new file mode 100644
index 0000000..5b8f93c
--- /dev/null
+++ b/src/gpgcontext.h
@@ -0,0 +1,183 @@
+/*
+ * gpgcontext.h
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef __SGPGMEPP_CONTEXT_H__
+#define __SGPGMEPP_CONTEXT_H__
+
+#include "gpgconstants.h"
+#include <locale.h>
+#include <errno.h>
+#include <gpgme.h>
+#include <QLinkedList>
+#include <QtGui>
+
+QT_BEGIN_NAMESPACE
+class QMessageBox;
+class sstream;
+class QApplication;
+class QByteArray;
+class QString;
+QT_END_NAMESPACE
+
+class GpgKey
+{
+public:
+ GpgKey() {
+ privkey = false;
+ }
+ QString id;
+ QString name;
+ QString email;
+ QString fpr;
+ bool privkey;
+ bool expired;
+ bool revoked;
+};
+
+typedef QLinkedList< GpgKey > GpgKeyList;
+
+class GpgImportedKey
+{
+public:
+ QString fpr;
+ int importStatus;
+};
+
+typedef QLinkedList< GpgImportedKey > GpgImportedKeyList;
+
+class GpgImportInformation
+{
+public:
+ GpgImportInformation() {
+ considered = 0;
+ no_user_id = 0;
+ imported = 0;
+ imported_rsa = 0;
+ unchanged = 0;
+ new_user_ids = 0;
+ new_sub_keys = 0;
+ new_signatures = 0;
+ new_revocations = 0;
+ secret_read = 0;
+ secret_imported = 0;
+ secret_unchanged = 0;
+ not_imported = 0;
+ }
+
+ int considered;
+ int no_user_id;
+ int imported;
+ int imported_rsa;
+ int unchanged;
+ int new_user_ids;
+ int new_sub_keys;
+ int new_signatures;
+ int new_revocations;
+ int secret_read;
+ int secret_imported;
+ int secret_unchanged;
+ int not_imported;
+ GpgImportedKeyList importedKeys;
+};
+
+namespace GpgME
+{
+
+class GpgContext : public QObject
+{
+ Q_OBJECT
+
+public:
+ GpgContext(); // Constructor
+ ~GpgContext(); // Destructor
+ GpgImportInformation importKey(QByteArray inBuffer);
+ bool exportKeys(QStringList *uidList, QByteArray *outBuffer);
+ void generateKey(QString *params);
+ GpgKeyList listKeys();
+ void deleteKeys(QStringList *uidList);
+ bool encrypt(QStringList *uidList, const QByteArray &inBuffer,
+ QByteArray *outBuffer);
+ bool decrypt(const QByteArray &inBuffer, QByteArray *outBuffer);
+ void clearPasswordCache();
+ void exportSecretKey(QString uid, QByteArray *outBuffer);
+ gpgme_key_t getKeyDetails(QString uid);
+ gpgme_signature_t verify(QByteArray *inBuffer, QByteArray *sigBuffer = NULL);
+// void decryptVerify(QByteArray in);
+ bool sign(QStringList *uidList, const QByteArray &inBuffer, QByteArray *outBuffer, bool detached = false);
+ /**
+ * @details If text contains PGP-message, put a linebreak before the message,
+ * so that gpgme can decrypt correctly
+ *
+ * @param in Pointer to the QBytearray to check.
+ */
+ void preventNoDataErr(QByteArray *in);
+
+ GpgKey getKeyByFpr(QString fpr);
+ GpgKey getKeyById(QString id);
+
+ static QString gpgErrString(gpgme_error_t err);
+ static QString getGpgmeVersion();
+
+ /**
+ * @brief
+ *
+ * @param text
+ * @return \li 2, if the text is completly signed,
+ * \li 1, if the text is partially signed,
+ * \li 0, if the text is not signed at all.
+ */
+ int textIsSigned(const QByteArray &text);
+ QString beautifyFingerprint(QString fingerprint);
+
+signals:
+ void signalKeyDBChanged();
+
+private slots:
+ void slotRefreshKeyList();
+
+private:
+ gpgme_ctx_t mCtx;
+ gpgme_data_t in, out;
+ gpgme_error_t err;
+ gpgme_error_t readToBuffer(gpgme_data_t in, QByteArray *outBuffer);
+ QByteArray mPasswordCache;
+ QSettings settings;
+ bool debug;
+ GpgKeyList mKeyList;
+ int checkErr(gpgme_error_t err) const;
+ int checkErr(gpgme_error_t err, QString comment) const;
+
+ static gpgme_error_t passphraseCb(void *hook, const char *uid_hint,
+ const char *passphrase_info,
+ int last_was_bad, int fd);
+ gpgme_error_t passphrase(const char *uid_hint,
+ const char *passphrase_info,
+ int last_was_bad, int fd);
+
+ void executeGpgCommand(QStringList arguments,
+ QByteArray *stdOut,
+ QByteArray *stdErr);
+ QString gpgBin;
+ QString gpgKeys;
+};
+} // namespace GpgME
+
+#endif // __SGPGMEPP_CONTEXT_H__
diff --git a/src/helppage.cpp b/src/helppage.cpp
new file mode 100644
index 0000000..ace8c92
--- /dev/null
+++ b/src/helppage.cpp
@@ -0,0 +1,81 @@
+/*
+ * helppage.cpp
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "helppage.h"
+
+HelpPage::HelpPage(const QString path, QWidget *parent) :
+ QWidget(parent)
+{
+
+ browser = new QTextBrowser();
+ QVBoxLayout* mainLayout = new QVBoxLayout();
+ mainLayout->setSpacing(0);
+ mainLayout->addWidget(browser);
+ mainLayout->setContentsMargins(0,0,0,0);
+ setLayout(mainLayout);
+ //setAttribute(Qt::WA_DeleteOnClose);
+ //browser->setSource(QUrl::fromLocalFile(path));
+
+ connect(browser, SIGNAL(anchorClicked(QUrl)), this, SLOT(slotOpenUrl(QUrl)));
+ browser->setOpenLinks(false);
+ browser->setSource(localizedHelp(QUrl(path)));
+ browser->setFocus();
+
+}
+
+void HelpPage::slotOpenUrl(QUrl url) {
+ browser->setSource(localizedHelp(url));
+};
+
+/**
+ * @brief HelpPage::localizedHelp
+ * check if the requested file is also available with the locale,
+ * e.g. return index.de.html if index.html was requested but the
+ * locale is de and index.de.html is available
+ * @param url
+ * @return
+ */
+QUrl HelpPage::localizedHelp(QUrl url) {
+ QString path = url.toLocalFile();
+ QString filename = path.mid(path.lastIndexOf("/") + 1 );
+ QString filepath = path.left(path.lastIndexOf("/") + 1 );
+ QStringList fileparts = filename.split(".");
+
+ //QSettings settings;
+ QString lang = QSettings().value("int/lang", QLocale::system().name()).toString();
+ if (lang.isEmpty()) {
+ lang = QLocale::system().name();
+ }
+
+ fileparts.insert(1,lang);
+ QString langfile = filepath + fileparts.join(".");
+
+ if(QFile(QUrl(langfile).toLocalFile()).exists()) {
+ return langfile;
+ } else {
+ return path;
+ }
+
+}
+
+QTextBrowser* HelpPage::getBrowser() {
+ return browser;
+}
diff --git a/src/helppage.h b/src/helppage.h
new file mode 100644
index 0000000..22aa9b1
--- /dev/null
+++ b/src/helppage.h
@@ -0,0 +1,50 @@
+/*
+ * helppage.h
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef HELPPAGE_H
+#define HELPPAGE_H
+
+#include <QWidget>
+#include <QTextBrowser>
+#include <QVBoxLayout>
+#include <QSettings>
+#include <QFile>
+#include <QLocale>
+
+class HelpPage : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit HelpPage(const QString path, QWidget *parent = 0);
+ QTextBrowser *getBrowser();
+
+signals:
+
+public slots:
+ void slotOpenUrl(QUrl url);
+
+private:
+ QTextBrowser *browser; /** The textbrowser of the tab */
+ QUrl localizedHelp(QUrl path);
+
+};
+
+#endif // HELPPAGE_H
diff --git a/src/keydetailsdialog.cpp b/src/keydetailsdialog.cpp
new file mode 100644
index 0000000..36f2e4a
--- /dev/null
+++ b/src/keydetailsdialog.cpp
@@ -0,0 +1,225 @@
+/*
+ * keydetailsdialog.cpp
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "keydetailsdialog.h"
+
+KeyDetailsDialog::KeyDetailsDialog(GpgME::GpgContext* ctx, gpgme_key_t key, QWidget *parent)
+ : QDialog(parent)
+{
+ mCtx = ctx;
+ keyid = new QString(key->subkeys->keyid);
+
+ ownerBox = new QGroupBox(tr("Owner details"));
+ keyBox = new QGroupBox(tr("Key details"));
+ fingerprintBox = new QGroupBox(tr("Fingerprint"));
+ additionalUidBox = new QGroupBox(tr("Additional Uids"));
+ buttonBox = new QDialogButtonBox(QDialogButtonBox::Close);
+ connect(buttonBox, SIGNAL(rejected()), this, SLOT(close()));
+
+ nameVarLabel = new QLabel(QString::fromUtf8(key->uids->name));
+ nameVarLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
+ emailVarLabel = new QLabel(QString::fromUtf8(key->uids->email));
+ emailVarLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
+
+ commentVarLabel = new QLabel(QString::fromUtf8(key->uids->comment));
+ commentVarLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
+ keyidVarLabel = new QLabel(key->subkeys->keyid);
+ keyidVarLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
+
+ QString keySizeVal, keyExpireVal, keyCreatedVal, keyAlgoVal;
+
+ if (key->subkeys->expires == 0) {
+ keyExpireVal = tr("Never");
+ } else {
+ keyExpireVal = QDateTime::fromTime_t(key->subkeys->expires).toString("dd. MMM. yyyy");
+ }
+
+ keyAlgoVal = gpgme_pubkey_algo_name(key->subkeys->pubkey_algo);
+ keyCreatedVal = QDateTime::fromTime_t(key->subkeys->timestamp).toString("dd. MMM. yyyy");
+
+ // have el-gamal key?
+ if (key->subkeys->next) {
+ keySizeVal.sprintf("%d / %d", int(key->subkeys->length), int(key->subkeys->next->length));
+ if (key->subkeys->next->expires == 0) {
+ keyExpireVal += tr(" / Never");
+ } else {
+ keyExpireVal += " / " + QDateTime::fromTime_t(key->subkeys->next->expires).toString("dd. MMM. yyyy");
+ }
+ keyAlgoVal.append(" / ").append(gpgme_pubkey_algo_name(key->subkeys->next->pubkey_algo));
+ keyCreatedVal += " / " + QDateTime::fromTime_t(key->subkeys->next->timestamp).toString("dd. MMM. yyyy");
+ } else {
+ keySizeVal.setNum(int(key->subkeys->length));
+ }
+
+ keySizeVarLabel = new QLabel(keySizeVal);
+ expireVarLabel = new QLabel(keyExpireVal);
+ createdVarLabel = new QLabel(keyCreatedVal);
+ algorithmVarLabel = new QLabel(keyAlgoVal);
+
+ QVBoxLayout *mvbox = new QVBoxLayout();
+ QGridLayout *vboxKD = new QGridLayout();
+ QGridLayout *vboxOD = new QGridLayout();
+
+ vboxOD->addWidget(new QLabel(tr("Name:")), 0, 0);
+ vboxOD->addWidget(new QLabel(tr("E-Mailaddress:")), 1, 0);
+ vboxOD->addWidget(new QLabel(tr("Comment:")), 2, 0);
+ vboxOD->addWidget(nameVarLabel, 0, 1);
+ vboxOD->addWidget(emailVarLabel, 1, 1);
+ vboxOD->addWidget(commentVarLabel, 2, 1);
+
+ vboxKD->addWidget(new QLabel(tr("Key size:")), 0, 0);
+ vboxKD->addWidget(new QLabel(tr("Expires on: ")), 1, 0);
+ vboxKD->addWidget(new QLabel(tr("Algorithm: ")), 3, 0);
+ vboxKD->addWidget(new QLabel(tr("Created on: ")), 4, 0);
+ vboxKD->addWidget(new QLabel(tr("Key ID: ")), 5, 0);
+ vboxKD->addWidget(keySizeVarLabel, 0, 1);
+ vboxKD->addWidget(expireVarLabel, 1, 1);
+ vboxKD->addWidget(algorithmVarLabel, 3, 1);
+ vboxKD->addWidget(createdVarLabel, 4, 1);
+ vboxKD->addWidget(keyidVarLabel, 5, 1);
+
+ ownerBox->setLayout(vboxOD);
+ mvbox->addWidget(ownerBox);
+
+ keyBox->setLayout(vboxKD);
+ mvbox->addWidget(keyBox);
+
+ fingerPrintVarLabel = new QLabel(beautifyFingerprint(key->subkeys->fpr));
+ fingerPrintVarLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
+ fingerPrintVarLabel->setStyleSheet("margin-left: 20; margin-right: 20;");
+ QHBoxLayout *hboxFP = new QHBoxLayout();
+
+ hboxFP->addWidget(fingerPrintVarLabel);
+ QIcon ico(":button_copy.png");
+
+ QPushButton copyFingerprintButton(QIcon(ico.pixmap(12, 12)), "");
+ //copyFingerprintButton.setStyleSheet("QPushButton {border: 0px; } QPushButton:Pressed {} ");
+ copyFingerprintButton.setFlat(true);
+ copyFingerprintButton.setToolTip(tr("copy fingerprint to clipboard"));
+ connect(&copyFingerprintButton, SIGNAL(clicked()), this, SLOT(slotCopyFingerprint()));
+
+ hboxFP->addWidget(&copyFingerprintButton);
+
+ fingerprintBox->setLayout(hboxFP);
+ mvbox->addWidget(fingerprintBox);
+
+ // If key has more than primary uid, also show the other uids
+ gpgme_user_id_t addUserIds = key->uids->next;
+ if (addUserIds !=NULL) {
+ QVBoxLayout *vboxUID = new QVBoxLayout();
+ while (addUserIds != NULL){
+ addUserIdsVarLabel = new QLabel(QString::fromUtf8(addUserIds->name)+ QString(" <")+addUserIds->email+">");
+ addUserIdsVarLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
+ vboxUID->addWidget(addUserIdsVarLabel);
+ addUserIds=addUserIds->next;
+ }
+ additionalUidBox->setLayout(vboxUID);
+ mvbox->addWidget(additionalUidBox);
+ }
+
+ if (key->secret) {
+ QGroupBox *privKeyBox = new QGroupBox(tr("Private Key"));
+ QVBoxLayout *vboxPK = new QVBoxLayout();
+
+ QPushButton *exportButton = new QPushButton(tr("Export Private Key"));
+ vboxPK->addWidget(exportButton);
+ connect(exportButton, SIGNAL(clicked()), this, SLOT(slotExportPrivateKey()));
+
+ privKeyBox->setLayout(vboxPK);
+ mvbox->addWidget(privKeyBox);
+ }
+
+ if((key->expired) || (key->revoked)) {
+ QHBoxLayout *expBox = new QHBoxLayout();
+ QIcon icon = QIcon::fromTheme("dialog-warning");
+ QPixmap pixmap = icon.pixmap(QSize(32,32),QIcon::Normal,QIcon::On);
+
+ QLabel *expLabel = new QLabel();
+ QLabel *iconLabel = new QLabel();
+ if (key->expired) {
+ expLabel->setText(tr("Warning: Key expired"));
+ }
+ if (key->revoked) {
+ expLabel->setText(tr("Warning: Key revoked"));
+ }
+
+ iconLabel->setPixmap(pixmap);
+ QFont font = expLabel->font();
+ font.setBold(true);
+ expLabel->setFont(font);
+ expBox->addWidget(iconLabel);
+ expBox->addWidget(expLabel);
+ mvbox->addLayout(expBox);
+ }
+
+ mvbox->addWidget(buttonBox);
+
+ this->setLayout(mvbox);
+ this->setWindowTitle(tr("Keydetails"));
+ this->setModal(true);
+ this->show();
+
+ exec();
+}
+
+void KeyDetailsDialog::slotExportPrivateKey()
+{
+ // Show a information box with explanation about private key
+ int ret = QMessageBox::information(this, tr("Exporting private Key"),
+ tr("You are about to export your private key.\n"
+ "This is NOT your public key, so don't give it away.\n"
+ "Make sure you keep it save."
+ "Do you really want to export your private key?"),
+ QMessageBox::Cancel | QMessageBox::Ok);
+
+ // export key, if ok was clicked
+ if (ret == QMessageBox::Ok) {
+ QByteArray *keyArray = new QByteArray();
+ mCtx->exportSecretKey(*keyid, keyArray);
+ gpgme_key_t key = mCtx->getKeyDetails(*keyid);
+ QString fileString = QString::fromUtf8(key->uids->name) + " " + QString::fromUtf8(key->uids->email) + "(" + QString(key->subkeys->keyid)+ ")_pub_sec.asc";
+ QString fileName = QFileDialog::getSaveFileName(this, tr("Export Key To File"), fileString, tr("Key Files") + " (*.asc *.txt);;All Files (*)");
+ QFile file(fileName);
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ QMessageBox::critical(0,tr("Export error"),tr("Couldn't open %1 for writing").arg(fileName));
+ return;
+ }
+ QTextStream stream(&file);
+ stream << *keyArray;
+ file.close();
+ delete keyArray;
+ }
+}
+
+QString KeyDetailsDialog::beautifyFingerprint(QString fingerprint)
+{
+ uint len = fingerprint.length();
+ if ((len > 0) && (len % 4 == 0))
+ for (uint n = 0; 4 *(n + 1) < len; ++n)
+ fingerprint.insert(5 * n + 4, ' ');
+ return fingerprint;
+}
+
+void KeyDetailsDialog::slotCopyFingerprint() {
+ QString fpr = fingerPrintVarLabel->text().trimmed().replace(" ", "");
+ QClipboard *cb = QApplication::clipboard();
+ cb->setText(fpr);
+}
diff --git a/src/keydetailsdialog.h b/src/keydetailsdialog.h
new file mode 100644
index 0000000..2774fe2
--- /dev/null
+++ b/src/keydetailsdialog.h
@@ -0,0 +1,87 @@
+/*
+ * keydetailsdialog.h
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef __KEYDETAILSDIALOG_H__
+#define __KEYDETAILSDIALOG_H__
+
+#include "gpgcontext.h"
+#include <gpgme.h>
+
+QT_BEGIN_NAMESPACE
+class QDateTime;
+class QVBoxLayout;
+class QHBoxLayout;
+class QDialogButtonBox;
+class QDialog;
+class QGroupBox;
+class QLabel;
+class QGridLayout;
+class QPushButton;
+QT_END_NAMESPACE
+
+class KeyDetailsDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ KeyDetailsDialog(GpgME::GpgContext* ctx, gpgme_key_t key, QWidget *parent = 0);
+
+ /**
+ * @details Return QString with a space inserted at every fourth character
+ *
+ * @param fingerprint The fingerprint to be beautified
+ */
+ static QString beautifyFingerprint(QString fingerprint);
+
+private slots:
+ /**
+ * @details Export the key to a file, which is choosen in a file dialog
+ */
+ void slotExportPrivateKey();
+
+ /**
+ * @details Copy the fingerprint to clipboard
+ */
+ void slotCopyFingerprint();
+
+private:
+ QString *keyid; /** The id of the key the details should be shown for */
+ GpgME::GpgContext *mCtx; /** The current gpg-context */
+
+ QGroupBox *ownerBox; /** Groupbox containing owner information */
+ QGroupBox *keyBox; /** Groupbox containing key information */
+ QGroupBox *fingerprintBox; /** Groupbox containing fingerprint information */
+ QGroupBox *additionalUidBox; /** Groupbox containing information about additional uids */
+ QDialogButtonBox *buttonBox; /** Box containing the close button */
+
+ QLabel *nameVarLabel; /** Label containng the keys name */
+ QLabel *emailVarLabel; /** Label containng the keys email */
+ QLabel *commentVarLabel; /** Label containng the keys commment */
+ QLabel *keySizeVarLabel; /** Label containng the keys keysize */
+ QLabel *expireVarLabel; /** Label containng the keys expiration date */
+ QLabel *createdVarLabel; /** Label containng the keys creation date */
+ QLabel *algorithmVarLabel; /** Label containng the keys algorithm */
+ QLabel *keyidVarLabel; /** Label containng the keys keyid */
+ QLabel *fingerPrintVarLabel; /** Label containng the keys fingerprint */
+ QLabel *addUserIdsVarLabel; /** Label containng info about keys additional uids */
+};
+
+#endif // __KEYDETAILSDIALOG_H__
diff --git a/src/keygendialog.cpp b/src/keygendialog.cpp
new file mode 100644
index 0000000..2aa5f81
--- /dev/null
+++ b/src/keygendialog.cpp
@@ -0,0 +1,255 @@
+/*
+ *
+ * keygendialog.cpp
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "keygendialog.h"
+
+KeyGenDialog::KeyGenDialog(GpgME::GpgContext *ctx, QWidget *parent)
+ : QDialog(parent)
+{
+ mCtx = ctx;
+ buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+
+ this->setWindowTitle(tr("Generate Key"));
+ this->setModal(true);
+ generateKeyDialog();
+}
+
+void KeyGenDialog::generateKeyDialog()
+{
+ errorLabel = new QLabel(tr(""));
+ nameEdit = new QLineEdit(this);
+ emailEdit = new QLineEdit(this);
+ commentEdit = new QLineEdit(this);
+
+ keySizeSpinBox = new QSpinBox(this);
+ keySizeSpinBox->setRange(1024, 4096);
+ keySizeSpinBox->setValue(2048);
+
+ keySizeSpinBox->setSingleStep(1024);
+
+ keyTypeComboBox = new QComboBox(this);
+ keyTypeComboBox->addItem("RSA");
+ keyTypeComboBox->addItem("DSA/Elgamal");
+ keyTypeComboBox->setCurrentIndex(0);
+ dateEdit = new QDateEdit(QDate::currentDate().addYears(5), this);
+ dateEdit->setMinimumDate(QDate::currentDate());
+ dateEdit->setDisplayFormat("dd/MM/yyyy");
+ dateEdit->setCalendarPopup(true);
+ dateEdit->setEnabled(true);
+
+ expireCheckBox = new QCheckBox(this);
+ expireCheckBox->setCheckState(Qt::Unchecked);
+
+ passwordEdit = new QLineEdit(this);
+ repeatpwEdit = new QLineEdit(this);
+
+ passwordEdit->setEchoMode(QLineEdit::Password);
+ repeatpwEdit->setEchoMode(QLineEdit::Password);
+
+ pwStrengthSlider = new QSlider(this);
+ pwStrengthSlider->setOrientation(Qt::Horizontal);
+ pwStrengthSlider->setMaximum(6);
+ pwStrengthSlider->setDisabled(true);
+ pwStrengthSlider->setToolTip(tr("Password Strength"));
+ pwStrengthSlider->setTickPosition(QSlider::TicksBelow);
+
+ QGridLayout *vbox1 = new QGridLayout;
+
+ vbox1->addWidget(new QLabel(tr("Name:")), 0, 0);
+ vbox1->addWidget(new QLabel(tr("E-Mailaddress:")), 1, 0);
+ vbox1->addWidget(new QLabel(tr("Comment:")), 2, 0);
+ vbox1->addWidget(new QLabel(tr("Expiration Date:")), 3, 0);
+ vbox1->addWidget(new QLabel(tr("Never Expire")), 3, 3);
+ vbox1->addWidget(new QLabel(tr("KeySize (in Bit):")), 4, 0);
+ vbox1->addWidget(new QLabel(tr("Key Type:")), 5, 0);
+ vbox1->addWidget(new QLabel(tr("Password:")), 6, 0);
+ vbox1->addWidget(new QLabel(tr("Password: Strength\nWeak -> Strong")), 6, 3);
+ vbox1->addWidget(new QLabel(tr("Repeat Password:")), 7, 0);
+
+ vbox1->addWidget(nameEdit, 0, 1);
+ vbox1->addWidget(emailEdit, 1, 1);
+ vbox1->addWidget(commentEdit, 2, 1);
+ vbox1->addWidget(dateEdit, 3, 1);
+ vbox1->addWidget(expireCheckBox, 3, 2);
+ vbox1->addWidget(keySizeSpinBox, 4, 1);
+ vbox1->addWidget(keyTypeComboBox,5, 1);
+ vbox1->addWidget(passwordEdit, 6, 1);
+ vbox1->addWidget(repeatpwEdit, 7, 1);
+ vbox1->addWidget(pwStrengthSlider, 7, 3);
+
+ QWidget *nameList = new QWidget(this);
+ nameList->setLayout(vbox1);
+
+ QVBoxLayout *vbox2 = new QVBoxLayout();
+ vbox2->addWidget(nameList);
+ vbox2->addWidget(errorLabel);
+ vbox2->addWidget(buttonBox);
+
+ connect(buttonBox, SIGNAL(accepted()), this, SLOT(slotKeyGenAccept()));
+ connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+
+ connect(expireCheckBox, SIGNAL(stateChanged(int)), this, SLOT(slotExpireBoxChanged()));
+ connect(passwordEdit, SIGNAL(textChanged(QString)), this, SLOT(slotPasswordEditChanged()));
+// connect(keyTypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotKeyTypeChanged()));
+// connect(keySizeSpinBox, SIGNAL(valueChanged(int)), this, SLOT(slotKeySizeChanged()));
+ this->setLayout(vbox2);
+}
+
+void KeyGenDialog::slotKeyGenAccept()
+{
+ QString errorString = "";
+ QString keyGenParams = "";
+ /**
+ * check for errors in keygen dialog input
+ */
+ if ((nameEdit->text()).size() < 5) {
+ errorString.append(tr(" Name must contain at least five characters. \n"));
+ }
+ if (passwordEdit->text() != repeatpwEdit->text()) {
+ errorString.append(tr(" Password and Repeat don't match. "));
+ }
+
+ if (errorString.isEmpty()) {
+ /**
+ * create the string for key generation
+ */
+
+ if(keyTypeComboBox->currentText() == "RSA") {
+ keyGenParams = "<GnupgKeyParms format=\"internal\">\n"
+ "Key-Type: RSA\n"
+ "Key-Usage: sign\n"
+ "Key-Length: " + keySizeSpinBox->cleanText() + "\n"
+ "Subkey-Type: RSA\n"
+ "Subkey-Length: " + keySizeSpinBox->cleanText() + "\n"
+ "Subkey-Usage: encrypt\n";
+ } else {
+ keyGenParams = "<GnupgKeyParms format=\"internal\">\n"
+ "Key-Type: DSA\n"
+ "Key-Length: " + keySizeSpinBox->cleanText() + "\n"
+ "Subkey-Type: ELG-E\n"
+ "Subkey-Length: " + keySizeSpinBox->cleanText() + "\n";
+ }
+
+ keyGenParams += "Name-Real: " + nameEdit->text().toUtf8() + "\n";
+ if (!(commentEdit->text().isEmpty())) {
+ keyGenParams += "Name-Comment: " + commentEdit->text().toUtf8() + "\n";
+ }
+ if (!(emailEdit->text().isEmpty())) {
+ keyGenParams += "Name-Email: " + emailEdit->text().toUtf8() + "\n";
+ }
+ if (expireCheckBox->checkState()) {
+ keyGenParams += "Expire-Date: 0\n";
+ } else {
+ keyGenParams += "Expire-Date: " + dateEdit->sectionText(QDateTimeEdit::YearSection) + "-" + dateEdit->sectionText(QDateTimeEdit::MonthSection) + "-" + dateEdit->sectionText(QDateTimeEdit::DaySection) + "\n";
+ }
+ if (!(passwordEdit->text().isEmpty())) {
+ keyGenParams += "Passphrase: " + passwordEdit->text() + "\n";
+ }
+ keyGenParams += "</GnupgKeyParms>";
+
+ KeyGenThread *kg = new KeyGenThread(keyGenParams, mCtx);
+ kg->start();
+
+ this->accept();
+
+ QDialog *dialog = new QDialog(this, Qt::CustomizeWindowHint | Qt::WindowTitleHint);
+ dialog->setModal(true);
+ dialog->setWindowTitle(tr("Generating Key..."));
+
+ QLabel *waitMessage = new QLabel(tr("Collecting random data for key generation.\n This may take a while.\n To speed up the process use your computer\n (e.g. browse the net, listen to music,...)"));
+ QProgressBar *pb = new QProgressBar();
+ pb->setRange(0, 0);
+
+ QVBoxLayout *layout = new QVBoxLayout(dialog);
+ layout->addWidget(waitMessage);
+ layout->addWidget(pb);
+ dialog->setLayout(layout);
+
+ dialog->show();
+
+ while (kg->isRunning()) {
+ QCoreApplication::processEvents();
+ }
+
+ dialog->close();
+ QMessageBox::information(0,tr("Success"),tr("New key created"));
+ } else {
+ /**
+ * create error message
+ */
+ errorLabel->setAutoFillBackground(true);
+ QPalette error = errorLabel->palette();
+ error.setColor(QPalette::Background, "#ff8080");
+ errorLabel->setPalette(error);
+ errorLabel->setText(errorString);
+
+ this->show();
+ }
+}
+
+void KeyGenDialog::slotExpireBoxChanged()
+{
+ if (expireCheckBox->checkState()) {
+ dateEdit->setEnabled(false);
+ } else {
+ dateEdit->setEnabled(true);
+ }
+}
+
+void KeyGenDialog::slotPasswordEditChanged()
+{
+ pwStrengthSlider->setValue(checkPassWordStrength());
+ update();
+}
+
+int KeyGenDialog::checkPassWordStrength()
+{
+ int strength = 0;
+
+ // increase strength by two, if password has more than 7 characters
+ if ((passwordEdit->text()).length() > 7) {
+ strength = strength + 2;
+ }
+
+ // increase strength by one, if password contains a digit
+ if ((passwordEdit->text()).contains(QRegExp("\\d"))) {
+ strength++;
+ }
+
+ // increase strength by one, if password contains a lowercase character
+ if ((passwordEdit->text()).contains(QRegExp("[a-z]"))) {
+ strength++;
+ }
+
+ // increase strength by one, if password contains an uppercase character
+ if ((passwordEdit->text()).contains(QRegExp("[A-Z]"))) {
+ strength++;
+ }
+
+ // increase strength by one, if password contains a non-word character
+ if ((passwordEdit->text()).contains(QRegExp("\\W"))) {
+ strength++;
+ }
+
+ return strength;
+}
+
diff --git a/src/keygendialog.h b/src/keygendialog.h
new file mode 100644
index 0000000..b3f4183
--- /dev/null
+++ b/src/keygendialog.h
@@ -0,0 +1,93 @@
+/*
+ * keygendialog.h
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef __KEYGENDIALOG_H__
+#define __KEYGENDIALOG_H__
+
+#include "keygenthread.h"
+#include "gpgcontext.h"
+#include <QtGui>
+
+QT_BEGIN_NAMESPACE
+class QDateTime;
+class QDialogButtonBox;
+class QDialog;
+class QGridLayout;
+QT_END_NAMESPACE
+
+class KeyGenDialog : public QDialog
+{
+ Q_OBJECT
+
+ /**
+ * @details Constructor of this class
+ *
+ * @param ctx The current GpgME context
+ * @param key The key to show details of
+ * @param parent The parent of this widget
+ */
+ public:
+ KeyGenDialog(GpgME::GpgContext* ctx, QWidget *parent = 0);
+
+private:
+ void generateKeyDialog();
+
+ /**
+ * @details Check the password strength of the text in the passwordEdit member
+ *
+ * @return digit between 0 and 6, the higher the more secure is the password
+ */
+ int checkPassWordStrength();
+
+ GpgME::GpgContext *mCtx; /** The current gpg context */
+ KeyGenThread *keyGenThread; /** Thread for key generation */
+ QStringList errorMessages; /** List of errors occuring when checking entries of lineedits */
+ QDialogButtonBox *buttonBox; /** Box for standardbuttons */
+ QLabel *errorLabel; /** Label containing error message */
+ QLineEdit *nameEdit; /** Lineedit for the keys name */
+ QLineEdit *emailEdit; /** Lineedit for the keys email */
+ QLineEdit *commentEdit; /** Lineedit for the keys comment */
+ QLineEdit *passwordEdit; /** Lineedit for the keys password */
+ QLineEdit *repeatpwEdit; /** Lineedit for the repetition of the keys password */
+ QSpinBox *keySizeSpinBox; /** Spinbox for the keys size (in bit) */
+ QComboBox *keyTypeComboBox; /** Combobox for Keytpe */
+ QDateTimeEdit *dateEdit; /** Dateedit for expiration date */
+ QCheckBox *expireCheckBox; /** Checkbox, if key should expire */
+ QSlider *pwStrengthSlider; /** Slider showing the password strength */
+
+private slots:
+ /**
+ * @details when expirebox was checked/unchecked, enable/disable the expiration date box
+ */
+ void slotExpireBoxChanged();
+
+ /**
+ * @details When passwordedit changed, set new value for password strength slider
+ */
+ void slotPasswordEditChanged();
+
+ /**
+ * @details check all lineedits for false entries. Show error, when there is one, otherwise generate the key
+ */
+ void slotKeyGenAccept();
+
+};
+#endif // __KEYGENDIALOG_H__
diff --git a/src/keygenthread.cpp b/src/keygenthread.cpp
new file mode 100644
index 0000000..c558877
--- /dev/null
+++ b/src/keygenthread.cpp
@@ -0,0 +1,34 @@
+/*
+ * keygenthread.cpp
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "keygenthread.h"
+
+KeyGenThread::KeyGenThread(QString keyGenParams, GpgME::GpgContext *ctx)
+{
+ this->keyGenParams = keyGenParams;
+ this->mCtx = ctx;
+ abort = false;
+}
+
+void KeyGenThread::run()
+{
+ mCtx->generateKey(&keyGenParams);
+}
diff --git a/src/keygenthread.h b/src/keygenthread.h
new file mode 100644
index 0000000..6fc61e9
--- /dev/null
+++ b/src/keygenthread.h
@@ -0,0 +1,56 @@
+/*
+ * keygenthread.h
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef __KEYGENTHREAD_H__
+#define __KEYGENTHREAD_H__
+
+#include "gpgcontext.h"
+#include <qthread.h>
+#include <iostream>
+#include <string>
+#include <cmath>
+#include <QtGui>
+
+QT_BEGIN_NAMESPACE
+class QMessageBox;
+QT_END_NAMESPACE
+
+class KeyGenThread : public QThread
+{
+ Q_OBJECT
+
+public:
+ KeyGenThread(QString keyGenParams, GpgME::GpgContext *ctx);
+
+signals:
+ void signalKeyGenerated();
+
+private:
+ QString keyGenParams;
+ GpgME::GpgContext *mCtx;
+ bool abort;
+ QMutex mutex;
+
+protected:
+ void run();
+
+};
+#endif // __KEYGENTHREAD_H__
diff --git a/src/keyimportdetaildialog.cpp b/src/keyimportdetaildialog.cpp
new file mode 100644
index 0000000..4448865
--- /dev/null
+++ b/src/keyimportdetaildialog.cpp
@@ -0,0 +1,160 @@
+/*
+ * keyimportdetailsdialog.cpp
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "keyimportdetaildialog.h"
+
+KeyImportDetailDialog::KeyImportDetailDialog(GpgME::GpgContext* ctx, GpgImportInformation result, QWidget *parent)
+ : QDialog(parent)
+{
+ mCtx = ctx;
+ mResult = result;
+ // If no key for import found, just show a message
+ if (mResult.considered == 0) {
+ QMessageBox::information(0, tr("Key import details"), tr("No keys found to import"));
+ return;
+ }
+
+ QVBoxLayout *mvbox = new QVBoxLayout();
+
+ this->createGeneralInfoBox();
+ mvbox->addWidget(generalInfoBox);
+
+ this->createKeysTable();
+ mvbox->addWidget(keysTable);
+
+ this->createButtonBox();
+ mvbox->addWidget(buttonBox);
+
+ this->setLayout(mvbox);
+ this->setWindowTitle(tr("Key import details"));
+ this->resize(QSize(600,300));
+ this->setModal(true);
+ this->exec();
+}
+
+void KeyImportDetailDialog::createGeneralInfoBox()
+{
+ // GridBox for general import information
+ generalInfoBox = new QGroupBox(tr("Genral key import info"));
+ QGridLayout *generalInfoBoxLayout = new QGridLayout(generalInfoBox);
+
+ generalInfoBoxLayout->addWidget(new QLabel(tr("Considered:")),1,0);
+ generalInfoBoxLayout->addWidget(new QLabel(QString::number(mResult.considered)),1,1);
+ int row=2;
+ if (mResult.unchanged != 0){
+ generalInfoBoxLayout->addWidget(new QLabel(tr("Public unchanged:")),row,0);
+ generalInfoBoxLayout->addWidget(new QLabel(QString::number(mResult.unchanged)),row,1);
+ row++;
+ }
+ if (mResult.imported != 0){
+ generalInfoBoxLayout->addWidget(new QLabel(tr("Imported:")),row,0);
+ generalInfoBoxLayout->addWidget(new QLabel(QString::number(mResult.imported)),row,1);
+ row++;
+ }
+ if (mResult.not_imported != 0){
+ generalInfoBoxLayout->addWidget(new QLabel(tr("Not imported:")),row,0);
+ generalInfoBoxLayout->addWidget(new QLabel(QString::number(mResult.not_imported)),row,1);
+ row++;
+ }
+ if (mResult.secret_read != 0){
+ generalInfoBoxLayout->addWidget(new QLabel(tr("Private read:")),row,0);
+ generalInfoBoxLayout->addWidget(new QLabel(QString::number(mResult.secret_read)),row,1);
+ row++;
+ }
+ if (mResult.secret_imported != 0){
+ generalInfoBoxLayout->addWidget(new QLabel(tr("Private imported:")),row,0);
+ generalInfoBoxLayout->addWidget(new QLabel(QString::number(mResult.secret_imported)),row,1);
+ row++;
+ }
+ if (mResult.secret_unchanged != 0){
+ generalInfoBoxLayout->addWidget(new QLabel(tr("Private unchanged:")),row,0);
+ generalInfoBoxLayout->addWidget(new QLabel(QString::number(mResult.secret_unchanged)),row,1);
+ row++;
+ }
+}
+
+void KeyImportDetailDialog::createKeysTable()
+{
+ keysTable = new QTableWidget(this);
+ keysTable->setRowCount(0);
+ keysTable->setColumnCount(4);
+ keysTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ // Nothing is selectable
+ keysTable->setSelectionMode(QAbstractItemView::NoSelection);
+
+ QStringList headerLabels;
+ headerLabels << tr("Name") << tr("Email") << tr("Status") << tr("Fingerprint");
+ keysTable->verticalHeader()->hide();
+
+ keysTable->setHorizontalHeaderLabels(headerLabels);
+ int row = 0;
+ foreach (GpgImportedKey impKey, mResult.importedKeys) {
+ keysTable->setRowCount(row+1);
+ GpgKey key = mCtx->getKeyByFpr(impKey.fpr);
+ keysTable->setItem(row, 0, new QTableWidgetItem(key.name));
+ keysTable->setItem(row, 1, new QTableWidgetItem(key.email));
+ keysTable->setItem(row, 2 ,new QTableWidgetItem(getStatusString(impKey.importStatus)));
+ keysTable->setItem(row, 3, new QTableWidgetItem(impKey.fpr));
+ row++;
+ }
+ keysTable->horizontalHeader()->setResizeMode(0, QHeaderView::ResizeToContents);
+ keysTable->horizontalHeader()->setStretchLastSection(true);
+ keysTable->resizeColumnsToContents();
+}
+
+QString KeyImportDetailDialog::getStatusString(int keyStatus)
+{
+ QString statusString;
+ // keystatus is greater than 15, if key is private
+ if (keyStatus > 15) {
+ statusString.append(tr("private"));
+ keyStatus=keyStatus-16;
+ } else {
+ statusString.append(tr("public"));
+ }
+ if (keyStatus == 0) {
+ statusString.append(", "+tr("unchanged"));
+ } else {
+ if (keyStatus == 1) {
+ statusString.append(", "+tr("new key"));
+ } else {
+ if (keyStatus > 7) {
+ statusString.append(", "+tr("new subkey"));
+ keyStatus=keyStatus-8;
+ }
+ if (keyStatus > 3) {
+ statusString.append(", "+tr("new signature"));
+ keyStatus=keyStatus-4;
+ }
+ if (keyStatus > 1) {
+ statusString.append(", "+tr("new uid"));
+ keyStatus=keyStatus-2;
+ }
+ }
+ }
+ return statusString;
+}
+
+void KeyImportDetailDialog::createButtonBox()
+{
+ buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok);
+ connect(buttonBox, SIGNAL(accepted()), this, SLOT(close()));
+}
diff --git a/src/keyimportdetaildialog.h b/src/keyimportdetaildialog.h
new file mode 100644
index 0000000..dde1f54
--- /dev/null
+++ b/src/keyimportdetaildialog.h
@@ -0,0 +1,55 @@
+/*
+ * keyimportdetailsdialog.h
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef __KEYIMPORTDETAILSDIALOG_H__
+#define __KEYIMPORTDETAILSDIALOG_H__
+
+#include "gpgcontext.h"
+#include <gpgme.h>
+
+QT_BEGIN_NAMESPACE
+class QGridLayout;
+class QDialogButtonBox;
+QT_END_NAMESPACE
+
+class KeyImportDetailDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ KeyImportDetailDialog(GpgME::GpgContext* ctx, GpgImportInformation result, QWidget *parent = 0);
+
+private:
+ void createGeneralInfoBox();
+ void createKeyInfoBox();
+ void createKeysTable();
+ void createButtonBox();
+ QString getStatusString(int keyStatus);
+
+ QTableWidget *keysTable;
+ GpgME::GpgContext *mCtx;
+ QGroupBox *generalInfoBox;
+ QGroupBox *keyInfoBox;
+ QDialogButtonBox *buttonBox;
+ GpgImportInformation mResult;
+};
+
+#endif // __KEYIMPORTDETAILSDIALOG_H__
diff --git a/src/keylist.cpp b/src/keylist.cpp
new file mode 100644
index 0000000..cd01a2e
--- /dev/null
+++ b/src/keylist.cpp
@@ -0,0 +1,321 @@
+/*
+ * keylist.cpp
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "keylist.h"
+
+KeyList::KeyList(GpgME::GpgContext *ctx, QWidget *parent)
+ : QWidget(parent)
+{
+ mCtx = ctx;
+
+ mKeyList = new QTableWidget(this);
+ mKeyList->setColumnCount(6);
+ mKeyList->verticalHeader()->hide();
+ mKeyList->setShowGrid(false);
+ mKeyList->setColumnWidth(0, 24);
+ mKeyList->setColumnWidth(1, 20);
+ mKeyList->sortByColumn(2, Qt::AscendingOrder);
+ mKeyList->setSelectionBehavior(QAbstractItemView::SelectRows);
+ // hide id and fingerprint of key
+ mKeyList->setColumnHidden(4, true);
+ mKeyList->setColumnHidden(5, true);
+
+ // tableitems not editable
+ mKeyList->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ // no focus (rectangle around tableitems)
+ // may be it should focus on whole row
+ mKeyList->setFocusPolicy(Qt::NoFocus);
+
+ mKeyList->setAlternatingRowColors(true);
+
+ QStringList labels;
+ labels << "" << "" << tr("Name") << tr("EMail") << "id" << "fpr";
+ mKeyList->setHorizontalHeaderLabels(labels);
+ mKeyList->horizontalHeader()->setStretchLastSection(true);
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(mKeyList);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(3);
+ setLayout(layout);
+
+ popupMenu = new QMenu(this);
+ connect(mCtx, SIGNAL(signalKeyDBChanged()), this, SLOT(slotRefresh()));
+ setAcceptDrops(true);
+ slotRefresh();
+}
+
+void KeyList::slotRefresh()
+{
+ QStringList *keyList;
+ keyList = getChecked();
+ // while filling the table, sort enabled causes errors
+ mKeyList->setSortingEnabled(false);
+ mKeyList->clearContents();
+
+ GpgKeyList keys = mCtx->listKeys();
+ mKeyList->setRowCount(keys.size());
+
+ int row = 0;
+ GpgKeyList::iterator it = keys.begin();
+ while (it != keys.end()) {
+
+ QTableWidgetItem *tmp0 = new QTableWidgetItem();
+ tmp0->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
+ tmp0->setCheckState(Qt::Unchecked);
+ mKeyList->setItem(row, 0, tmp0);
+
+ if (it->privkey) {
+ QTableWidgetItem *tmp1 = new QTableWidgetItem(QIcon(":kgpg_key2.png"), "");
+ mKeyList->setItem(row, 1, tmp1);
+ }
+ QTableWidgetItem *tmp2 = new QTableWidgetItem(it->name);
+ tmp2->setToolTip(it->name);
+ mKeyList->setItem(row, 2, tmp2);
+ QTableWidgetItem *tmp3 = new QTableWidgetItem(it->email);
+ tmp3->setToolTip(it->email);
+ // strike out expired keys
+ if(it->expired || it->revoked) {
+ QFont strike = tmp2->font();
+ strike.setStrikeOut(true);
+ tmp2->setFont(strike);
+ tmp3->setFont(strike);
+ }
+ mKeyList->setItem(row, 3, tmp3);
+ QTableWidgetItem *tmp4 = new QTableWidgetItem(it->id);
+ mKeyList->setItem(row, 4, tmp4);
+ QTableWidgetItem *tmp5 = new QTableWidgetItem(it->fpr);
+ mKeyList->setItem(row, 5, tmp5);
+
+
+ it++;
+ ++row;
+ }
+ mKeyList->setSortingEnabled(true);
+ setChecked(keyList);
+}
+
+QStringList *KeyList::getChecked()
+{
+ QStringList *ret = new QStringList();
+ for (int i = 0; i < mKeyList->rowCount(); i++) {
+ if (mKeyList->item(i, 0)->checkState() == Qt::Checked) {
+ *ret << mKeyList->item(i, 4)->text();
+ }
+ }
+ return ret;
+}
+
+QStringList *KeyList::getAllPrivateKeys()
+{
+ QStringList *ret = new QStringList();
+ for (int i = 0; i < mKeyList->rowCount(); i++) {
+ if (mKeyList->item(i, 1)) {
+ *ret << mKeyList->item(i, 4)->text();
+ }
+ }
+ return ret;
+}
+
+QStringList *KeyList::getPrivateChecked()
+{
+ QStringList *ret = new QStringList();
+ for (int i = 0; i < mKeyList->rowCount(); i++) {
+ if ((mKeyList->item(i, 0)->checkState() == Qt::Checked) && (mKeyList->item(i, 1))) {
+ *ret << mKeyList->item(i, 4)->text();
+ }
+ }
+ return ret;
+}
+
+void KeyList::setChecked(QStringList *keyIds)
+{
+ if (!keyIds->isEmpty()) {
+ for (int i = 0; i < mKeyList->rowCount(); i++) {
+ if (keyIds->contains(mKeyList->item(i, 4)->text())) {
+ mKeyList->item(i, 0)->setCheckState(Qt::Checked);
+ }
+ }
+ }
+}
+
+QStringList *KeyList::getSelected()
+{
+ QStringList *ret = new QStringList();
+
+ for (int i = 0; i < mKeyList->rowCount(); i++) {
+ if (mKeyList->item(i, 0)->isSelected() == 1) {
+ *ret << mKeyList->item(i, 4)->text();
+ }
+ }
+ return ret;
+}
+
+bool KeyList::containsPrivateKeys()
+{
+ for (int i = 0; i < mKeyList->rowCount(); i++) {
+ if (mKeyList->item(i, 1)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void KeyList::setColumnWidth(int row, int size)
+{
+ mKeyList->setColumnWidth(row, size);
+}
+
+void KeyList::contextMenuEvent(QContextMenuEvent *event)
+{
+ popupMenu->exec(event->globalPos());
+}
+
+void KeyList::addMenuAction(QAction *act)
+{
+ popupMenu->addAction(act);
+}
+
+void KeyList::dropEvent(QDropEvent* event)
+{
+// importKeyDialog();
+ QSettings settings;
+
+ QDialog *dialog = new QDialog();
+
+ dialog->setWindowTitle(tr("Import Keys"));
+ QLabel *label;
+ label = new QLabel(tr("You've dropped something on the keylist.\n gpg4usb will now try to import key(s).")+"\n");
+
+ // "always import keys"-CheckBox
+ QCheckBox *checkBox = new QCheckBox(tr("Always import without bothering."));
+ if (settings.value("general/confirmImportKeys").toBool()) checkBox->setCheckState(Qt::Unchecked);
+
+ // Buttons for ok and cancel
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+ connect(buttonBox, SIGNAL(accepted()), dialog, SLOT(accept()));
+ connect(buttonBox, SIGNAL(rejected()), dialog, SLOT(reject()));
+
+ QVBoxLayout *vbox = new QVBoxLayout();
+ vbox->addWidget(label);
+ vbox->addWidget(checkBox);
+ vbox->addWidget(buttonBox);
+
+ dialog->setLayout(vbox);
+
+ if (settings.value("general/confirmImportKeys",Qt::Checked).toBool())
+ {
+ dialog->exec();
+ if (dialog->result() == QDialog::Rejected) {
+ return;
+ }
+ if (checkBox->isChecked()){
+ settings.setValue("general/confirmImportKeys", false);
+ } else {
+ settings.setValue("general/confirmImportKeys", true);
+
+ }
+ }
+
+ if (event->mimeData()->hasUrls())
+ {
+ foreach (QUrl tmp, event->mimeData()->urls())
+ {
+ QFile file;
+ file.setFileName(tmp.toLocalFile());
+ if (!file.open(QIODevice::ReadOnly)) {
+ qDebug() << tr("Couldn't Open File: ") + tmp.toString();
+ }
+ QByteArray inBuffer = file.readAll();
+ this->importKeys(inBuffer);
+ file.close();
+ }
+ } else {
+ QByteArray inBuffer(event->mimeData()->text().toUtf8());
+ this->importKeys(inBuffer);
+ }
+}
+
+void KeyList::dragEnterEvent(QDragEnterEvent *event)
+{
+ event->acceptProposedAction();
+}
+
+/** set background color for Keys and put them to top
+ *
+ */
+void KeyList::markKeys(QStringList *keyIds)
+{
+ foreach(QString id, *keyIds) {
+ qDebug() << "marked: " << id;
+ }
+}
+
+void KeyList::importKeys(QByteArray inBuffer)
+{
+ GpgImportInformation result = mCtx->importKey(inBuffer);
+ new KeyImportDetailDialog(mCtx, result, this);
+}
+
+void KeyList::uploadKeyToServer(QByteArray *keys)
+{
+ QUrl reqUrl("http://localhost:11371/pks/add");
+ qnam = new QNetworkAccessManager(this);
+
+ QUrl params;
+ keys->replace("\n", "%0D%0A")
+ .replace("(", "%28")
+ .replace(")", "%29")
+ .replace("/", "%2F")
+ .replace(":", "%3A")
+ .replace("+","%2B")
+ .replace(' ', '+');
+
+ params.addEncodedQueryItem("keytext", *keys);
+ QNetworkRequest req(reqUrl);
+
+ req.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");
+
+ QNetworkReply *reply = qnam->post(req,params.encodedQuery());
+ connect(reply, SIGNAL(finished()),
+ this, SLOT(uploadFinished()));
+ qDebug() << "REQURL: " << reqUrl;
+ qDebug() << "PARAMS.ENCODED: " << params.toEncoded();
+}
+
+void KeyList::uploadFinished()
+{
+ QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
+
+ QByteArray response = reply->readAll();
+ qDebug() << "RESPNOSE: " << response.data();
+ //reply->readAll();
+ qDebug() << "ERROR: " << reply->error();
+ if (reply->error()) {
+ qDebug() << "Error while contacting keyserver!";
+ return;
+ } else {
+ qDebug() << "Success while contacting keyserver!";
+ }
+
+ reply->deleteLater();
+ reply = 0;
+}
diff --git a/src/keylist.h b/src/keylist.h
new file mode 100644
index 0000000..0909291
--- /dev/null
+++ b/src/keylist.h
@@ -0,0 +1,76 @@
+/*
+ * keylist.h
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef __KEYLIST_H__
+#define __KEYLIST_H__
+
+#include "gpgcontext.h"
+#include "keyimportdetaildialog.h"
+#include <QNetworkAccessManager>
+#include <QtNetwork>
+
+QT_BEGIN_NAMESPACE
+class QWidget;
+class QVBoxLayout;
+class QLabel;
+class QTableWidget;
+class QMenu;
+QT_END_NAMESPACE
+
+class KeyList : public QWidget
+{
+ Q_OBJECT
+
+public:
+ KeyList(GpgME::GpgContext *ctx, QWidget *parent = 0);
+ void setColumnWidth(int row, int size);
+ void addMenuAction(QAction *act);
+
+ QStringList *getChecked();
+ QStringList *getPrivateChecked();
+ QStringList *getAllPrivateKeys();
+
+ void setChecked(QStringList *keyIds);
+ //QStringList *getPrivateChecked();
+ QStringList *getSelected();
+ void markKeys(QStringList *keyIds);
+ bool containsPrivateKeys();
+
+public slots:
+ void slotRefresh();
+ void uploadKeyToServer(QByteArray *keys);
+
+private:
+ void importKeys(QByteArray inBuffer);
+ GpgME::GpgContext *mCtx;
+ QTableWidget *mKeyList;
+ QMenu *popupMenu;
+ QNetworkAccessManager *qnam;
+
+private slots:
+ void uploadFinished();
+
+protected:
+ void contextMenuEvent(QContextMenuEvent *event);
+ void dragEnterEvent(QDragEnterEvent *event);
+ void dropEvent(QDropEvent* event);};
+
+#endif // __KEYLIST_H__
diff --git a/src/keymgmt.cpp b/src/keymgmt.cpp
new file mode 100755
index 0000000..c17fd86
--- /dev/null
+++ b/src/keymgmt.cpp
@@ -0,0 +1,289 @@
+/*
+ *
+ * keymgmt.cpp
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "keymgmt.h"
+
+KeyMgmt::KeyMgmt(GpgME::GpgContext *ctx, QWidget *parent ) : QMainWindow(parent)
+{
+ mCtx = ctx;
+
+ /* the list of Keys available*/
+ mKeyList = new KeyList(mCtx);
+ mKeyList->setColumnWidth(2, 250);
+ mKeyList->setColumnWidth(3, 250);
+ setCentralWidget(mKeyList);
+
+ createActions();
+ createMenus();
+ createToolBars();
+ connect(this,SIGNAL(signalStatusBarChanged(QString)),this->parent(),SLOT(slotSetStatusBarText(QString)));
+
+ /* Restore the iconstyle */
+ QSettings settings;
+ settings.sync();
+ QSize iconSize = settings.value("toolbar/iconsize", QSize(32, 32)).toSize();
+ Qt::ToolButtonStyle buttonStyle = static_cast<Qt::ToolButtonStyle>(settings.value("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon).toUInt());
+ this->setIconSize(iconSize);
+ this->setToolButtonStyle(buttonStyle);
+
+ // state sets pos & size of dock-widgets
+ this->restoreState(settings.value("keymgmt/windowState").toByteArray());
+
+ // Restore window size & location
+ if (settings.value("window/windowSave").toBool()) {
+ QPoint pos = settings.value("keymgmt/pos", QPoint(100, 100)).toPoint();
+ QSize size = settings.value("keymgmt/size", QSize(800, 450)).toSize();
+ this->resize(size);
+ this->move(pos);
+ } else {
+ this->resize(QSize(800, 400));
+ }
+
+ setWindowTitle(tr("Keymanagement"));
+ mKeyList->addMenuAction(deleteSelectedKeysAct);
+ mKeyList->addMenuAction(showKeyDetailsAct);
+}
+
+void KeyMgmt::createActions()
+{
+ closeAct = new QAction(tr("&Close Key Management"), this);
+ closeAct->setShortcut(tr("Ctrl+Q"));
+ closeAct->setIcon(QIcon(":exit.png"));
+ closeAct->setToolTip(tr("Close Key Management"));
+ connect(closeAct, SIGNAL(triggered()), this, SLOT(close()));
+
+ importKeyFromFileAct = new QAction(tr("&File"), this);
+ importKeyFromFileAct->setIcon(QIcon(":import_key_from_file.png"));
+ importKeyFromFileAct->setToolTip(tr("Import New Key From File"));
+ connect(importKeyFromFileAct, SIGNAL(triggered()), this, SLOT(slotImportKeyFromFile()));
+
+ importKeyFromClipboardAct = new QAction(tr("&Clipboard"), this);
+ importKeyFromClipboardAct->setIcon(QIcon(":import_key_from_clipboard.png"));
+ importKeyFromClipboardAct->setToolTip(tr("Import New Key From Clipboard"));
+ connect(importKeyFromClipboardAct, SIGNAL(triggered()), this, SLOT(slotImportKeyFromClipboard()));
+
+ importKeyFromKeyServerAct = new QAction(tr("&Keyserver"), this);
+ importKeyFromKeyServerAct->setIcon(QIcon(":import_key_from_server.png"));
+ importKeyFromKeyServerAct->setToolTip(tr("Import New Key From Keyserver"));
+ connect(importKeyFromKeyServerAct, SIGNAL(triggered()), this, SLOT(slotImportKeyFromKeyServer()));
+
+ exportKeyToClipboardAct = new QAction(tr("Export To &Clipboard"), this);
+ exportKeyToClipboardAct->setIcon(QIcon(":export_key_to_clipboard.png"));
+ exportKeyToClipboardAct->setToolTip(tr("Export Selected Key(s) To Clipboard"));
+ connect(exportKeyToClipboardAct, SIGNAL(triggered()), this, SLOT(slotExportKeyToClipboard()));
+
+ exportKeyToFileAct = new QAction(tr("Export To &File"), this);
+ exportKeyToFileAct->setIcon(QIcon(":export_key_to_file.png"));
+ exportKeyToFileAct->setToolTip(tr("Export Selected Key(s) To File"));
+ connect(exportKeyToFileAct, SIGNAL(triggered()), this, SLOT(slotExportKeyToFile()));
+
+ deleteSelectedKeysAct = new QAction(tr("Delete Selected Key(s)"), this);
+ deleteSelectedKeysAct->setToolTip(tr("Delete the Selected keys"));
+ connect(deleteSelectedKeysAct, SIGNAL(triggered()), this, SLOT(slotDeleteSelectedKeys()));
+
+ deleteCheckedKeysAct = new QAction(tr("Delete Checked Key(s)"), this);
+ deleteCheckedKeysAct->setToolTip(tr("Delete the Checked keys"));
+ deleteCheckedKeysAct->setIcon(QIcon(":button_cancel.png"));
+ connect(deleteCheckedKeysAct, SIGNAL(triggered()), this, SLOT(slotDeleteCheckedKeys()));
+
+ generateKeyDialogAct = new QAction(tr("Generate Key"), this);
+ generateKeyDialogAct->setToolTip(tr("Generate New Key"));
+ generateKeyDialogAct->setIcon(QIcon(":key_generate.png"));
+ connect(generateKeyDialogAct, SIGNAL(triggered()), this, SLOT(slotGenerateKeyDialog()));
+
+ showKeyDetailsAct = new QAction(tr("Show Keydetails"), this);
+ showKeyDetailsAct->setToolTip(tr("Show Details for this Key"));
+ connect(showKeyDetailsAct, SIGNAL(triggered()), this, SLOT(slotShowKeyDetails()));
+}
+
+void KeyMgmt::createMenus()
+{
+ fileMenu = menuBar()->addMenu(tr("&File"));
+ fileMenu->addAction(closeAct);
+
+ keyMenu = menuBar()->addMenu(tr("&Key"));
+ importKeyMenu = keyMenu->addMenu(tr("&Import Key From..."));
+ importKeyMenu->addAction(importKeyFromFileAct);
+ importKeyMenu->addAction(importKeyFromClipboardAct);
+ importKeyMenu->addAction(importKeyFromKeyServerAct);
+ keyMenu->addAction(exportKeyToFileAct);
+ keyMenu->addAction(exportKeyToClipboardAct);
+ keyMenu->addSeparator();
+ keyMenu->addAction(deleteCheckedKeysAct);
+ keyMenu->addAction(generateKeyDialogAct);
+}
+
+void KeyMgmt::createToolBars()
+{
+ QToolBar *keyToolBar = addToolBar(tr("Key"));
+ keyToolBar->setObjectName("keytoolbar");
+
+ // add button with popup menu for import
+ QToolButton* toolButton = new QToolButton(this);
+ toolButton->setMenu(importKeyMenu);
+ toolButton->setPopupMode(QToolButton::InstantPopup);
+ toolButton->setIcon(QIcon(":key_import.png"));
+ toolButton->setToolTip(tr("Import key"));
+ toolButton->setText(tr("Import key from"));
+ toolButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
+ keyToolBar->addWidget(toolButton);
+
+ keyToolBar->addSeparator();
+ keyToolBar->addAction(deleteCheckedKeysAct);
+ keyToolBar->addSeparator();
+ keyToolBar->addAction(exportKeyToFileAct);
+ keyToolBar->addAction(exportKeyToClipboardAct);
+
+}
+
+void KeyMgmt::slotImportKeys(QByteArray inBuffer)
+{
+ GpgImportInformation result = mCtx->importKey(inBuffer);
+ new KeyImportDetailDialog(mCtx, result, this);
+
+}
+
+void KeyMgmt::slotImportKeyFromFile()
+{
+ QString fileName = QFileDialog::getOpenFileName(this, tr("Open Key"), "", tr("Key Files") + " (*.asc *.txt);;"+tr("Keyring files")+" (*.gpg);;All Files (*)");
+ if (! fileName.isNull()) {
+ QFile file;
+ file.setFileName(fileName);
+ if (!file.open(QIODevice::ReadOnly)) {
+ qDebug() << tr("Couldn't Open File: ") + fileName;
+ return;
+ }
+ QByteArray inBuffer = file.readAll();
+ slotImportKeys(inBuffer);
+ file.close();
+ }
+}
+
+void KeyMgmt::slotImportKeyFromKeyServer()
+{
+ importDialog = new KeyServerImportDialog(mCtx, mKeyList, this);
+ importDialog->show();
+}
+
+void KeyMgmt::slotImportKeyFromClipboard()
+{
+ QClipboard *cb = QApplication::clipboard();
+ slotImportKeys(cb->text(QClipboard::Clipboard).toAscii());
+}
+
+void KeyMgmt::slotDeleteSelectedKeys()
+{
+ deleteKeysWithWarning(mKeyList->getSelected());
+}
+
+void KeyMgmt::slotDeleteCheckedKeys()
+{
+ deleteKeysWithWarning(mKeyList->getChecked());
+}
+
+void KeyMgmt::deleteKeysWithWarning(QStringList *uidList)
+{
+ /**
+ * TODO: Different Messages for private/public key, check if
+ * more than one selected... compare to seahorse "delete-dialog"
+ */
+
+ if (uidList->isEmpty()) {
+ return;
+ }
+ QString keynames;
+ foreach (QString uid, *uidList) {
+ keynames.append(QString::fromUtf8(mCtx->getKeyDetails(uid)->uids->name));
+ keynames.append("<i> &lt;");
+ keynames.append(QString::fromUtf8(mCtx->getKeyDetails(uid)->uids->email));
+ keynames.append("&gt; </i><br/>");
+ }
+
+ int ret = QMessageBox::warning(this, tr("Deleting Keys"),
+ "<b>"+tr("Are you sure that you want to delete the following keys?")+"</b><br/><br/>"+keynames+
+ +"<br/>"+tr("The action can not be undone."),
+ QMessageBox::No | QMessageBox::Yes);
+
+ if (ret == QMessageBox::Yes) {
+ mCtx->deleteKeys(uidList);
+ }
+}
+
+void KeyMgmt::slotShowKeyDetails()
+{
+ if (mKeyList->getSelected()->isEmpty()) {
+ return;
+ }
+
+ // TODO: first...?
+ gpgme_key_t key = mCtx->getKeyDetails(mKeyList->getSelected()->first());
+
+ new KeyDetailsDialog(mCtx, key);
+}
+
+void KeyMgmt::slotExportKeyToFile()
+{
+ QByteArray *keyArray = new QByteArray();
+ if (!mCtx->exportKeys(mKeyList->getChecked(), keyArray)) {
+ return;
+ }
+ gpgme_key_t key = mCtx->getKeyDetails(mKeyList->getChecked()->first());
+ QString fileString = QString::fromUtf8(key->uids->name) + " " + QString::fromUtf8(key->uids->email) + "(" + QString(key->subkeys->keyid)+ ")_pub.asc";
+
+ QString fileName = QFileDialog::getSaveFileName(this, tr("Export Key To File"), fileString, tr("Key Files") + " (*.asc *.txt);;All Files (*)");
+ QFile file(fileName);
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
+ return;
+ QTextStream stream(&file);
+ stream << *keyArray;
+ file.close();
+ delete keyArray;
+ emit signalStatusBarChanged(QString(tr("key(s) exported")));
+}
+
+void KeyMgmt::slotExportKeyToClipboard()
+{
+ QByteArray *keyArray = new QByteArray();
+ QClipboard *cb = QApplication::clipboard();
+ if (!mCtx->exportKeys(mKeyList->getChecked(), keyArray)) {
+ return;
+ }
+ cb->setText(*keyArray);
+ delete keyArray;
+}
+
+void KeyMgmt::slotGenerateKeyDialog()
+{
+ KeyGenDialog *keyGenDialog = new KeyGenDialog(mCtx,this);
+ keyGenDialog->show();
+}
+
+void KeyMgmt::closeEvent(QCloseEvent *event)
+{
+ QSettings settings;
+ //settings.setValue("geometry", saveGeometry());
+ settings.setValue("keymgmt/windowState", saveState());
+ settings.setValue("keymgmt/pos", pos());
+ settings.setValue("keymgmt/size", size());
+
+ QMainWindow::closeEvent(event);
+}
diff --git a/src/keymgmt.h b/src/keymgmt.h
new file mode 100755
index 0000000..22a8b66
--- /dev/null
+++ b/src/keymgmt.h
@@ -0,0 +1,92 @@
+/*
+ * keymgmt.h
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef __KEYMGMT_H__
+#define __KEYMGMT_H__
+
+#include "keylist.h"
+#include "keygenthread.h"
+#include "keydetailsdialog.h"
+#include "keyimportdetaildialog.h"
+#include "keyserverimportdialog.h"
+#include "keygendialog.h"
+#include <QtGui>
+
+QT_BEGIN_NAMESPACE
+class QMainWindow;
+class iostream;
+class QFileDialog;
+class QIcon;
+class QAction;
+class QApplication;
+QT_END_NAMESPACE
+
+class KeyMgmt : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ KeyMgmt(GpgME::GpgContext* ctx, QWidget *parent = 0);
+ QAction *importKeyFromClipboardAct;
+ QAction *importKeyFromFileAct;
+ QAction *importKeyFromKeyServerAct;
+
+public slots:
+ void slotImportKeyFromFile();
+ void slotImportKeyFromClipboard();
+ void slotImportKeyFromKeyServer();
+ void slotImportKeys(QByteArray inBuffer);
+ void slotExportKeyToFile();
+ void slotExportKeyToClipboard();
+ void slotDeleteSelectedKeys();
+ void slotDeleteCheckedKeys();
+ void slotGenerateKeyDialog();
+ void slotShowKeyDetails();
+
+signals:
+ void signalStatusBarChanged(QString);
+
+private:
+ void createMenus();
+ void createActions();
+ void createToolBars();
+ void deleteKeysWithWarning(QStringList *uidList);
+
+ KeyList *mKeyList;
+ GpgME::GpgContext *mCtx;
+ QMenu *fileMenu;
+ QMenu *keyMenu;
+ QMenu *importKeyMenu;
+ QAction *exportKeyToFileAct;
+ QAction *exportKeyToClipboardAct;
+ QAction *deleteCheckedKeysAct;
+ QAction *deleteSelectedKeysAct;
+ QAction *generateKeyDialogAct;
+ QAction *closeAct;
+ QAction *showKeyDetailsAct;
+ QMessageBox msgbox;
+ KeyServerImportDialog *importDialog;
+
+protected:
+ void closeEvent(QCloseEvent *event);
+};
+
+#endif // __KEYMGMT_H__
diff --git a/src/keyserverimportdialog.cpp b/src/keyserverimportdialog.cpp
new file mode 100644
index 0000000..819dfc0
--- /dev/null
+++ b/src/keyserverimportdialog.cpp
@@ -0,0 +1,313 @@
+/*
+ *
+ * keyserverimportdialog.cpp
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "keyserverimportdialog.h"
+
+KeyServerImportDialog::KeyServerImportDialog(GpgME::GpgContext *ctx, KeyList *keyList, QWidget *parent)
+ : QDialog(parent)
+{
+ mCtx = ctx;
+ mKeyList = keyList;
+ // Buttons
+ closeButton = createButton(tr("&Close"), SLOT(close()));
+ importButton = createButton(tr("&Import"), SLOT(slotImport()));
+ searchButton = createButton(tr("&Search"), SLOT(slotSearch()));
+
+ // Line edit for search string
+ searchLabel = new QLabel(tr("Search string:"));
+ searchLineEdit = new QLineEdit();
+
+ // combobox for keyserverlist
+ keyServerLabel = new QLabel(tr("Keyserver:"));
+ keyServerComboBox = createComboBox();
+
+ // table containing the keys found
+ createKeysTable();
+ message = new QLabel;
+ icon = new QLabel;
+
+ // Layout for messagebox
+ QHBoxLayout *messageLayout= new QHBoxLayout;
+ messageLayout->addWidget(icon);
+ messageLayout->addWidget(message);
+ messageLayout->addStretch();
+
+ // Layout for import and close button
+ QHBoxLayout *buttonsLayout = new QHBoxLayout;
+ buttonsLayout->addStretch();
+ buttonsLayout->addWidget(importButton);
+ buttonsLayout->addWidget(closeButton);
+
+ QGridLayout *mainLayout = new QGridLayout;
+ mainLayout->addWidget(searchLabel, 1, 0);
+ mainLayout->addWidget(searchLineEdit, 1, 1);
+ mainLayout->addWidget(searchButton,1, 2);
+ mainLayout->addWidget(keyServerLabel, 2, 0);
+ mainLayout->addWidget(keyServerComboBox, 2, 1);
+ mainLayout->addWidget(keysTable, 3, 0, 1, 3);
+ mainLayout->addLayout(messageLayout, 4, 0, 1, 3);
+ mainLayout->addLayout(buttonsLayout, 5, 0, 1, 3);
+
+ this->setLayout(mainLayout);
+ this->setWindowTitle(tr("Import Keys from Keyserver"));
+ this->resize(700, 300);
+ this->setModal(true);
+}
+
+QPushButton *KeyServerImportDialog::createButton(const QString &text, const char *member)
+{
+ QPushButton *button = new QPushButton(text);
+ connect(button, SIGNAL(clicked()), this, member);
+ return button;
+}
+
+QComboBox *KeyServerImportDialog::createComboBox()
+{
+ QComboBox *comboBox = new QComboBox;
+ comboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+
+ // Read keylist from ini-file and fill it into combobox
+ QSettings settings;
+ comboBox->addItems(settings.value("keyserver/keyServerList").toStringList());
+
+ // set default keyserver in combobox
+ QString keyserver = settings.value("keyserver/defaultKeyServer").toString();
+ comboBox->setCurrentIndex(comboBox->findText(keyserver));
+
+ return comboBox;
+}
+
+void KeyServerImportDialog::createKeysTable()
+{
+ keysTable = new QTableWidget();
+ keysTable->setColumnCount(4);
+
+ // always a whole row is marked
+ keysTable->setSelectionBehavior(QAbstractItemView::SelectRows);
+ keysTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+
+ // Make just one row selectable
+ keysTable->setSelectionMode(QAbstractItemView::SingleSelection);
+
+ QStringList labels;
+ labels << tr("UID") << tr("Creation date") << tr("KeyID") << tr("Tag");
+ keysTable->horizontalHeader()->setResizeMode(0, QHeaderView::ResizeToContents);
+ keysTable->setHorizontalHeaderLabels(labels);
+ keysTable->verticalHeader()->hide();
+
+ connect(keysTable, SIGNAL(cellActivated(int,int)),
+ this, SLOT(slotImport()));
+}
+
+void KeyServerImportDialog::setMessage(const QString &text, bool error)
+{
+ message->setText(text);
+ if (error) {
+ QIcon undoicon = QIcon::fromTheme("dialog-error");
+ QPixmap pixmap = undoicon.pixmap(QSize(32,32),QIcon::Normal,QIcon::On);
+ icon->setPixmap(pixmap);
+ } else {
+ QIcon undoicon = QIcon::fromTheme("dialog-information");
+ QPixmap pixmap = undoicon.pixmap(QSize(32,32),QIcon::Normal,QIcon::On);
+ icon->setPixmap(pixmap);
+ }
+}
+
+void KeyServerImportDialog::slotSearch()
+{
+ QUrl url = keyServerComboBox->currentText()+":11371/pks/lookup?search="+searchLineEdit->text()+"&op=index&options=mr";
+ qnam = new QNetworkAccessManager(this);
+ QNetworkReply* reply = qnam->get(QNetworkRequest(url));
+ connect(reply, SIGNAL(finished()),
+ this, SLOT(slotSearchFinished()));
+}
+
+void KeyServerImportDialog::slotSearchFinished()
+{
+ QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
+
+ keysTable->clearContents();
+ keysTable->setRowCount(0);
+ QString firstLine = QString(reply->readLine(1024));
+
+ QVariant redirectionTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
+ if (reply->error()) {
+ setMessage(tr("Couldn't contact keyserver!"),true);
+ //setMessage(reply->error());
+ qDebug() << reply->error();
+ }
+ if (firstLine.contains("Error"))
+ {
+ QString text= QString(reply->readLine(1024));
+ if (text.contains("Too many responses")) {
+ setMessage(tr("Too many responses from keyserver!"),true);
+ } else if (text.contains("No keys found")) {
+ // if string looks like hex string, search again with 0x prepended
+ QRegExp rx("[0-9A-Fa-f]*");
+ QString query = searchLineEdit->text();
+ if (rx.exactMatch(query)) {
+ setMessage(tr("No keys found, input may be kexId, retrying search with 0x."),true);
+ searchLineEdit->setText(query.prepend("0x"));
+ this->slotSearch();
+ } else {
+ setMessage(tr("No keys found containing the search string!"),true);
+ }
+ } else if (text.contains("Insufficiently specific words")) {
+ setMessage(tr("Insufficiently specific search string!"),true);
+ } else {
+ setMessage(text, true);
+ }
+ } else {
+ int row = 0;
+ char buff[1024];
+ bool strikeout=false;
+ while (reply->readLine(buff,sizeof(buff)) !=-1) {
+ QString decoded = QString::fromUtf8(QByteArray::fromPercentEncoding(buff));
+ QStringList line = decoded.split(":");
+
+ //TODO: have a look at two following pub lines
+ if (line[0] == "pub") {
+ strikeout=false;
+
+ QString flags = line[line.size()-1];
+
+ keysTable->setRowCount(row+1);
+
+ // flags can be "d" for disabled, "r" for revoked
+ // or "e" for expired
+ if (flags.contains("r") or flags.contains("d") or flags.contains("e")) {
+ strikeout=true;
+ if (flags.contains("e")) {
+ keysTable->setItem(row, 3, new QTableWidgetItem( QString("expired")));
+ }
+ if (flags.contains("r")) {
+ keysTable->setItem(row, 3, new QTableWidgetItem( QString(tr("revoked"))));
+ }
+ if (flags.contains("d")) {
+ keysTable->setItem(row, 3, new QTableWidgetItem( QString(tr("disabled"))));
+ }
+ }
+
+ QStringList line2 = QString(reply->readLine()).split(":");
+
+ QTableWidgetItem *uid = new QTableWidgetItem();
+ if (line2.size() > 1) {
+ uid->setText(line2[1]);
+ keysTable->setItem(row, 0, uid);
+ }
+ QTableWidgetItem *creationdate = new QTableWidgetItem(QDateTime::fromTime_t(line[4].toInt()).toString("dd. MMM. yyyy"));
+ keysTable->setItem(row, 1, creationdate);
+ QTableWidgetItem *keyid = new QTableWidgetItem(line[1]);
+ keysTable->setItem(row, 2, keyid);
+ if (strikeout) {
+ QFont strike = uid->font();
+ strike.setStrikeOut(true);
+ uid->setFont(strike);
+ creationdate->setFont(strike);
+ keyid->setFont(strike);
+ }
+ row++;
+ } else {
+ if (line[0] == "uid") {
+ QStringList l;
+ int height=keysTable->rowHeight(row-1);
+ keysTable->setRowHeight(row-1,height+16);
+ QString tmp=keysTable->item(row-1,0)->text();
+ tmp.append(QString("\n")+line[1]);
+ QTableWidgetItem *tmp1 = new QTableWidgetItem(tmp);
+ keysTable->setItem(row-1,0,tmp1);
+ if (strikeout) {
+ QFont strike = tmp1->font();
+ strike.setStrikeOut(true);
+ tmp1->setFont(strike);
+ }
+ }
+ }
+ setMessage(tr("%1 keys found. Doubleclick a key to import it.").arg(row),false);
+ }
+ keysTable->resizeColumnsToContents();
+ }
+ reply->deleteLater();
+ reply = 0;
+}
+
+void KeyServerImportDialog::slotImport()
+{
+ if ( keysTable->currentRow() > -1 ) {
+ QString keyid = keysTable->item(keysTable->currentRow(),2)->text();
+ QUrl url = keyServerComboBox->currentText();
+ slotImport(QStringList(keyid), url);
+ }
+}
+
+void KeyServerImportDialog::slotImport(QStringList keyIds)
+{
+ QSettings settings;
+ QString keyserver=settings.value("keyserver/defaultKeyServer").toString();
+ QUrl url(keyserver);
+ slotImport(keyIds, url);
+}
+
+
+void KeyServerImportDialog::slotImport(QStringList keyIds, QUrl keyServerUrl)
+{
+ foreach(QString keyId, keyIds) {
+ QUrl reqUrl(keyServerUrl.scheme() + "://" + keyServerUrl.host() + ":11371/pks/lookup?op=get&search=0x"+keyId+"&options=mr");
+ //qDebug() << "req to " << reqUrl;
+ qnam = new QNetworkAccessManager(this);
+ QNetworkReply *reply = qnam->get(QNetworkRequest(reqUrl));
+ connect(reply, SIGNAL(finished()),
+ this, SLOT(slotImportFinished()));
+ }
+}
+
+void KeyServerImportDialog::slotImportFinished()
+{
+ QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
+
+ QByteArray key = reply->readAll();
+
+ QVariant redirectionTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
+ if (reply->error()) {
+ setMessage(tr("Error while contacting keyserver!"),true);
+ return;
+ }
+ this->importKeys(key.constData());
+ setMessage(tr("Key imported"),false);
+
+ // Add keyserver to list in config-file, if it isn't contained
+ QSettings settings;
+ QStringList keyServerList = settings.value("keyserver/keyServerList").toStringList();
+ if (!keyServerList.contains(keyServerComboBox->currentText()))
+ {
+ keyServerList.append(keyServerComboBox->currentText());
+ settings.setValue("keyserver/keyServerList", keyServerList);
+ }
+ reply->deleteLater();
+ reply = 0;
+}
+
+void KeyServerImportDialog::importKeys(QByteArray inBuffer)
+{
+ GpgImportInformation result = mCtx->importKey(inBuffer);
+ new KeyImportDetailDialog(mCtx, result, this);
+}
diff --git a/src/keyserverimportdialog.h b/src/keyserverimportdialog.h
new file mode 100644
index 0000000..b33af57
--- /dev/null
+++ b/src/keyserverimportdialog.h
@@ -0,0 +1,89 @@
+/*
+ *
+ * keyserverimportdialog.h
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef __KEYSERVERIMPORTDIALOG_H__
+#define __KEYSERVERIMPORTDIALOG_H__
+
+#include "gpgcontext.h"
+#include "keyimportdetaildialog.h"
+#include "keylist.h"
+#include <QNetworkAccessManager>
+#include <QtNetwork>
+
+QT_BEGIN_NAMESPACE
+class QDialog;
+class QDir;
+class QUrl;
+class QtGui;
+class QPixmap;
+class QNetworkReply;
+class QComboBox;
+class QLabel;
+class QPushButton;
+class QTableWidget;
+class QTableWidgetItem;
+class QLineEdit;
+class QPalette;
+class QTreeWidget;
+class QTreeWidgetItem;
+QT_END_NAMESPACE
+
+class KeyServerImportDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ KeyServerImportDialog(GpgME::GpgContext *ctx, KeyList *keyList, QWidget *parent = 0);
+ void slotImport(QStringList keyIds);
+ void slotImport(QStringList keyIds, QUrl keyserverUrl);
+
+private slots:
+ void slotImport();
+ void slotSearchFinished();
+ void slotImportFinished();
+ void slotSearch();
+
+private:
+ void createKeysTable();
+ void setMessage(const QString &text, bool error);
+ void close();
+ void importKeys(QByteArray inBuffer);
+
+ QPushButton *createButton(const QString &text, const char *member);
+ QComboBox *createComboBox();
+ GpgME::GpgContext *mCtx;
+ KeyList *mKeyList;
+ QLineEdit *searchLineEdit;
+ QComboBox *keyServerComboBox;
+ QLabel *searchLabel;
+ QLabel *keyServerLabel;
+ QLabel *message;
+ QLabel *icon;
+ QPushButton *closeButton;
+ QPushButton *importButton;
+ QPushButton *searchButton;
+ QTableWidget *keysTable;
+ QUrl url;
+ QNetworkAccessManager *qnam;
+
+};
+#endif // __KEYSERVERIMPORTDIALOG_H__
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..019466b
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,121 @@
+/*
+ * main.cpp
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include <QApplication>
+#include "mainwindow.h"
+#include "gpgconstants.h"
+
+int main(int argc, char *argv[])
+{
+
+ Q_INIT_RESOURCE(gpg4usb);
+
+ QApplication app(argc, argv);
+
+ // get application path
+ QString appPath = qApp->applicationDirPath();
+
+ app.setApplicationVersion("0.3.3");
+ app.setApplicationName("gpg4usb");
+
+ // dont show icons in menus
+ app.setAttribute(Qt::AA_DontShowIconsInMenus);
+
+ // unicode in source
+ QTextCodec::setCodecForTr(QTextCodec::codecForName("utf-8"));
+
+ // set environment variables
+ // TODO:
+ // - unsetenv on windows?
+ // - wputenv or wputenv_s on windows? http://msdn.microsoft.com/en-us/library/d6dtz42k(v=vs.80).aspx
+ #ifndef _WIN32
+ // do not use GPG_AGENTS like seahorse, because they may save
+ // a password an pc's not owned by user
+ unsetenv("GPG_AGENT_INFO");
+ #endif
+
+// qDebug() << getenv("GNUPGHOME");
+
+#ifndef GPG4USB_NON_PORTABLE
+ // take care of gpg not creating directorys on harddisk
+ putenv(QString("GNUPGHOME=" + appPath + "/keydb").toAscii().data());
+
+ // this may help with newer gpgme versions on windows
+ //putenv(QString("GPGME_GPGPATH=" + appPath.replace("/", "\\") + "\\bin\\gpg.exe").toAscii().data());
+
+ // QSettings uses org-name for automatically setting path...
+ app.setOrganizationName("conf");
+
+ // specify default path & format for QSettings
+ QSettings::setPath(QSettings::IniFormat, QSettings::UserScope, appPath);
+#else
+ // in non portable conf should go to ~/.conf/gpg4usb
+ app.setOrganizationName("gpg4usb");
+ qDebug() << "gpg4usb non portable build";
+#endif
+
+ /*QLocale ql(lang);
+ foreach(QLocale l , QLocale::matchingLocales(ql.language(), ql.script(), ql.country())) {
+ qDebug() << "l: " << l.bcp47Name();
+ }*/
+
+ // css
+ QFile file(qApp->applicationDirPath() + "/css/default.css");
+ file.open(QFile::ReadOnly);
+ QString styleSheet = QLatin1String(file.readAll());
+ qApp->setStyleSheet(styleSheet);
+ file.close();
+
+ /**
+ * internationalisation. loop to restart mainwindow
+ * with changed translation when settings change.
+ */
+ QSettings::setDefaultFormat(QSettings::IniFormat);
+ QSettings settings;
+ QTranslator translator, translator2;
+ int return_from_event_loop_code;
+
+ do {
+ app.removeTranslator(&translator);
+ app.removeTranslator(&translator2);
+
+ QString lang = settings.value("int/lang", QLocale::system().name()).toString();
+ if (lang.isEmpty()) {
+ lang = QLocale::system().name();
+ }
+
+ translator.load("ts/gpg4usb_" + lang, appPath);
+ app.installTranslator(&translator);
+
+ // set qt translations
+ translator2.load("ts/qt_" + lang, appPath);
+ app.installTranslator(&translator2);
+
+ MainWindow window;
+ return_from_event_loop_code = app.exec();
+
+ } while( return_from_event_loop_code == RESTART_CODE);
+
+ return return_from_event_loop_code;
+}
+
+
+
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
new file mode 100644
index 0000000..6e00eb9
--- /dev/null
+++ b/src/mainwindow.cpp
@@ -0,0 +1,1043 @@
+/*
+ * mainwindow.cpp
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "mainwindow.h"
+
+MainWindow::MainWindow()
+{
+ mCtx = new GpgME::GpgContext();
+
+ /* get path were app was started */
+ setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
+ setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
+
+ edit = new TextEdit();
+ setCentralWidget(edit);
+
+ /* the list of Keys available*/
+ mKeyList = new KeyList(mCtx);
+
+ /* List of binary Attachments */
+ attachmentDockCreated = false;
+
+ /* Variable containing if restart is needed */
+ this->slotSetRestartNeeded(false);
+
+ keyMgmt = new KeyMgmt(mCtx, this);
+ keyMgmt->hide();
+ /* test attachmentdir for files alll 15s */
+ QTimer *timer = new QTimer(this);
+ connect(timer, SIGNAL(timeout()), this, SLOT(slotCheckAttachmentFolder()));
+ timer->start(5000);
+
+ createActions();
+ createMenus();
+ createToolBars();
+ createStatusBar();
+ createDockWindows();
+
+ connect(edit->tabWidget,SIGNAL(currentChanged(int)),this,SLOT(slotDisableTabActions(int)));
+
+ mKeyList->addMenuAction(appendSelectedKeysAct);
+ mKeyList->addMenuAction(copyMailAddressToClipboardAct);
+ mKeyList->addMenuAction(showKeyDetailsAct);
+ mKeyList->addMenuAction(refreshKeysFromKeyserverAct);
+ mKeyList->addMenuAction(uploadKeyToServerAct);
+
+ restoreSettings();
+
+ // open filename if provided as first command line parameter
+ QStringList args = qApp->arguments();
+ if (args.size() > 1) {
+ if (!args[1].startsWith("-")) {
+ if (QFile::exists(args[1]))
+ edit->loadFile(args[1]);
+ }
+ }
+ edit->curTextPage()->setFocus();
+ this->setWindowTitle(qApp->applicationName());
+ this->show();
+
+ // Show wizard, if the don't show wizard message box wasn't checked
+ // and keylist doesn't contain a private key
+ QSettings settings;
+ if (settings.value("wizard/showWizard",true).toBool() || !settings.value("wizard/nextPage").isNull()) {
+ slotStartWizard();
+ }
+}
+
+void MainWindow::restoreSettings()
+{
+ // state sets pos & size of dock-widgets
+ this->restoreState(settings.value("window/windowState").toByteArray());
+
+ // Restore window size & location
+ if (settings.value("window/windowSave").toBool()) {
+ QPoint pos = settings.value("window/pos", QPoint(100, 100)).toPoint();
+ QSize size = settings.value("window/size", QSize(800, 450)).toSize();
+ this->resize(size);
+ this->move(pos);
+ } else {
+ this->resize(QSize(800, 450));
+ this->move(QPoint(100, 100));
+ }
+
+ // Iconsize
+ QSize iconSize = settings.value("toolbar/iconsize", QSize(24, 24)).toSize();
+ this->setIconSize(iconSize);
+
+ importButton->setIconSize(iconSize);
+ fileEncButton->setIconSize(iconSize);
+ // set list of keyserver if not defined
+ QStringList *keyServerDefaultList;
+ keyServerDefaultList = new QStringList("http://pgp.mit.edu");
+ keyServerDefaultList->append("http://pool.sks-keyservers.net");
+ keyServerDefaultList->append("http://subkeys.pgp.net");
+
+ QStringList keyServerList = settings.value("keyserver/keyServerList", *keyServerDefaultList).toStringList();
+ settings.setValue("keyserver/keyServerList", keyServerList);
+
+ // set default keyserver, if it's not set
+ QString defaultKeyServer = settings.value("keyserver/defaultKeyServer", QString("http://pgp.mit.edu")).toString();
+ settings.setValue("keyserver/defaultKeyServer", defaultKeyServer);
+
+ // Iconstyle
+ Qt::ToolButtonStyle buttonStyle = static_cast<Qt::ToolButtonStyle>(settings.value("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon).toUInt());
+ this->setToolButtonStyle(buttonStyle);
+ importButton->setToolButtonStyle(buttonStyle);
+ fileEncButton->setToolButtonStyle(buttonStyle);
+
+ // Checked Keys
+ if (settings.value("keys/keySave").toBool()) {
+ QStringList keyIds = settings.value("keys/keyList").toStringList();
+ mKeyList->setChecked(&keyIds);
+ }
+}
+
+void MainWindow::saveSettings()
+{
+ // window position and size
+ settings.setValue("window/windowState", saveState());
+ settings.setValue("window/pos", pos());
+ settings.setValue("window/size", size());
+
+ // keyid-list of private checked keys
+ if (settings.value("keys/keySave").toBool()) {
+ QStringList *keyIds = mKeyList->getPrivateChecked();
+ if (!keyIds->isEmpty()) {
+ settings.setValue("keys/keyList", *keyIds);
+ } else {
+ settings.setValue("keys/keyList", "");
+ }
+ } else {
+ settings.remove("keys/keyList");
+ }
+}
+
+void MainWindow::createActions()
+{
+ /* Main Menu
+ */
+ newTabAct = new QAction(tr("&New"), this);
+ newTabAct->setIcon(QIcon(":misc_doc.png"));
+ QList<QKeySequence> newTabActShortcutList;
+ newTabActShortcutList.append(QKeySequence (Qt::CTRL + Qt::Key_N));
+ newTabActShortcutList.append(QKeySequence (Qt::CTRL + Qt::Key_T));
+ newTabAct->setShortcuts(newTabActShortcutList);
+ newTabAct->setToolTip(tr("Open a new file"));
+ connect(newTabAct, SIGNAL(triggered()), edit, SLOT(slotNewTab()));
+
+ openAct = new QAction(tr("&Open..."), this);
+ openAct->setIcon(QIcon(":fileopen.png"));
+ openAct->setShortcut(QKeySequence::Open);
+ openAct->setToolTip(tr("Open an existing file"));
+ connect(openAct, SIGNAL(triggered()), edit, SLOT(slotOpen()));
+
+ saveAct = new QAction(tr("&Save"), this);
+ saveAct->setIcon(QIcon(":filesave.png"));
+ saveAct->setShortcut(QKeySequence::Save);
+ saveAct->setToolTip(tr("Save the current File"));
+ connect(saveAct, SIGNAL(triggered()), edit, SLOT(slotSave()));
+
+ saveAsAct = new QAction(tr("Save &As")+"...", this);
+ saveAsAct->setIcon(QIcon(":filesaveas.png"));
+ saveAsAct->setShortcut(QKeySequence::SaveAs);
+ saveAsAct->setToolTip(tr("Save the current File as..."));
+ connect(saveAsAct, SIGNAL(triggered()), edit, SLOT(slotSaveAs()));
+
+ printAct = new QAction(tr("&Print"), this);
+ printAct->setIcon(QIcon(":fileprint.png"));
+ printAct->setShortcut(QKeySequence::Print);
+ printAct->setToolTip(tr("Print Document"));
+ connect(printAct, SIGNAL(triggered()), edit, SLOT(slotPrint()));
+
+ closeTabAct = new QAction(tr("&Close"), this);
+ closeTabAct->setShortcut(QKeySequence::Close);
+ closeTabAct->setToolTip(tr("Close file"));
+ connect(closeTabAct, SIGNAL(triggered()), edit, SLOT(slotCloseTab()));
+
+ quitAct = new QAction(tr("&Quit"), this);
+ quitAct->setShortcut(QKeySequence::Quit);
+ quitAct->setIcon(QIcon(":exit.png"));
+ quitAct->setToolTip(tr("Quit Program"));
+ connect(quitAct, SIGNAL(triggered()), this, SLOT(close()));
+
+ /* Edit Menu
+ */
+ undoAct = new QAction(tr("&Undo"), this);
+ undoAct->setShortcut(QKeySequence::Undo);
+ undoAct->setToolTip(tr("Undo Last Edit Action"));
+ connect(undoAct, SIGNAL(triggered()), edit, SLOT(slotUndo()));
+
+ redoAct = new QAction(tr("&Redo"), this);
+ redoAct->setShortcut(QKeySequence::Redo);
+ redoAct->setToolTip(tr("Redo Last Edit Action"));
+ connect(redoAct, SIGNAL(triggered()), edit, SLOT(slotRedo()));
+
+ zoomInAct = new QAction(tr("Zoom In"), this);
+ zoomInAct->setShortcut(QKeySequence::ZoomIn);
+ connect(zoomInAct, SIGNAL(triggered()), edit, SLOT(slotZoomIn()));
+
+ zoomOutAct = new QAction(tr("Zoom Out"), this);
+ zoomOutAct->setShortcut(QKeySequence::ZoomOut);
+ connect(zoomOutAct, SIGNAL(triggered()), edit, SLOT(slotZoomOut()));
+
+ pasteAct = new QAction(tr("&Paste"), this);
+ pasteAct->setIcon(QIcon(":button_paste.png"));
+ pasteAct->setShortcut(QKeySequence::Paste);
+ pasteAct->setToolTip(tr("Paste Text From Clipboard"));
+ connect(pasteAct, SIGNAL(triggered()), edit, SLOT(slotPaste()));
+
+ cutAct = new QAction(tr("Cu&t"), this);
+ cutAct->setIcon(QIcon(":button_cut.png"));
+ cutAct->setShortcut(QKeySequence::Cut);
+ cutAct->setToolTip(tr("Cut the current selection's contents to the "
+ "clipboard"));
+ connect(cutAct, SIGNAL(triggered()), edit, SLOT(slotCut()));
+
+ copyAct = new QAction(tr("&Copy"), this);
+ copyAct->setIcon(QIcon(":button_copy.png"));
+ copyAct->setShortcut(QKeySequence::Copy);
+ copyAct->setToolTip(tr("Copy the current selection's contents to the "
+ "clipboard"));
+ connect(copyAct, SIGNAL(triggered()), edit, SLOT(slotCopy()));
+
+ quoteAct = new QAction(tr("&Quote"), this);
+ quoteAct->setIcon(QIcon(":quote.png"));
+ quoteAct->setToolTip(tr("Quote whole text"));
+ connect(quoteAct, SIGNAL(triggered()), edit, SLOT(slotQuote()));
+
+ selectallAct = new QAction(tr("Select &All"), this);
+ selectallAct->setIcon(QIcon(":edit.png"));
+ selectallAct->setShortcut(QKeySequence::SelectAll);
+ selectallAct->setToolTip(tr("Select the whole text"));
+ connect(selectallAct, SIGNAL(triggered()), edit, SLOT(slotSelectAll()));
+
+ findAct = new QAction(tr("&Find"), this);
+ findAct->setShortcut(QKeySequence::Find);
+ findAct->setToolTip(tr("Find a word"));
+ connect(findAct, SIGNAL(triggered()), this, SLOT(slotFind()));
+
+ cleanDoubleLinebreaksAct = new QAction(tr("Remove &spacing"), this);
+ cleanDoubleLinebreaksAct->setIcon(QIcon(":format-line-spacing-triple.png"));
+ //cleanDoubleLineBreaksAct->setShortcut(QKeySequence::SelectAll);
+ cleanDoubleLinebreaksAct->setToolTip(tr("Remove double linebreaks, e.g. in pasted text from webmailer"));
+ connect(cleanDoubleLinebreaksAct, SIGNAL(triggered()), this, SLOT(slotCleanDoubleLinebreaks()));
+
+ openSettingsAct = new QAction(tr("Se&ttings"), this);
+ openSettingsAct->setToolTip(tr("Open settings dialog"));
+ openSettingsAct->setShortcut(QKeySequence::Preferences);
+ connect(openSettingsAct, SIGNAL(triggered()), this, SLOT(slotOpenSettingsDialog()));
+
+ /* Crypt Menu
+ */
+ encryptAct = new QAction(tr("&Encrypt"), this);
+ encryptAct->setIcon(QIcon(":encrypted.png"));
+ encryptAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_E));
+ encryptAct->setToolTip(tr("Encrypt Message"));
+ connect(encryptAct, SIGNAL(triggered()), this, SLOT(slotEncrypt()));
+
+ decryptAct = new QAction(tr("&Decrypt"), this);
+ decryptAct->setIcon(QIcon(":decrypted.png"));
+ decryptAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_D));
+ decryptAct->setToolTip(tr("Decrypt Message"));
+ connect(decryptAct, SIGNAL(triggered()), this, SLOT(slotDecrypt()));
+
+ /*
+ * File encryption submenu
+ */
+ fileEncryptAct = new QAction(tr("&Encrypt File"), this);
+ fileEncryptAct->setToolTip(tr("Encrypt File"));
+ connect(fileEncryptAct, SIGNAL(triggered()), this, SLOT(slotFileEncrypt()));
+
+ fileDecryptAct = new QAction(tr("&Decrypt File"), this);
+ fileDecryptAct->setToolTip(tr("Decrypt File"));
+ connect(fileDecryptAct, SIGNAL(triggered()), this, SLOT(slotFileDecrypt()));
+
+ fileSignAct = new QAction(tr("&Sign File"), this);
+ fileSignAct->setToolTip(tr("Sign File"));
+ connect(fileSignAct, SIGNAL(triggered()), this, SLOT(slotFileSign()));
+
+ fileVerifyAct = new QAction(tr("&Verify File"), this);
+ fileVerifyAct->setToolTip(tr("Verify File"));
+ connect(fileVerifyAct, SIGNAL(triggered()), this, SLOT(slotFileVerify()));
+
+
+ signAct = new QAction(tr("&Sign"), this);
+ signAct->setIcon(QIcon(":signature.png"));
+ signAct->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_I));
+ signAct->setToolTip(tr("Sign Message"));
+ connect(signAct, SIGNAL(triggered()), this, SLOT(slotSign()));
+
+ verifyAct = new QAction(tr("&Verify"), this);
+ verifyAct->setIcon(QIcon(":verify.png"));
+ verifyAct->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_V));
+ verifyAct->setToolTip(tr("Verify Message"));
+ connect(verifyAct, SIGNAL(triggered()), this, SLOT(slotVerify()));
+
+ /* Key Menu
+ */
+
+ importKeyFromEditAct = new QAction(tr("&Editor"), this);
+ importKeyFromEditAct->setIcon(QIcon(":txt.png"));
+ importKeyFromEditAct->setToolTip(tr("Import New Key From Editor"));
+ connect(importKeyFromEditAct, SIGNAL(triggered()), this, SLOT(slotImportKeyFromEdit()));
+
+ openKeyManagementAct = new QAction(tr("Manage &keys"), this);
+ openKeyManagementAct->setIcon(QIcon(":keymgmt.png"));
+ openKeyManagementAct->setToolTip(tr("Open Keymanagement"));
+ connect(openKeyManagementAct, SIGNAL(triggered()), this, SLOT(slotOpenKeyManagement()));
+
+ /* About Menu
+ */
+ aboutAct = new QAction(tr("&About"), this);
+ aboutAct->setIcon(QIcon(":help.png"));
+ aboutAct->setToolTip(tr("Show the application's About box"));
+ connect(aboutAct, SIGNAL(triggered()), this, SLOT(slotAbout()));
+
+ openHelpAct = new QAction(tr("Integrated Help"), this);
+ openHelpAct->setToolTip(tr("Open integrated Help"));
+ connect(openHelpAct, SIGNAL(triggered()), this, SLOT(slotOpenHelp()));
+
+ openTutorialAct = new QAction(tr("Online &Tutorials"), this);
+ openTutorialAct->setToolTip(tr("Open Online Tutorials"));
+ connect(openTutorialAct, SIGNAL(triggered()), this, SLOT(slotOpenTutorial()));
+
+ openTranslateAct = new QAction(tr("Translate gpg4usb"), this);
+ openTranslateAct->setToolTip(tr("Translate gpg4usb yourself"));
+ connect(openTranslateAct, SIGNAL(triggered()), this, SLOT(slotOpenTranslate()));
+
+ startWizardAct= new QAction(tr("Open &Wizard"), this);
+ startWizardAct->setToolTip(tr("Open the wizard"));
+ connect(startWizardAct, SIGNAL(triggered()), this, SLOT(slotStartWizard()));
+
+ /* Popup-Menu-Action for KeyList
+ */
+ appendSelectedKeysAct = new QAction(tr("Append Selected Key(s) To Text"), this);
+ appendSelectedKeysAct->setToolTip(tr("Append The Selected Keys To Text in Editor"));
+ connect(appendSelectedKeysAct, SIGNAL(triggered()), this, SLOT(slotAppendSelectedKeys()));
+
+ copyMailAddressToClipboardAct = new QAction(tr("Copy EMail-address"), this);
+ copyMailAddressToClipboardAct->setToolTip(tr("Copy selected EMailaddress to clipboard"));
+ connect(copyMailAddressToClipboardAct, SIGNAL(triggered()), this, SLOT(slotCopyMailAddressToClipboard()));
+
+ // TODO: find central place for shared actions, to avoid code-duplication with keymgmt.cpp
+ showKeyDetailsAct = new QAction(tr("Show Keydetails"), this);
+ showKeyDetailsAct->setToolTip(tr("Show Details for this Key"));
+ connect(showKeyDetailsAct, SIGNAL(triggered()), this, SLOT(slotShowKeyDetails()));
+
+ refreshKeysFromKeyserverAct = new QAction(tr("Refresh key from keyserver"), this);
+ refreshKeysFromKeyserverAct->setToolTip(tr("Refresh key from default keyserver"));
+ connect(refreshKeysFromKeyserverAct, SIGNAL(triggered()), this, SLOT(refreshKeysFromKeyserver()));
+
+ uploadKeyToServerAct = new QAction(tr("Upload Key(s) To Server"), this);
+ uploadKeyToServerAct->setToolTip(tr("Upload The Selected Keys To Server"));
+ connect(uploadKeyToServerAct, SIGNAL(triggered()), this, SLOT(uploadKeyToServer()));
+ /* Key-Shortcuts for Tab-Switchung-Action
+ */
+ switchTabUpAct = new QAction(this);
+ switchTabUpAct->setShortcut(QKeySequence::NextChild);
+ connect(switchTabUpAct, SIGNAL(triggered()), edit, SLOT(slotSwitchTabUp()));
+ this->addAction(switchTabUpAct);
+
+ switchTabDownAct = new QAction(this);
+ switchTabDownAct->setShortcut(QKeySequence::PreviousChild);
+ connect(switchTabDownAct, SIGNAL(triggered()), edit, SLOT(slotSwitchTabDown()));
+ this->addAction(switchTabDownAct);
+
+ cutPgpHeaderAct = new QAction(tr("Remove PGP Header"), this);
+ connect(cutPgpHeaderAct, SIGNAL(triggered()), this, SLOT(slotCutPgpHeader()));
+
+ addPgpHeaderAct = new QAction(tr("Add PGP Header"), this);
+ connect(addPgpHeaderAct, SIGNAL(triggered()), this, SLOT(slotAddPgpHeader()));
+}
+
+void MainWindow::slotDisableTabActions(int number)
+{
+ bool disable;
+
+ if (number == -1 ) {
+ disable = true;
+ } else {
+ disable= false;
+ }
+ printAct->setDisabled(disable);
+ saveAct->setDisabled(disable);
+ saveAsAct->setDisabled(disable);
+ quoteAct->setDisabled(disable);
+ cutAct->setDisabled(disable);
+ copyAct->setDisabled(disable);
+ pasteAct->setDisabled(disable);
+ closeTabAct->setDisabled(disable);
+ selectallAct->setDisabled(disable);
+ findAct->setDisabled(disable);
+ verifyAct->setDisabled(disable);
+ signAct->setDisabled(disable);
+ encryptAct->setDisabled(disable);
+ decryptAct->setDisabled(disable);
+
+ redoAct->setDisabled(disable);
+ undoAct->setDisabled(disable);
+ zoomOutAct->setDisabled(disable);
+ zoomInAct->setDisabled(disable);
+ cleanDoubleLinebreaksAct->setDisabled(disable);
+ quoteAct->setDisabled(disable);
+ appendSelectedKeysAct->setDisabled(disable);
+ importKeyFromEditAct->setDisabled(disable);
+
+ cutPgpHeaderAct->setDisabled(disable);
+ addPgpHeaderAct->setDisabled(disable);
+}
+
+void MainWindow::createMenus()
+{
+ fileMenu = menuBar()->addMenu(tr("&File"));
+ fileMenu->addAction(newTabAct);
+ fileMenu->addAction(openAct);
+ fileMenu->addSeparator();
+ fileMenu->addAction(saveAct);
+ fileMenu->addAction(saveAsAct);
+ fileMenu->addSeparator();
+ fileMenu->addAction(printAct);
+ fileMenu->addSeparator();
+ fileMenu->addAction(closeTabAct);
+ fileMenu->addAction(quitAct);
+
+ editMenu = menuBar()->addMenu(tr("&Edit"));
+ editMenu->addAction(undoAct);
+ editMenu->addAction(redoAct);
+ editMenu->addSeparator();
+ editMenu->addAction(zoomInAct);
+ editMenu->addAction(zoomOutAct);
+ editMenu->addSeparator();
+ editMenu->addAction(copyAct);
+ editMenu->addAction(cutAct);
+ editMenu->addAction(pasteAct);
+ editMenu->addAction(selectallAct);
+ editMenu->addAction(findAct);
+ editMenu->addSeparator();
+ editMenu->addAction(quoteAct);
+ editMenu->addAction(cleanDoubleLinebreaksAct);
+ editMenu->addSeparator();
+ editMenu->addAction(openSettingsAct);
+
+ fileEncMenu = new QMenu(tr("&File..."));
+ fileEncMenu->addAction(fileEncryptAct);
+ fileEncMenu->addAction(fileDecryptAct);
+ fileEncMenu->addAction(fileSignAct);
+ fileEncMenu->addAction(fileVerifyAct);
+
+ cryptMenu = menuBar()->addMenu(tr("&Crypt"));
+ cryptMenu->addAction(encryptAct);
+ cryptMenu->addAction(decryptAct);
+ cryptMenu->addSeparator();
+ cryptMenu->addAction(signAct);
+ cryptMenu->addAction(verifyAct);
+ cryptMenu->addSeparator();
+ cryptMenu->addMenu(fileEncMenu);
+
+ keyMenu = menuBar()->addMenu(tr("&Keys"));
+ importKeyMenu = keyMenu->addMenu(tr("&Import Key From..."));
+ importKeyMenu->setIcon(QIcon(":key_import.png"));
+ importKeyMenu->addAction(keyMgmt->importKeyFromFileAct);
+ importKeyMenu->addAction(importKeyFromEditAct);
+ importKeyMenu->addAction(keyMgmt->importKeyFromClipboardAct);
+ importKeyMenu->addAction(keyMgmt->importKeyFromKeyServerAct);
+ importKeyMenu->addAction(keyMgmt->importKeyFromKeyServerAct);
+ keyMenu->addAction(openKeyManagementAct);
+
+ steganoMenu = menuBar()->addMenu(tr("&Steganography"));
+ steganoMenu->addAction(cutPgpHeaderAct);
+ steganoMenu->addAction(addPgpHeaderAct);
+
+ // Hide menu, when steganography menu is disabled in settings
+ if(!settings.value("advanced/steganography").toBool()) {
+ this->menuBar()->removeAction(steganoMenu->menuAction());
+ }
+
+ viewMenu = menuBar()->addMenu(tr("&View"));
+
+ helpMenu = menuBar()->addMenu(tr("&Help"));
+ helpMenu->addAction(openHelpAct);
+ helpMenu->addAction(startWizardAct);
+ helpMenu->addSeparator();
+ helpMenu->addAction(openTutorialAct);
+ helpMenu->addAction(openTranslateAct);
+ helpMenu->addSeparator();
+ helpMenu->addAction(aboutAct);
+
+}
+
+void MainWindow::createToolBars()
+{
+ fileToolBar = addToolBar(tr("File"));
+ fileToolBar->setObjectName("fileToolBar");
+ fileToolBar->addAction(newTabAct);
+ fileToolBar->addAction(openAct);
+ fileToolBar->addAction(saveAct);
+ fileToolBar->hide();
+ viewMenu->addAction(fileToolBar->toggleViewAction());
+
+ cryptToolBar = addToolBar(tr("Crypt"));
+ cryptToolBar->setObjectName("cryptToolBar");
+ cryptToolBar->addAction(encryptAct);
+ cryptToolBar->addAction(decryptAct);
+ cryptToolBar->addAction(signAct);
+ cryptToolBar->addAction(verifyAct);
+ //cryptToolBar->addAction(fileEncryptionAct);
+ viewMenu->addAction(cryptToolBar->toggleViewAction());
+
+ keyToolBar = addToolBar(tr("Key"));
+ keyToolBar->setObjectName("keyToolBar");
+ keyToolBar->addAction(openKeyManagementAct);
+ viewMenu->addAction(keyToolBar->toggleViewAction());
+
+ editToolBar = addToolBar(tr("Edit"));
+ editToolBar->setObjectName("editToolBar");
+ editToolBar->addAction(copyAct);
+ editToolBar->addAction(pasteAct);
+ editToolBar->addAction(selectallAct);
+ viewMenu->addAction(editToolBar->toggleViewAction());
+
+ specialEditToolBar = addToolBar(tr("Special edit"));
+ specialEditToolBar->setObjectName("specialEditToolBar");
+ specialEditToolBar->addAction(quoteAct);
+ specialEditToolBar->addAction(cleanDoubleLinebreaksAct);
+ viewMenu->addAction(specialEditToolBar->toggleViewAction());
+
+ // Add dropdown menu for key import to keytoolbar
+ importButton = new QToolButton();
+ importButton->setMenu(importKeyMenu);
+ importButton->setPopupMode(QToolButton::InstantPopup);
+ importButton->setIcon(QIcon(":key_import.png"));
+ importButton->setToolTip(tr("Import key from..."));
+ importButton->setText(tr("Import key"));
+ keyToolBar->addWidget(importButton);
+
+ // Add dropdown menu for file encryption/decryption to crypttoolbar
+ fileEncButton = new QToolButton();
+ fileEncButton->setMenu(fileEncMenu);
+ fileEncButton->setPopupMode(QToolButton::InstantPopup);
+ fileEncButton->setIcon(QIcon(":fileencryption.png"));
+ fileEncButton->setToolTip(tr("Encrypt or decrypt File"));
+ fileEncButton->setText(tr("File.."));
+
+ cryptToolBar->addWidget(fileEncButton);
+
+}
+
+void MainWindow::createStatusBar()
+{
+ QWidget *statusBarBox = new QWidget();
+ QHBoxLayout *statusBarBoxLayout = new QHBoxLayout();
+ QPixmap *pixmap;
+
+ // icon which should be shown if there are files in attachments-folder
+ pixmap = new QPixmap(":statusbar_icon.png");
+ statusBarIcon = new QLabel(statusBar());
+ statusBarIcon->setPixmap(*pixmap);
+ statusBar()->insertPermanentWidget(0,statusBarIcon,0);
+ statusBarIcon->hide();
+ statusBar()->showMessage(tr("Ready"),2000);
+ statusBarBox->setLayout(statusBarBoxLayout);
+}
+
+void MainWindow::createDockWindows()
+{
+ /* KeyList-Dockwindow
+ */
+ keylistDock = new QDockWidget(tr("Encrypt for:"), this);
+ keylistDock->setObjectName("EncryptDock");
+ keylistDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
+ addDockWidget(Qt::RightDockWidgetArea, keylistDock);
+ keylistDock->setWidget(mKeyList);
+ viewMenu->addAction(keylistDock->toggleViewAction());
+
+ /* Attachments-Dockwindow
+ */
+ if(settings.value("mime/parseMime").toBool()) {
+ createAttachmentDock();
+ }
+}
+
+void MainWindow::createAttachmentDock() {
+ if (attachmentDockCreated) {
+ return;
+ }
+ mAttachments = new Attachments();
+ attachmentDock = new QDockWidget(tr("Attached files:"), this);
+ attachmentDock->setObjectName("AttachmentDock");
+ attachmentDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea);
+ addDockWidget(Qt::BottomDockWidgetArea, attachmentDock);
+ attachmentDock->setWidget(mAttachments);
+ // hide till attachment is decrypted
+ viewMenu->addAction(attachmentDock->toggleViewAction());
+ attachmentDock->hide();
+ attachmentDockCreated = true;
+}
+
+void MainWindow::closeAttachmentDock() {
+ if (!attachmentDockCreated) {
+ return;
+ }
+ attachmentDock->close();
+ attachmentDock->deleteLater();
+ attachmentDockCreated = false;
+}
+
+void MainWindow::closeEvent(QCloseEvent *event)
+{
+ /*
+ * ask to save changes, if there are
+ * modified documents in any tab
+ */
+ if (edit->maybeSaveAnyTab()) {
+ saveSettings();
+ event->accept();
+ } else {
+ event->ignore();
+ }
+
+ // clear password from memory
+ mCtx->clearPasswordCache();
+}
+
+void MainWindow::slotAbout()
+{
+ new AboutDialog(this);
+}
+
+void MainWindow::slotOpenTranslate()
+{
+ QDesktopServices::openUrl(QUrl("http://gpg4usb.cpunk.de/docu_translate.html"));
+}
+
+void MainWindow::slotOpenTutorial()
+{
+ QDesktopServices::openUrl(QUrl("http://gpg4usb.cpunk.de/docu.html"));
+}
+
+void MainWindow::slotOpenHelp() {
+ slotOpenHelp("docu.html");
+}
+
+void MainWindow::slotOpenHelp(const QString page)
+{
+ edit->slotNewHelpTab("help", "file:" + qApp->applicationDirPath() + "/help/" + page);
+}
+
+void MainWindow::slotSetStatusBarText(QString text)
+{
+ statusBar()->showMessage(text,20000);
+}
+
+void MainWindow::slotStartWizard()
+{
+ Wizard *wizard = new Wizard(mCtx,keyMgmt,this);
+ wizard->show();
+ wizard->setModal(true);
+}
+
+/*
+ * if this is mime, split text and attachments...
+ * message contains only text afterwards
+ */
+void MainWindow::parseMime(QByteArray *message)
+{
+ /*if (! Mime::isMultipart(message)) {
+ qDebug() << "no multipart";
+ return;
+ }*/
+ //qDebug() << "multipart";
+
+ QString pText;
+ bool showmadock = false;
+
+ Mime *mime = new Mime(message);
+ foreach(MimePart tmp, mime->parts()) {
+ if (tmp.header.getValue("Content-Type") == "text/plain"
+ && tmp.header.getValue("Content-Transfer-Encoding") != "base64") {
+
+ QByteArray body;
+ if (tmp.header.getValue("Content-Transfer-Encoding") == "quoted-printable") {
+ Mime::quotedPrintableDecode(tmp.body, body);
+ } else {
+ body = tmp.body;
+ }
+ pText.append(QString(body));
+ } else {
+ (mAttachments->addMimePart(&tmp));
+ showmadock = true;
+ }
+ }
+ *message = pText.toUtf8();
+ if (showmadock) {
+ attachmentDock->show();
+ }
+}
+
+void MainWindow::slotCheckAttachmentFolder() {
+ // TODO: always check?
+ if(!settings.value("mime/parseMime").toBool()) {
+ return;
+ }
+
+ QString attachmentDir = qApp->applicationDirPath() + "/attachments/";
+ // filenum minus . and ..
+ int filenum = QDir(attachmentDir).count() - 2 ;
+ if(filenum > 0) {
+ QString statusText;
+ if(filenum == 1) {
+ statusText = tr("There is one unencrypted file in attachment folder");
+ } else {
+ statusText = tr("There are ") + QString::number(filenum) + tr(" unencrypted files in attachment folder");
+ }
+ statusBarIcon->setStatusTip(statusText);
+ statusBarIcon->show();
+ } else {
+ statusBarIcon->hide();
+ }
+}
+
+void MainWindow::slotImportKeyFromEdit()
+{
+ if (edit->tabCount()==0 || edit->slotCurPage() == 0) {
+ return;
+ }
+
+ keyMgmt->slotImportKeys(edit->curTextPage()->toPlainText().toAscii());
+}
+
+void MainWindow::slotOpenKeyManagement()
+{
+ keyMgmt->show();
+ keyMgmt->raise();
+ keyMgmt->activateWindow();
+}
+
+void MainWindow::slotEncrypt()
+{
+ if (edit->tabCount()==0 || edit->slotCurPage() == 0) {
+ return;
+ }
+
+ QStringList *uidList = mKeyList->getChecked();
+
+ QByteArray *tmp = new QByteArray();
+ if (mCtx->encrypt(uidList, edit->curTextPage()->toPlainText().toUtf8(), tmp)) {
+ QString *tmp2 = new QString(*tmp);
+ edit->slotFillTextEditWithText(*tmp2);
+ }
+}
+
+void MainWindow::slotSign()
+{
+ if (edit->tabCount()==0 || edit->slotCurPage() == 0) {
+ return;
+ }
+
+ QStringList *uidList = mKeyList->getPrivateChecked();
+
+ QByteArray *tmp = new QByteArray();
+
+ if (mCtx->sign(uidList, edit->curTextPage()->toPlainText().toUtf8(), tmp)) {
+ edit->slotFillTextEditWithText(QString::fromUtf8(*tmp));
+ }
+}
+
+void MainWindow::slotDecrypt()
+{
+ if (edit->tabCount()== 0 || edit->slotCurPage() == 0) {
+ return;
+ }
+
+ QByteArray *decrypted = new QByteArray();
+ QByteArray text = edit->curTextPage()->toPlainText().toAscii(); // TODO: toUtf8() here?
+ mCtx->preventNoDataErr(&text);
+
+ // try decrypt, if fail do nothing, especially don't replace text
+ if(!mCtx->decrypt(text, decrypted)) {
+ return;
+ }
+
+ /*
+ * 1) is it mime (content-type:)
+ * 2) parse header
+ * 2) choose action depending on content-type
+ */
+ if(Mime::isMime(decrypted)) {
+ Header header = Mime::getHeader(decrypted);
+ // is it multipart, is multipart-parsing enabled
+ if(header.getValue("Content-Type") == "multipart/mixed"
+ && settings.value("mime/parseMime").toBool()) {
+ parseMime(decrypted);
+ } else if(header.getValue("Content-Type") == "text/plain"
+ && settings.value("mime/parseQP").toBool()){
+ if (header.getValue("Content-Transfer-Encoding") == "quoted-printable") {
+ QByteArray *decoded = new QByteArray();
+ Mime::quotedPrintableDecode(*decrypted, *decoded);
+ //TODO: remove header
+ decrypted = decoded;
+ }
+ }
+ }
+ edit->slotFillTextEditWithText(QString::fromUtf8(*decrypted));
+}
+
+void MainWindow::slotFind()
+{
+ if (edit->tabCount()==0 || edit->curTextPage() == 0) {
+ return;
+ }
+
+ // At first close verifynotification, if existing
+ edit->slotCurPage()->closeNoteByClass("findwidget");
+
+ FindWidget *fw = new FindWidget(this,edit->curTextPage());
+ edit->slotCurPage()->showNotificationWidget(fw, "findWidget");
+
+}
+
+void MainWindow::slotVerify()
+{
+ if (edit->tabCount()==0 || edit->slotCurPage() == 0) {
+ return;
+ }
+
+ // At first close verifynotification, if existing
+ edit->slotCurPage()->closeNoteByClass("verifyNotification");
+
+ // create new verfiy notification
+ VerifyNotification *vn = new VerifyNotification(this, mCtx, mKeyList, edit->curTextPage());
+
+ // if signing information is found, show the notification, otherwise close it
+ if (vn->slotRefresh()) {
+ edit->slotCurPage()->showNotificationWidget(vn, "verifyNotification");
+ } else {
+ vn->close();
+ }
+}
+
+/*
+ * Append the selected (not checked!) Key(s) To Textedit
+ */
+void MainWindow::slotAppendSelectedKeys()
+{
+ if (edit->tabCount()==0 || edit->slotCurPage() == 0) {
+ return;
+ }
+
+ QByteArray *keyArray = new QByteArray();
+ mCtx->exportKeys(mKeyList->getSelected(), keyArray);
+ edit->curTextPage()->append(*keyArray);
+}
+
+void MainWindow::slotCopyMailAddressToClipboard()
+{
+ if (mKeyList->getSelected()->isEmpty()) {
+ return;
+ }
+
+ gpgme_key_t key = mCtx->getKeyDetails(mKeyList->getSelected()->first());
+ QClipboard *cb = QApplication::clipboard();
+ QString mail = key->uids->email;
+ cb->setText(mail);
+}
+
+void MainWindow::slotShowKeyDetails()
+{
+ if (mKeyList->getSelected()->isEmpty()) {
+ return;
+ }
+
+ gpgme_key_t key = mCtx->getKeyDetails(mKeyList->getSelected()->first());
+ if (key) {
+ new KeyDetailsDialog(mCtx, key, this);
+ }
+}
+void MainWindow::refreshKeysFromKeyserver()
+{
+ if (mKeyList->getSelected()->isEmpty()) {
+ return;
+ }
+
+ KeyServerImportDialog *ksid = new KeyServerImportDialog(mCtx,mKeyList,this);
+ ksid->slotImport(*mKeyList->getSelected());
+
+}
+
+void MainWindow::uploadKeyToServer()
+{
+ QByteArray *keyArray = new QByteArray();
+ mCtx->exportKeys(mKeyList->getSelected(), keyArray);
+
+ mKeyList->uploadKeyToServer(keyArray);
+}
+
+void MainWindow::slotFileEncrypt()
+{
+ QStringList *keyList;
+ keyList = mKeyList->getChecked();
+ new FileEncryptionDialog(mCtx, *keyList, FileEncryptionDialog::Encrypt, this);
+}
+
+void MainWindow::slotFileDecrypt()
+{
+ QStringList *keyList;
+ keyList = mKeyList->getChecked();
+ new FileEncryptionDialog(mCtx, *keyList, FileEncryptionDialog::Decrypt, this);
+}
+
+void MainWindow::slotFileSign()
+{
+ QStringList *keyList;
+ keyList = mKeyList->getChecked();
+ new FileEncryptionDialog(mCtx, *keyList, FileEncryptionDialog::Sign, this);
+}
+
+void MainWindow::slotFileVerify()
+{
+ QStringList *keyList;
+ keyList = mKeyList->getChecked();
+ new FileEncryptionDialog(mCtx, *keyList, FileEncryptionDialog::Verify, this);
+}
+
+void MainWindow::slotOpenSettingsDialog()
+{
+
+ QString preLang = settings.value("int/lang").toString();
+ QString preKeydbPath = settings.value("gpgpaths/keydbpath").toString();
+
+ new SettingsDialog(mCtx, this);
+ // Iconsize
+ QSize iconSize = settings.value("toolbar/iconsize", QSize(32, 32)).toSize();
+ this->setIconSize(iconSize);
+ importButton->setIconSize(iconSize);
+ fileEncButton->setIconSize(iconSize);
+
+ // Iconstyle
+ Qt::ToolButtonStyle buttonStyle = static_cast<Qt::ToolButtonStyle>(settings.value("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon).toUInt());
+ this->setToolButtonStyle(buttonStyle);
+ importButton->setToolButtonStyle(buttonStyle);
+ fileEncButton->setToolButtonStyle(buttonStyle);
+
+ // Mime-settings
+ if(settings.value("mime/parseMime").toBool()) {
+ createAttachmentDock();
+ } else if(attachmentDockCreated) {
+ closeAttachmentDock();
+ }
+
+ // restart mainwindow if necessary
+ if(getRestartNeeded()) {
+ if(edit->maybeSaveAnyTab()) {
+ saveSettings();
+ qApp->exit(RESTART_CODE);
+ }
+ }
+
+ // steganography hide/show
+ if(!settings.value("advanced/steganography").toBool()) {
+ this->menuBar()->removeAction(steganoMenu->menuAction());
+ } else {
+ this->menuBar()->insertAction(viewMenu->menuAction(), steganoMenu->menuAction());
+ }
+
+}
+
+void MainWindow::slotCleanDoubleLinebreaks()
+{
+ if (edit->tabCount()==0 || edit->slotCurPage() == 0) {
+ return;
+ }
+
+ QString content = edit->curTextPage()->toPlainText();
+ content.replace("\n\n", "\n");
+ edit->slotFillTextEditWithText(content);
+}
+
+void MainWindow::slotAddPgpHeader() {
+ if (edit->tabCount()==0 || edit->slotCurPage() == 0) {
+ return;
+ }
+
+ QString content = edit->curTextPage()->toPlainText().trimmed();
+
+ content.prepend("\n\n").prepend(GpgConstants::PGP_CRYPT_BEGIN);
+ content.append("\n").append(GpgConstants::PGP_CRYPT_END);
+
+ edit->slotFillTextEditWithText(content);
+}
+
+void MainWindow::slotCutPgpHeader() {
+
+ if (edit->tabCount()==0 || edit->slotCurPage() == 0) {
+ return;
+ }
+
+ QString content = edit->curTextPage()->toPlainText();
+ int start = content.indexOf(GpgConstants::PGP_CRYPT_BEGIN);
+ int end = content.indexOf(GpgConstants::PGP_CRYPT_END);
+
+ if(start < 0 || end < 0) {
+ return;
+ }
+
+ // remove head
+ int headEnd = content.indexOf("\n\n", start) + 2 ;
+ content.remove(start, headEnd-start);
+
+ // remove tail
+ end = content.indexOf(GpgConstants::PGP_CRYPT_END);
+ content.remove(end, QString(GpgConstants::PGP_CRYPT_END).size());
+
+ edit->slotFillTextEditWithText(content.trimmed());
+}
+
+void MainWindow::slotSetRestartNeeded(bool needed)
+{
+ this->restartNeeded = needed;
+}
+
+bool MainWindow::getRestartNeeded()
+{
+ return this->restartNeeded;
+}
diff --git a/src/mainwindow.h b/src/mainwindow.h
new file mode 100644
index 0000000..9ee1b63
--- /dev/null
+++ b/src/mainwindow.h
@@ -0,0 +1,374 @@
+/*
+ * mainwindow.h
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef __GPGWIN_H__
+#define __GPGWIN_H__
+
+#include "gpgconstants.h"
+#include "attachments.h"
+#include "keymgmt.h"
+#include "textedit.h"
+#include "fileencryptiondialog.h"
+#include "settingsdialog.h"
+#include "aboutdialog.h"
+#include "verifynotification.h"
+#include "findwidget.h"
+#include "wizard.h"
+
+QT_BEGIN_NAMESPACE
+class QMainWindow;
+class QTextEdit;
+class QWidget;
+class QVBoxLayout;
+class QGridLayout;
+class iostream;
+class QtGui;
+class QString;
+class QFileDialog;
+class QStringList;
+class QIcon;
+class QMessageBox;
+class QVBoxLayout;
+class QAction;
+class QMenu;
+class QTextEdit;
+class QComboBox;
+class QPushButton;
+class QRadioButton;
+class QButtonGroup;
+class QApplication;
+class QDockWidget;
+QT_END_NAMESPACE
+
+/**
+ * @brief
+ *
+ */
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ /**
+ * @brief
+ *
+ */
+ MainWindow();
+public slots:
+ void slotSetStatusBarText(QString text);
+
+protected:
+ /**
+ * @details Close event shows a save dialog, if there are unsaved documents on exit.
+ * @param event
+ */
+ void closeEvent(QCloseEvent *event);
+
+private slots:
+ /**
+ * @details encrypt the text of currently active textedit-page
+ * with the currently checked keys
+ */
+ void slotEncrypt();
+
+ /**
+ * @details Show a passphrase dialog and decrypt the text of currently active tab.
+ */
+ void slotDecrypt();
+
+ /**
+ * @details Sign the text of currently active tab with the checked private keys
+ */
+ void slotSign();
+
+ /**
+ * @details Verify the text of currently active tab and show verify information.
+ * If document is signed with a key, which is not in keylist, show import missing
+ * key from keyserver in Menu of verifynotification.
+ */
+ void slotVerify();
+
+ /**
+ * @details Show the details of the first of the first of selected keys
+ */
+ void slotShowKeyDetails();
+
+ /**
+ * @details Refresh key information of selected keys from default keyserver
+ */
+ void refreshKeysFromKeyserver();
+
+ /**
+ * @details upload the selected key to the keyserver
+ */
+ void uploadKeyToServer();
+
+ /**
+ * @details Open find widget.
+ */
+ void slotFind();
+
+ /**
+ * @details start the wizard
+ */
+ void slotStartWizard();
+
+ /**
+ * @details Import keys from currently active tab to keylist if possible.
+ */
+ void slotImportKeyFromEdit();
+
+ /**
+ * @details Append the selected keys to currently active textedit.
+ */
+ void slotAppendSelectedKeys();
+
+ /**
+ * @details Copy the mailaddress of selected key to clipboard.
+ * Method for keylists contextmenu.
+ */
+ void slotCopyMailAddressToClipboard();
+
+ /**
+ * @details Open key management dialog.
+ */
+ void slotOpenKeyManagement();
+
+ /**
+ * @details Open about-dialog.
+ */
+ void slotAbout();
+
+ /**
+ * @details Open dialog for encrypting file.
+ */
+ void slotFileEncrypt();
+
+ /**
+ * @details Open dialog for decrypting file.
+ */
+ void slotFileDecrypt();
+
+ /**
+ * @details Open dialog for signing file.
+ */
+ void slotFileSign();
+
+ /**
+ * @details Open dialog for verifying file.
+ */
+ void slotFileVerify();
+
+ /**
+ * @details Open settings-dialog.
+ */
+ void slotOpenSettingsDialog();
+
+ /**
+ * @details Open online-tutorial in default browser.
+ */
+ void slotOpenTutorial();
+
+ /**
+ * @details Open integrated help in new tab.
+ */
+ void slotOpenHelp();
+
+ /**
+ * @details Open integrated help in new tab with the specified page.
+ */
+ void slotOpenHelp(const QString page);
+
+ /**
+ * @details Show a warn message in status bar, if there are files in attachment folder.
+ */
+ void slotCheckAttachmentFolder();
+
+ /**
+ * @details Open online translation tutorial in default browser.
+ */
+ void slotOpenTranslate();
+
+ /**
+ * @details Replace double linebreaks by single linebreaks in currently active tab.
+ */
+ void slotCleanDoubleLinebreaks();
+
+ /**
+ * @details Cut the existing PGP header and footer from current tab.
+ */
+ void slotCutPgpHeader();
+
+ /**
+ * @details Add PGP header and footer to current tab.
+ */
+ void slotAddPgpHeader();
+
+// void dropEvent(QDropEvent *event);
+
+ /**
+ * @details Disable tab related actions, if number of tabs is 0.
+ * @param number number of the opened tabs and -1, if no tab is opened
+ */
+ void slotDisableTabActions(int number);
+
+ /**
+ * @details get value of member restartNeeded to needed.
+ * @param needed true, if application has to be restarted
+ */
+ void slotSetRestartNeeded(bool needed);
+
+private:
+ /**
+ * @details Create actions for the main-menu and the context-menu of the keylist.
+ */
+ void createActions();
+
+ /**
+ * @details create the menu of the main-window.
+ */
+ void createMenus();
+
+ /**
+ * @details Create edit-, crypt- and key-toolbars.
+ */
+ void createToolBars();
+
+ /**
+ * @details Create statusbar of mainwindow.
+ */
+ void createStatusBar();
+
+ /**
+ * @details Create keylist- and attachment-dockwindows.
+ */
+ void createDockWindows();
+
+ /**
+ * @details Create attachment-dockwindow.
+ */
+ void createAttachmentDock();
+
+ /**
+ * @details close attachment-dockwindow.
+ */
+ void closeAttachmentDock();
+
+ /**
+ * @details Load settings from ini-file.
+ */
+ void restoreSettings();
+
+ /**
+ * @details Save settings to ini-file.
+ */
+ void saveSettings();
+
+ /**
+ * @brief
+ *
+ * @param message
+ */
+ void parseMime(QByteArray *message);
+
+ /**
+ * @brief return true, if restart is needed
+ */
+ bool getRestartNeeded();
+
+ TextEdit *edit; /** Tabwidget holding the edit-windows */
+ QMenu *fileMenu; /** Submenu for file-operations*/
+ QMenu *editMenu; /** Submenu for text-operations*/
+ QMenu *cryptMenu; /** Submenu for crypt-operations */
+ QMenu *fileEncMenu; /** Submenu for file crypt operations */
+ QMenu *helpMenu; /** Submenu for help-operations */
+ QMenu *keyMenu; /** Submenu for key-operations */
+ QMenu *viewMenu; /** Submenu for view operations */
+ QMenu *importKeyMenu; /** Sumenu for import operations */
+ QMenu *steganoMenu; /** Submenu for steganographic operations*/
+ QToolBar *cryptToolBar; /** Toolbar holding crypt actions */
+ QToolBar *fileToolBar; /** Toolbar holding file actions */
+ QToolBar *editToolBar; /** Toolbar holding edit actions */
+ QToolBar *specialEditToolBar; /** Toolbar holding special edit actions */
+ QToolBar *keyToolBar; /** Toolbar holding key operations */
+ QToolButton* importButton; /** Toolbutton for import dropdown menu in toolbar */
+ QToolButton* fileEncButton; /** Toolbutton for file cryption dropdown menu in toolbar */
+ QDockWidget *keylistDock; /** Encrypt Dock*/
+ QDockWidget *attachmentDock; /** Attachment Dock */
+ QDialog *genkeyDialog; /** Dialog for key generation */
+
+ QAction *newTabAct; /** Action to create new tab */
+ QAction *switchTabUpAct; /** Action to switch tab up*/
+ QAction *switchTabDownAct; /** Action to switch tab down */
+ QAction *openAct; /** Action to open file */
+ QAction *saveAct; /** Action to save file */
+ QAction *saveAsAct; /** Action to save file as */
+ QAction *printAct; /** Action to print */
+ QAction *closeTabAct; /** Action to print */
+ QAction *quitAct; /** Action to quit application */
+ QAction *encryptAct; /** Action to encrypt text */
+ QAction *decryptAct; /** Action to decrypt text */
+ QAction *signAct; /** Action to sign text */
+ QAction *verifyAct; /** Action to verify text */
+ QAction *importKeyFromEditAct; /** Action to import key from edit */
+ QAction *cleanDoubleLinebreaksAct; /** Action to remove double line breaks */
+
+ QAction *appendSelectedKeysAct; /** Action to append selected keys to edit */
+ QAction *copyMailAddressToClipboardAct; /** Action to copy mail to clipboard */
+ QAction *openKeyManagementAct; /** Action to open key management */
+ QAction *copyAct; /** Action to copy text */
+ QAction *quoteAct; /** Action to quote text */
+ QAction *cutAct; /** Action to cut text */
+ QAction *pasteAct; /** Action to paste text */
+ QAction *selectallAct; /** Action to select whole text */
+ QAction *findAct; /** Action to find text */
+ QAction *undoAct; /** Action to undo last action */
+ QAction *redoAct; /** Action to redo last action */
+ QAction *zoomInAct; /** Action to zoom in */
+ QAction *zoomOutAct; /** Action to zoom out */
+ QAction *aboutAct; /** Action to open about dialog */
+ QAction *fileEncryptAct; /** Action to open dialog for encrypting file */
+ QAction *fileDecryptAct; /** Action to open dialog for decrypting file */
+ QAction *fileSignAct; /** Action to open dialog for signing file */
+ QAction *fileVerifyAct; /** Action to open dialog for verifying file */
+ QAction *openSettingsAct; /** Action to open settings dialog */
+ QAction *openTranslateAct; /** Action to open translate doc*/
+ QAction *openTutorialAct; /** Action to open tutorial */
+ QAction *openHelpAct; /** Action to open tutorial */
+ QAction *showKeyDetailsAct; /** Action to open key-details dialog */
+ QAction *refreshKeysFromKeyserverAct; /** Action to refresh a key from keyserver */
+ QAction *uploadKeyToServerAct; /** Action to append selected keys to edit */
+ QAction *startWizardAct; /** Action to open the wizard */
+ QAction *cutPgpHeaderAct; /** Action for cutting the PGP header */
+ QAction *addPgpHeaderAct; /** Action for adding the PGP header */
+
+ QLabel *statusBarIcon; /**< TODO */
+ QSettings settings; /**< TODO */
+ KeyList *mKeyList; /**< TODO */
+ Attachments *mAttachments; /**< TODO */
+ GpgME::GpgContext *mCtx; /**< TODO */
+ KeyMgmt *keyMgmt; /**< TODO */
+ KeyServerImportDialog *importDialog; /**< TODO */
+ bool attachmentDockCreated;
+ bool restartNeeded;
+};
+
+#endif // __GPGWIN_H__
diff --git a/src/mime.cpp b/src/mime.cpp
new file mode 100644
index 0000000..30f19cf
--- /dev/null
+++ b/src/mime.cpp
@@ -0,0 +1,243 @@
+/*
+ * mime.cpp
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+/***
+ * quotedPrintableDecode copied from KCodecs, where it is stated:
+
+ The quoted-printable codec as described in RFC 2045, section 6.7. is by
+ Rik Hemsley (C) 2001.
+
+ */
+
+/* TODO: proper import / copyright statement
+ *
+ */
+
+#include "mime.h"
+
+Mime::Mime(QByteArray *message)
+{
+ splitParts(message);
+ /*
+ mMessage = message;
+ int bStart = mMessage->indexOf("boundary=\"") + 10 ;
+ int bEnd = mMessage->indexOf("\"\n", bStart );
+
+ qDebug() << "bStart: " << bStart << " bEnd: " << bEnd;
+ mBoundary = new QByteArray(mMessage->mid(bStart, bEnd - bStart));
+ qDebug() << "boundary: " << *mBoundary;
+
+ Part *p1 = new Part();
+
+ int nb = mMessage->indexOf(*mBoundary, bEnd) + mBoundary->length() +1 ;
+ qDebug() << "nb: " << nb;
+ int eh = mMessage->indexOf("\n\n", nb);
+ qDebug() << "eh: " << eh;
+ QByteArray *header = new QByteArray(mMessage->mid(nb , eh - nb));
+ qDebug() << "header:" << header;
+
+ // split header at newlines
+ foreach(QByteArray tmp , header->split(* "\n")) {
+ // split lines at :
+ QList<QByteArray> tmp2 = tmp.split(* ":");
+ p1->header.insert(QString(tmp2[0].trimmed()), QString(tmp2[1].trimmed()));
+ }
+
+ QHashIterator<QString, QString> i(p1->header);
+ while (i.hasNext()) {
+ i.next();
+ qDebug() << "found: " << i.key() << ":" << i.value() << endl;
+ }
+
+ int nb2 = mMessage->indexOf(*mBoundary, eh);
+
+ p1->body = mMessage->mid(eh , nb2 - eh);
+
+ QTextCodec *codec = QTextCodec::codecForName("ISO-8859-15");
+ QString qs = codec->toUnicode(p1->body);
+ qDebug() << "body: " << qs;
+ */
+}
+
+Mime::~Mime()
+{
+
+}
+
+void Mime::splitParts(QByteArray *message)
+{
+ int pos1, pos2, headEnd;
+ MimePart p_tmp;
+
+ // find the boundary
+ pos1 = message->indexOf("boundary=\"") + 10 ;
+ pos2 = message->indexOf("\"\n", pos1);
+ QByteArray boundary = message->mid(pos1, pos2 - pos1);
+ //qDebug() << "boundary: " << boundary;
+
+ while (pos2 > pos1) {
+
+ pos1 = message->indexOf(boundary, pos2) + boundary.length() + 1 ;
+ headEnd = message->indexOf("\n\n", pos1);
+ if (headEnd < 0)
+ break;
+ QByteArray header = message->mid(pos1 , headEnd - pos1);
+
+ p_tmp.header = parseHeader(&header);
+
+ pos2 = message->indexOf(boundary, headEnd);
+ p_tmp.body = message->mid(headEnd , pos2 - headEnd);
+
+ mPartList.append(p_tmp);
+ }
+}
+
+Header Mime::parseHeader(QByteArray *header)
+{
+
+ QList<HeadElem> ret;
+
+ /** http://www.aspnetmime.com/help/welcome/overviewmimeii.html :
+ * If a line starts with any white space, that line is said to be 'folded' and is actually
+ * part of the header above it.
+ */
+ header->replace("\n ", " ");
+
+ //split header at newlines
+ foreach(QByteArray line , header->split(* "\n")) {
+ HeadElem elem;
+ //split lines at :
+ QList<QByteArray> tmp2 = line.split(* ":");
+ elem.name = tmp2[0].trimmed();
+ if (tmp2[1].contains(';')) {
+ // split lines at ;
+ // TODO: what if ; is inside ""
+ QList<QByteArray> tmp3 = tmp2[1].split(* ";");
+ elem.value = QString(tmp3.takeFirst().trimmed());
+ foreach(QByteArray tmp4, tmp3) {
+ QList<QByteArray> tmp5 = tmp4.split(* "=");
+ elem.params.insert(QString(tmp5[0].trimmed()), QString(tmp5[1].trimmed()));
+ }
+ } else {
+ elem.value = tmp2[1].trimmed();
+ }
+ ret.append(elem);
+ }
+ return Header(ret);
+}
+
+Header Mime::getHeader(const QByteArray *message) {
+ int headEnd = message->indexOf("\n\n");
+ QByteArray header = message->mid(0, headEnd);
+ return parseHeader(&header);
+}
+
+bool Mime::isMultipart(QByteArray *message)
+{
+ return message->startsWith("Content-Type: multipart/mixed;");
+}
+
+/**
+ * if Content-Type is specified, it should be mime
+ *
+ */
+bool Mime::isMime(const QByteArray *message)
+{
+ return message->startsWith("Content-Type:");
+}
+
+/***
+ * quotedPrintableDecode copied from KCodecs, where it is stated:
+
+ The quoted-printable codec as described in RFC 2045, section 6.7. is by
+ Rik Hemsley (C) 2001.
+
+ */
+
+static const char hexChars[16] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+};
+
+/******************************** KCodecs ********************************/
+// strchr(3) for broken systems.
+static int rikFindChar(register const char * _s, const char c)
+{
+ register const char * s = _s;
+
+ while (true) {
+ if ((0 == *s) || (c == *s)) break; ++s;
+ if ((0 == *s) || (c == *s)) break; ++s;
+ if ((0 == *s) || (c == *s)) break; ++s;
+ if ((0 == *s) || (c == *s)) break; ++s;
+ }
+
+ return s - _s;
+}
+
+void Mime::quotedPrintableDecode(const QByteArray& in, QByteArray& out)
+{
+ // clear out the output buffer
+ out.resize(0);
+ if (in.isEmpty())
+ return;
+
+ char *cursor;
+ const char *data;
+ const unsigned int length = in.size();
+
+ data = in.data();
+ out.resize(length);
+ cursor = out.data();
+
+ for (unsigned int i = 0; i < length; i++) {
+ char c(in[i]);
+
+ if ('=' == c) {
+ if (i < length - 2) {
+ char c1 = in[i + 1];
+ char c2 = in[i + 2];
+
+ if (('\n' == c1) || ('\r' == c1 && '\n' == c2)) {
+ // Soft line break. No output.
+ if ('\r' == c1)
+ i += 2; // CRLF line breaks
+ else
+ i += 1;
+ } else {
+ // =XX encoded byte.
+
+ int hexChar0 = rikFindChar(hexChars, c1);
+ int hexChar1 = rikFindChar(hexChars, c2);
+
+ if (hexChar0 < 16 && hexChar1 < 16) {
+ *cursor++ = char((hexChar0 * 16) | hexChar1);
+ i += 2;
+ }
+ }
+ }
+ } else {
+ *cursor++ = c;
+ }
+ }
+
+ out.truncate(cursor - out.data());
+}
diff --git a/src/mime.h b/src/mime.h
new file mode 100644
index 0000000..df44647
--- /dev/null
+++ b/src/mime.h
@@ -0,0 +1,134 @@
+/*
+ * mime.h
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef __MIME_H__
+#define __MIME_H__
+
+#include <QHashIterator>
+#include <QHash>
+
+QT_BEGIN_NAMESPACE
+class QByteArray;
+class QDebug;
+class QTextCodec;
+QT_END_NAMESPACE
+
+class HeadElem
+{
+public:
+ QString name;
+ QString value;
+ QHash<QString, QString> params;
+
+ /* QDataStream & operator<<(QDataStream& Stream, const HeadElem& H)
+ {
+ return Stream << H.name << " : " << H.value;
+ }*/
+
+};
+
+class Header
+{
+public:
+ QList<HeadElem> headElems;
+
+ Header() {}
+
+ Header(QList <HeadElem> heads) {
+ headElems = heads;
+ }
+
+ void setHeader(QList <HeadElem> heads) {
+ headElems = heads;
+ }
+
+ QString getValue(QString key) {
+ foreach(HeadElem tmp, headElems) {
+ //qDebug() << "gv: " << tmp.name << ":" << tmp.value;
+ if (tmp.name == key)
+ return tmp.value;
+ }
+ return "";
+ }
+
+ QHash<QString, QString> getParams(QString key) {
+ foreach(HeadElem tmp, headElems) {
+ //qDebug() << "gv: " << tmp.name << ":" << tmp.value;
+ if (tmp.name == key)
+ //return tmp.value;
+ return tmp.params;
+ }
+ return *(new QHash<QString, QString>());
+ }
+
+ QString getParam(QString key, QString pKey) {
+ foreach(HeadElem tmp, headElems) {
+ //qDebug() << "gv: " << tmp.name << ":" << tmp.value;
+ if (tmp.name == key)
+ return tmp.params.value(pKey);
+ }
+ return "";
+ }
+
+
+};
+
+class MimePart
+{
+public:
+ Header header;
+ QByteArray body;
+
+
+
+ /* QDataStream & operator<<(QDataStream& Stream, const Part& P)
+ {
+ foreach(HeadElem tmp, header) {
+ Stream << tmp << "\n";
+ }
+ return Stream;
+ }*/
+};
+
+class Mime
+{
+
+public:
+ Mime(QByteArray *message); // Constructor
+ ~Mime(); // Destructor
+ static bool isMultipart(QByteArray *message);
+ static bool isMime(const QByteArray *message);
+ QList<MimePart> parts() {
+ return mPartList;
+ }
+ void splitParts(QByteArray *message);
+ static Header getHeader(const QByteArray *message);
+ static Header parseHeader(QByteArray *header);
+ static void quotedPrintableDecode(const QByteArray& in, QByteArray& out);
+
+private:
+ QByteArray *mMessage;
+ QByteArray *mBoundary;
+ QList<MimePart> mPartList;
+
+};
+
+#endif // __MIME_H__
diff --git a/src/quitdialog.cpp b/src/quitdialog.cpp
new file mode 100755
index 0000000..e32369b
--- /dev/null
+++ b/src/quitdialog.cpp
@@ -0,0 +1,131 @@
+/*
+ *
+ * keymgmt.cpp
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "quitdialog.h"
+
+QuitDialog::QuitDialog(QWidget *parent, QHash<int, QString> unsavedDocs)
+ : QDialog(parent)
+{
+ setWindowTitle(tr("Unsaved files"));
+ setModal(true);
+ discarded =false;
+
+ /*
+ * Table of unsaved documents
+ */
+ QHashIterator<int, QString> i (unsavedDocs);
+ int row = 0;
+ mFileList = new QTableWidget(this);
+ mFileList->horizontalHeader()->hide();
+ mFileList->setColumnCount(3);
+ mFileList->setColumnWidth(0, 20);
+ mFileList->setColumnHidden(2, true);
+ mFileList->verticalHeader()->hide();
+ mFileList->setShowGrid(false);
+ mFileList->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ mFileList->setFocusPolicy(Qt::NoFocus);
+ mFileList->horizontalHeader()->setStretchLastSection( true );
+ // fill the table
+ i.toBack(); //jump to the end of list to fill the table backwards
+ while (i.hasPrevious()) {
+ i.previous();
+ mFileList->setRowCount(mFileList->rowCount()+1);
+
+ // checkbox in front of filename
+ QTableWidgetItem *tmp0 = new QTableWidgetItem();
+ tmp0->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled );
+ tmp0->setCheckState(Qt::Checked);
+ mFileList->setItem(row, 0, tmp0);
+
+ // filename
+ QTableWidgetItem *tmp1 = new QTableWidgetItem(i.value());
+ mFileList->setItem(row, 1, tmp1);
+
+ // tab-index in hidden column
+ QTableWidgetItem *tmp2 = new QTableWidgetItem(QString::number(i.key()));
+ mFileList->setItem(row, 2, tmp2);
+ ++row;
+ }
+ /*
+ * Warnbox with icon and text
+ */
+ QPixmap *pixmap = new QPixmap(":error.png");
+ QLabel *warnicon = new QLabel();
+ warnicon->setPixmap(*pixmap);
+ QLabel *warnlabel = new QLabel(tr("<h3>%1 files contain unsaved information.<br/>Save the changes before closing?</h3>").arg(row));
+ QHBoxLayout *warnBoxLayout = new QHBoxLayout();
+ warnBoxLayout->addWidget(warnicon);
+ warnBoxLayout->addWidget(warnlabel);
+ warnBoxLayout->setAlignment(Qt::AlignLeft);
+ QWidget *warnBox = new QWidget(this);
+ warnBox->setLayout(warnBoxLayout);
+
+ /*
+ * Two labels on top and under the filelist
+ */
+ QLabel *checkLabel = new QLabel(tr("Check the files you want to save:"));
+ QLabel *notelabel = new QLabel(tr("<b>Note:</b> If you don't save these files, all changes are lost.<br/>"));
+
+ /*
+ * Buttonbox
+ */
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Discard |QDialogButtonBox::Save | QDialogButtonBox::Cancel);
+ connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+ QPushButton* btnNoKey = buttonBox->button(QDialogButtonBox::Discard);
+ connect(btnNoKey, SIGNAL(clicked()), SLOT(slotMyDiscard()));
+
+ /*
+ * Set the layout
+ */
+ QVBoxLayout *vbox = new QVBoxLayout();
+ vbox->addWidget(warnBox);
+ vbox->addWidget(checkLabel);
+ vbox->addWidget(mFileList);
+ vbox->addWidget(notelabel);
+ vbox->addWidget(buttonBox);
+ this->setLayout(vbox);
+}
+
+
+void QuitDialog::slotMyDiscard()
+{
+ discarded =true;
+ reject();
+}
+
+bool QuitDialog::isDiscarded()
+{
+ return discarded;
+}
+
+QList <int> QuitDialog::getTabIdsToSave()
+{
+ QList <int> tabIdsToSave;
+ for (int i = 0; i < mFileList->rowCount(); i++) {
+ if (mFileList->item(i, 0)->checkState() == Qt::Checked) {
+ tabIdsToSave << mFileList->item(i, 2)->text().toInt();
+ }
+ }
+ return tabIdsToSave;
+}
+
diff --git a/src/quitdialog.h b/src/quitdialog.h
new file mode 100755
index 0000000..bc24712
--- /dev/null
+++ b/src/quitdialog.h
@@ -0,0 +1,50 @@
+/*
+ * keymgmt.h
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef __QUITDIALOG_H__
+#define __QUITDIALOG_H__
+
+#include <QtGui>
+
+QT_BEGIN_NAMESPACE
+class QTableWidget;
+QT_END_NAMESPACE
+
+class QuitDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ QuitDialog(QWidget *parent,QHash<int, QString> unsavedDocs);
+ bool isDiscarded();
+ QList <int> getTabIdsToSave();
+
+private slots:
+ void slotMyDiscard();
+
+private:
+ QAction *closeAct;
+ QLabel *nameLabel;
+ bool discarded;
+ QTableWidget *mFileList;
+};
+
+#endif // __QUITDIALOG_H__
diff --git a/src/settingsdialog.cpp b/src/settingsdialog.cpp
new file mode 100755
index 0000000..a99b832
--- /dev/null
+++ b/src/settingsdialog.cpp
@@ -0,0 +1,716 @@
+/*
+ * settingsdialog.cpp
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "settingsdialog.h"
+
+SettingsDialog::SettingsDialog(GpgME::GpgContext *ctx, QWidget *parent)
+ : QDialog(parent)
+{
+ mCtx=ctx;
+ tabWidget = new QTabWidget;
+ generalTab = new GeneralTab(mCtx);
+ appearanceTab = new AppearanceTab;
+ mimeTab = new MimeTab;
+ keyserverTab = new KeyserverTab;
+ advancedTab = new AdvancedTab;
+ gpgPathsTab = new GpgPathsTab;
+
+ tabWidget->addTab(generalTab, tr("General"));
+ tabWidget->addTab(appearanceTab, tr("Appearance"));
+ tabWidget->addTab(mimeTab, tr("PGP/Mime"));
+ tabWidget->addTab(keyserverTab, tr("Keyserver"));
+ tabWidget->addTab(gpgPathsTab, tr("Gpg paths"));
+ tabWidget->addTab(advancedTab, tr("Advanced"));
+
+ buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok
+ | QDialogButtonBox::Cancel);
+
+ connect(buttonBox, SIGNAL(accepted()), this, SLOT(slotAccept()));
+ connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+
+ QVBoxLayout *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(tabWidget);
+ mainLayout->addWidget(buttonBox);
+ setLayout(mainLayout);
+
+ setWindowTitle(tr("Settings"));
+
+ // slots for handling the restartneeded member
+ this->slotSetRestartNeeded(false);
+ connect(generalTab, SIGNAL(signalRestartNeeded(bool)), this, SLOT(slotSetRestartNeeded(bool)));
+ connect(appearanceTab, SIGNAL(signalRestartNeeded(bool)), this, SLOT(slotSetRestartNeeded(bool)));
+ connect(mimeTab, SIGNAL(signalRestartNeeded(bool)), this, SLOT(slotSetRestartNeeded(bool)));
+ connect(keyserverTab, SIGNAL(signalRestartNeeded(bool)), this, SLOT(slotSetRestartNeeded(bool)));
+ connect(advancedTab, SIGNAL(signalRestartNeeded(bool)), this, SLOT(slotSetRestartNeeded(bool)));
+
+ connect(this, SIGNAL(signalRestartNeeded(bool)), parent, SLOT(slotSetRestartNeeded(bool)));
+
+ exec();
+}
+
+bool SettingsDialog::getRestartNeeded()
+{
+ return this->restartNeeded;
+}
+
+void SettingsDialog::slotSetRestartNeeded(bool needed)
+{
+ this->restartNeeded = needed;
+}
+
+void SettingsDialog::slotAccept()
+{
+ generalTab->applySettings();
+ mimeTab->applySettings();
+ appearanceTab->applySettings();
+ keyserverTab->applySettings();
+ advancedTab->applySettings();
+ gpgPathsTab->applySettings();
+ if (getRestartNeeded()) {
+ emit signalRestartNeeded(true);
+ }
+ close();
+}
+
+// http://www.informit.com/articles/article.aspx?p=1405555&seqNum=3
+// http://developer.qt.nokia.com/wiki/How_to_create_a_multi_language_application
+QHash<QString, QString> SettingsDialog::listLanguages()
+{
+ QHash<QString, QString> languages;
+
+ languages.insert("", tr("System Default"));
+
+ QString appPath = qApp->applicationDirPath();
+ QDir qmDir = QDir(appPath + "/ts/");
+ QStringList fileNames =
+ qmDir.entryList(QStringList("gpg4usb_*.qm"));
+
+ for (int i = 0; i < fileNames.size(); ++i) {
+ QString locale = fileNames[i];
+ locale.truncate(locale.lastIndexOf('.'));
+ locale.remove(0, locale.indexOf('_') + 1);
+
+ // this works in qt 4.8
+ QLocale qloc(locale);
+ #if QT_VERSION < 0x040800
+ QString language = QLocale::languageToString(qloc.language()) +" (" + locale + ")"; //+ " (" + QLocale::languageToString(qloc.language()) + ")";
+ #else
+ QString language = qloc.nativeLanguageName() +" (" + locale + ")"; //+ " (" + QLocale::languageToString(qloc.language()) + ")";
+ #endif
+ languages.insert(locale, language);
+ }
+ return languages;
+}
+
+
+
+GeneralTab::GeneralTab(GpgME::GpgContext *ctx,QWidget *parent)
+ : QWidget(parent)
+{
+ mCtx=ctx;
+
+ /*****************************************
+ * remember Password-Box
+ *****************************************/
+ QGroupBox *rememberPasswordBox = new QGroupBox(tr("Remember Password"));
+ QHBoxLayout *rememberPasswordBoxLayout = new QHBoxLayout();
+ rememberPasswordCheckBox = new QCheckBox(tr("Remember password until closing gpg4usb"), this);
+ rememberPasswordBoxLayout->addWidget(rememberPasswordCheckBox);
+ rememberPasswordBox->setLayout(rememberPasswordBoxLayout);
+
+ /*****************************************
+ * Save-Checked-Keys-Box
+ *****************************************/
+ QGroupBox *saveCheckedKeysBox = new QGroupBox(tr("Save Checked Keys"));
+ QHBoxLayout *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
+ *****************************************/
+ QGroupBox *importConfirmationBox = new QGroupBox(tr("Confirm drag'n'drop key import"));
+ QHBoxLayout *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
+ *****************************************/
+ QGroupBox *langBox = new QGroupBox(tr("Language"));
+ QVBoxLayout *langBoxLayout = new QVBoxLayout();
+ langSelectBox = new QComboBox;
+ lang = SettingsDialog::listLanguages();
+
+ foreach(QString l , lang) {
+ langSelectBox->addItem(l);
+ }
+
+ langBoxLayout->addWidget(langSelectBox);
+ langBoxLayout->addWidget(new QLabel(tr("<b>NOTE: </b> Gpg4usb will restart automatically if you change the language!")));
+ langBox->setLayout(langBoxLayout);
+ connect(langSelectBox,SIGNAL(currentIndexChanged(int)),this,SLOT(slotLanguageChanged()));
+
+ /*****************************************
+ * Own Key Select Box
+ *****************************************/
+ QGroupBox *ownKeyBox = new QGroupBox(tr("Own key"));
+ QVBoxLayout *ownKeyBoxLayout = new QVBoxLayout();
+ ownKeySelectBox = new QComboBox;
+
+ ownKeyBox->setLayout(ownKeyBoxLayout);
+ mKeyList = new KeyList(mCtx);
+
+ // Fill the keyid hashmap
+ keyIds.insert("", tr("<none>"));
+
+ foreach (QString keyid, *mKeyList->getAllPrivateKeys()) {
+ gpgme_key_t key = mCtx->getKeyDetails(keyid);
+ QString newKey = " (" + keyid + ")";
+ if (! QString(key->uids->email).isEmpty()) {
+ newKey.prepend( " <"+ QString::fromUtf8(key->uids->email) +">");
+ }
+ if (! QString(key->uids->name).isEmpty()) {
+ newKey.prepend( " "+ QString::fromUtf8(key->uids->name));
+ }
+ keyIds.insert(key->uids->uid, newKey);
+ }
+ foreach(QString k , keyIds) {
+ ownKeySelectBox->addItem(k);
+ }
+ connect(ownKeySelectBox,SIGNAL(currentIndexChanged(int)),this,SLOT(slotOwnKeyIdChanged()));
+
+ ownKeyBoxLayout->addWidget(new QLabel(tr("Encrypt all messages additionally to the chosen key:")));
+ ownKeyBoxLayout->addWidget(ownKeySelectBox);
+
+ /*****************************************
+ * Mainlayout
+ *****************************************/
+ QVBoxLayout *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(rememberPasswordBox);
+ 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()
+{
+ QSettings settings;
+ // Keysaving
+ if (settings.value("keys/keySave").toBool()) {
+ saveCheckedKeysCheckBox->setCheckState(Qt::Checked);
+ }
+
+ // Remember Password
+ if (settings.value("general/rememberPassword").toBool()) {
+ rememberPasswordCheckBox->setCheckState(Qt::Checked);
+ }
+
+ // Language setting
+ QString langKey = settings.value("int/lang").toString();
+ QString langValue = lang.value(langKey);
+ if (langKey != "") {
+ langSelectBox->setCurrentIndex(langSelectBox->findText(langValue));
+ }
+
+ // Get own key information from keydb/gpg.conf (if contained)
+ QFile gpgConfFile(qApp->applicationDirPath() + "/keydb/gpg.conf");
+ gpgConfFile.open(QFile::ReadOnly);
+ while (!gpgConfFile.atEnd())
+ {
+ QString line = gpgConfFile.readLine();
+ if (line.startsWith("recipient")){
+ QStringList args;
+
+ // get key id from gpg.conf
+ args=line.split(" ");
+ ownKeyId = args.at(1);
+ // remove linebreak at end of id
+ ownKeyId.remove("\n");
+ ownKeyId.remove("\r");
+ }
+ }
+ gpgConfFile.close();
+ if (ownKeyId.isEmpty()) {
+ ownKeySelectBox->setCurrentIndex(0);
+ } else {
+ ownKeySelectBox->setCurrentIndex(ownKeySelectBox->findText(ownKeyId, Qt::MatchContains));
+ }
+
+ 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()
+{
+ QSettings settings;
+ settings.setValue("keys/keySave", saveCheckedKeysCheckBox->isChecked());
+ // TODO: clear passwordCache instantly on unset rememberPassword
+ settings.setValue("general/rememberPassword", rememberPasswordCheckBox->isChecked());
+ settings.setValue("int/lang", lang.key(langSelectBox->currentText()));
+ settings.setValue("general/confirmImportKeys", importConfirmationCheckBox->isChecked());
+}
+
+void GeneralTab::slotLanguageChanged()
+{
+ emit signalRestartNeeded(true);
+}
+
+void GeneralTab::slotOwnKeyIdChanged()
+{
+ // Set ownKeyId to currently selected
+
+ QHashIterator<QString, QString> i(keyIds);
+ while (i.hasNext()) {
+ i.next();
+ if (ownKeySelectBox->currentText() == i.value()) {
+ ownKeyId = i.key();
+ }
+ }
+
+ /*****************************************
+ * Write keyid of own key to gpg.conf
+ *****************************************/
+ QFile gpgConfFile(qApp->applicationDirPath() + "/keydb/gpg.conf");
+ gpgConfFile.open(QFile::ReadWrite);
+ QFile gpgConfTempFile(qApp->applicationDirPath() + "/keydb/gpg.conf.swp");
+ gpgConfTempFile.open(QFile::WriteOnly);
+
+ // remove line with the hidden-encrypt-to
+ while (!gpgConfFile.atEnd())
+ {
+ QByteArray line = gpgConfFile.readLine();
+ if (!line.startsWith("recipient")) {
+ gpgConfTempFile.write(line);
+ }
+ }
+
+ // add line with hidden-encrypt-to, if a key is chosen
+ if (!ownKeyId.isEmpty()) {
+ QByteArray string("recipient ");
+ string.append(ownKeyId);
+ string.append("\n");
+ gpgConfTempFile.write(string);
+ }
+
+ gpgConfFile.close();
+ gpgConfTempFile.close();
+
+ // move the temporary gpg.conffile to the actual one
+ gpgConfFile.remove();
+ gpgConfTempFile.copy(gpgConfTempFile.fileName(),gpgConfFile.fileName());
+ gpgConfTempFile.remove();
+}
+
+MimeTab::MimeTab(QWidget *parent)
+ : QWidget(parent)
+{
+ /*****************************************
+ * MIME-Parsing-Box
+ *****************************************/
+ QGroupBox *mimeQPBox = new QGroupBox(tr("Decode quoted printable"));
+ QVBoxLayout *mimeQPBoxLayout = new QVBoxLayout();
+ mimeQPCheckBox = new QCheckBox(tr("Try to recognize quoted printable."), this);
+ mimeQPBoxLayout->addWidget(mimeQPCheckBox);
+ mimeQPBox->setLayout(mimeQPBoxLayout);
+
+ QGroupBox *mimeParseBox = new QGroupBox(tr("Parse PGP/MIME (Experimental)"));
+ QVBoxLayout *mimeParseBoxLayout = new QVBoxLayout();
+ mimeParseCheckBox = new QCheckBox(tr("Try to split attachments from PGP-MIME ecrypted messages."), this);
+ mimeParseBoxLayout->addWidget(mimeParseCheckBox);
+ mimeParseBox->setLayout(mimeParseBoxLayout);
+
+ QGroupBox *mimeOpenAttachmentBox = new QGroupBox(tr("Open with external application (Experimental)"));
+ QVBoxLayout *mimeOpenAttachmentBoxLayout = new QVBoxLayout();
+ QLabel *mimeOpenAttachmentText = new QLabel(tr("Open attachments with default application for the filetype.<br> "
+ "There are at least two possible problems with this behaviour:"
+ "<ol><li>File needs to be saved unencrypted to attachments folder.<br> "
+ "Its your job to clean this folder.</li>"
+ "<li>The external application may have its own temp files.</li></ol>"));
+
+ //mimeOpenAttachmentBox->setDisabled(true);
+ mimeOpenAttachmentCheckBox = new QCheckBox(tr("Enable opening with external applications."), this);
+
+ mimeOpenAttachmentBoxLayout->addWidget(mimeOpenAttachmentText);
+ mimeOpenAttachmentBoxLayout->addWidget(mimeOpenAttachmentCheckBox);
+ mimeOpenAttachmentBox->setLayout(mimeOpenAttachmentBoxLayout);
+
+ QVBoxLayout *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(mimeParseBox);
+ mainLayout->addWidget(mimeOpenAttachmentBox);
+ mainLayout->addWidget(mimeQPBox);
+ mainLayout->addStretch(1);
+ setLayout(mainLayout);
+ setSettings();
+}
+
+/**********************************
+ * Read the settings from config
+ * and set the buttons and checkboxes
+ * appropriately
+ **********************************/
+void MimeTab::setSettings()
+{
+ QSettings settings;
+
+ // MIME-Parsing
+ if (settings.value("mime/parsemime").toBool()) mimeParseCheckBox->setCheckState(Qt::Checked);
+
+ // Qouted Printable
+ if (settings.value("mime/parseQP",true).toBool()) mimeQPCheckBox->setCheckState(Qt::Checked);
+
+ // Open Attachments with external app
+ if (settings.value("mime/openAttachment").toBool()) mimeOpenAttachmentCheckBox->setCheckState(Qt::Checked);
+}
+
+
+/***********************************
+ * get the values of the buttons and
+ * write them to settings-file
+ *************************************/
+void MimeTab::applySettings()
+{
+ QSettings settings;
+ settings.setValue("mime/parsemime" , mimeParseCheckBox->isChecked());
+ settings.setValue("mime/parseQP" , mimeQPCheckBox->isChecked());
+ settings.setValue("mime/openAttachment" , mimeOpenAttachmentCheckBox->isChecked());
+
+}
+
+AppearanceTab::AppearanceTab(QWidget *parent)
+ : QWidget(parent)
+{
+ /*****************************************
+ * Icon-Size-Box
+ *****************************************/
+ QGroupBox *iconSizeBox = new QGroupBox(tr("Iconsize"));
+ iconSizeGroup = new QButtonGroup();
+ iconSizeSmall = new QRadioButton(tr("small"));
+ iconSizeMedium = new QRadioButton(tr("medium"));
+ iconSizeLarge = new QRadioButton(tr("large"));
+
+ iconSizeGroup->addButton(iconSizeSmall, 1);
+ iconSizeGroup->addButton(iconSizeMedium, 2);
+ iconSizeGroup->addButton(iconSizeLarge, 3);
+
+ QHBoxLayout *iconSizeBoxLayout = new QHBoxLayout();
+ iconSizeBoxLayout->addWidget(iconSizeSmall);
+ iconSizeBoxLayout->addWidget(iconSizeMedium);
+ iconSizeBoxLayout->addWidget(iconSizeLarge);
+
+ iconSizeBox->setLayout(iconSizeBoxLayout);
+
+ /*****************************************
+ * Icon-Style-Box
+ *****************************************/
+ QGroupBox *iconStyleBox = new QGroupBox(tr("Iconstyle"));
+ iconStyleGroup = new QButtonGroup();
+ iconTextButton = new QRadioButton(tr("just text"));
+ iconIconsButton = new QRadioButton(tr("just icons"));
+ iconAllButton = new QRadioButton(tr("text and icons"));
+
+ iconStyleGroup->addButton(iconTextButton, 1);
+ iconStyleGroup->addButton(iconIconsButton, 2);
+ iconStyleGroup->addButton(iconAllButton, 3);
+
+ QHBoxLayout *iconStyleBoxLayout = new QHBoxLayout();
+ iconStyleBoxLayout->addWidget(iconTextButton);
+ iconStyleBoxLayout->addWidget(iconIconsButton);
+ iconStyleBoxLayout->addWidget(iconAllButton);
+
+ iconStyleBox->setLayout(iconStyleBoxLayout);
+
+ /*****************************************
+ * Window-Size-Box
+ *****************************************/
+ QGroupBox *windowSizeBox = new QGroupBox(tr("Windowstate"));
+ QHBoxLayout *windowSizeBoxLayout = new QHBoxLayout();
+ windowSizeCheckBox = new QCheckBox(tr("Save window size and position on exit."), this);
+ windowSizeBoxLayout->addWidget(windowSizeCheckBox);
+ windowSizeBox->setLayout(windowSizeBoxLayout);
+
+ QVBoxLayout *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(iconSizeBox);
+ mainLayout->addWidget(iconStyleBox);
+ mainLayout->addWidget(windowSizeBox);
+ mainLayout->addStretch(1);
+ setSettings();
+ setLayout(mainLayout);
+}
+
+/**********************************
+ * Read the settings from config
+ * and set the buttons and checkboxes
+ * appropriately
+ **********************************/
+void AppearanceTab::setSettings()
+{
+ QSettings settings;
+
+ //Iconsize
+ QSize iconSize = settings.value("toolbar/iconsize", QSize(24, 24)).toSize();
+ switch (iconSize.height()) {
+ case 12: iconSizeSmall->setChecked(true);
+ break;
+ case 24:iconSizeMedium->setChecked(true);
+ break;
+ case 32:iconSizeLarge->setChecked(true);
+ break;
+ }
+ // Iconstyle
+ Qt::ToolButtonStyle iconStyle = static_cast<Qt::ToolButtonStyle>(settings.value("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon).toUInt());
+ switch (iconStyle) {
+ case Qt::ToolButtonTextOnly: iconTextButton->setChecked(true);
+ break;
+ case Qt::ToolButtonIconOnly:iconIconsButton->setChecked(true);
+ break;
+ case Qt::ToolButtonTextUnderIcon:iconAllButton->setChecked(true);
+ break;
+ default:
+ break;
+ }
+
+ // Window Save and Position
+ if (settings.value("window/windowSave").toBool()) windowSizeCheckBox->setCheckState(Qt::Checked);
+
+}
+
+/***********************************
+ * get the values of the buttons and
+ * write them to settings-file
+ *************************************/
+void AppearanceTab::applySettings()
+{
+ QSettings settings;
+ switch (iconSizeGroup->checkedId()) {
+ case 1: settings.setValue("toolbar/iconsize", QSize(12, 12));
+ break;
+ case 2:settings.setValue("toolbar/iconsize", QSize(24, 24));
+ break;
+ case 3:settings.setValue("toolbar/iconsize", QSize(32, 32));
+ break;
+ }
+
+ switch (iconStyleGroup->checkedId()) {
+ case 1: settings.setValue("toolbar/iconstyle", Qt::ToolButtonTextOnly);
+ break;
+ case 2:settings.setValue("toolbar/iconstyle", Qt::ToolButtonIconOnly);
+ break;
+ case 3:settings.setValue("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon);
+ break;
+ }
+
+ settings.setValue("window/windowSave", windowSizeCheckBox->isChecked());
+}
+
+KeyserverTab::KeyserverTab(QWidget *parent)
+ : QWidget(parent)
+{
+ QVBoxLayout *mainLayout = new QVBoxLayout(this);
+
+ QLabel *label = new QLabel(tr("Default Keyserver for import:"));
+ comboBox = new QComboBox;
+ comboBox->setEditable(false);
+ comboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+
+ QWidget *addKeyServerBox = new QWidget(this);
+ QHBoxLayout *addKeyServerLayout = new QHBoxLayout(addKeyServerBox);
+ QLabel *http = new QLabel("http://");
+ newKeyServerEdit = new QLineEdit(this);
+ QPushButton *newKeyServerButton = new QPushButton(tr("Add to keyserverlist"), this);
+ connect(newKeyServerButton,SIGNAL(clicked()), this, SLOT(addKeyServer()));
+ addKeyServerLayout->addWidget(http);
+ addKeyServerLayout->addWidget(newKeyServerEdit);
+ addKeyServerLayout->addWidget(newKeyServerButton);
+
+ mainLayout->addWidget(label);
+ mainLayout->addWidget(comboBox);
+ mainLayout->addWidget(addKeyServerBox);
+ mainLayout->addStretch(1);
+
+ // Read keylist from ini-file and fill it into combobox
+ setSettings();
+}
+
+
+/**********************************
+ * Read the settings from config
+ * and set the buttons and checkboxes
+ * appropriately
+ **********************************/
+void KeyserverTab::setSettings()
+{
+ QSettings settings;
+ QString defKeyserver = settings.value("keyserver/defaultKeyServer").toString();
+
+ QStringList *keyServerList = new QStringList();
+ for(int i=0; i < comboBox->count(); i++) {
+ keyServerList->append(comboBox->itemText(i));
+ }
+ settings.setValue("keyserver/keyServerList", *keyServerList);
+}
+
+void KeyserverTab::addKeyServer()
+{
+ if (newKeyServerEdit->text().startsWith("http://")) {
+ comboBox->addItem(newKeyServerEdit->text());
+ } else {
+ comboBox->addItem("http://" +newKeyServerEdit->text());
+ }
+ comboBox->setCurrentIndex(comboBox->count()-1);
+}
+/***********************************
+ * get the values of the buttons and
+ * write them to settings-file
+ *************************************/
+void KeyserverTab::applySettings()
+{
+ QSettings settings;
+ settings.setValue("keyserver/defaultKeyServer",comboBox->currentText());
+}
+
+AdvancedTab::AdvancedTab(QWidget *parent)
+ : QWidget(parent)
+{
+ /*****************************************
+ * Steganography Box
+ *****************************************/
+ QGroupBox *steganoBox = new QGroupBox(tr("Show Steganography Options [Advanced]"));
+ QHBoxLayout *steganoBoxLayout = new QHBoxLayout();
+ steganoCheckBox= new QCheckBox(tr("Show Steganographic Options."), this);
+ steganoBoxLayout->addWidget(steganoCheckBox);
+ steganoBox->setLayout(steganoBoxLayout);
+
+ QVBoxLayout *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(steganoBox);
+ setSettings();
+ mainLayout->addStretch(1);
+ setLayout(mainLayout);
+
+}
+
+void AdvancedTab::setSettings()
+{
+ QSettings settings;
+ if (settings.value("advanced/steganography").toBool()){
+ steganoCheckBox->setCheckState(Qt::Checked);
+ }
+}
+
+void AdvancedTab::applySettings()
+{
+ QSettings settings;
+ settings.setValue("advanced/steganography", steganoCheckBox->isChecked());
+}
+
+GpgPathsTab::GpgPathsTab(QWidget *parent)
+ : QWidget(parent)
+{
+ setSettings();
+
+ /*****************************************
+ * Keydb Box
+ *****************************************/
+ QGroupBox *keydbBox = new QGroupBox(tr("Relative path to keydb"));
+ QGridLayout *keydbBoxLayout = new QGridLayout();
+
+ // Label containing the current keydbpath relative to default keydb path
+ keydbLabel = new QLabel(accKeydbPath,this);
+
+ QPushButton *keydbButton = new QPushButton("Change keydb path",this);
+ connect(keydbButton, SIGNAL(clicked()), this, SLOT(chooseKeydbDir()));
+ QPushButton *keydbDefaultButton = new QPushButton("Set keydb to default path",this);
+ connect(keydbDefaultButton, SIGNAL(clicked()), this, SLOT(setKeydbPathToDefault()));
+
+ keydbBox->setLayout(keydbBoxLayout);
+ keydbBoxLayout->addWidget(new QLabel(tr("Current keydb path: ")),1,1);
+ keydbBoxLayout->addWidget(keydbLabel,1,2);
+ keydbBoxLayout->addWidget(keydbButton,1,3);
+ keydbBoxLayout->addWidget(keydbDefaultButton,2,3);
+ keydbBoxLayout->addWidget(new QLabel(tr("<b>NOTE: </b> Gpg4usb will restart automatically if you change the keydb path!")),3,1,1,3);
+
+ QVBoxLayout *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(keydbBox);
+ mainLayout->addStretch(1);
+ setLayout(mainLayout);
+}
+
+QString GpgPathsTab::getRelativePath(const QString dir1,const QString dir2)
+{
+ QDir dir(dir1);
+ QString s;
+
+ s = dir.relativeFilePath(dir2);
+ qDebug() << "relative path: " << s;
+ if (s.isEmpty()) {
+ s = ".";
+ }
+ return s;
+}
+
+void GpgPathsTab::setKeydbPathToDefault()
+{
+ accKeydbPath = ".";
+ keydbLabel->setText(".");
+}
+
+QString GpgPathsTab::chooseKeydbDir()
+{
+ QString dir = QFileDialog::getExistingDirectory(this,tr ("Choose keydb directory"),accKeydbPath,QFileDialog::ShowDirsOnly);
+
+ accKeydbPath = getRelativePath(defKeydbPath, dir);
+ keydbLabel->setText(accKeydbPath);
+ return "";
+}
+
+void GpgPathsTab::setSettings()
+{
+ defKeydbPath = qApp->applicationDirPath() + "/keydb";
+
+ QSettings settings;
+ accKeydbPath = settings.value("gpgpaths/keydbpath").toString();
+ if (accKeydbPath.isEmpty()) {
+ accKeydbPath = ".";
+ }
+}
+
+void GpgPathsTab::applySettings()
+{
+ QSettings settings;
+ settings.setValue("gpgpaths/keydbpath",accKeydbPath);
+}
diff --git a/src/settingsdialog.h b/src/settingsdialog.h
new file mode 100755
index 0000000..0b5f164
--- /dev/null
+++ b/src/settingsdialog.h
@@ -0,0 +1,217 @@
+/*
+ * settingsdialog.h
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef __SETTINGSDIALOG_H__
+#define __SETTINGSDIALOG_H__
+
+#include "keylist.h"
+
+#include <QHash>
+#include <QWidget>
+#include <QtGui>
+
+QT_BEGIN_NAMESPACE
+class QDialog;
+class QRadioButton;
+class QDialogButtonBox;
+class QHBoxLayout;
+class QVBoxLayout;
+class QComboBox;
+class QCheckBox;
+class QDebug;
+class QSettings;
+class QApplication;
+class QDir;
+class QTranslator;
+class QLabel;
+class QButtonGroup;
+class QGroupBox;
+class QFileInfo;
+class QTabWidget;
+QT_END_NAMESPACE
+
+class GeneralTab : public QWidget
+ {
+ Q_OBJECT
+
+ public:
+ GeneralTab(GpgME::GpgContext *ctx, QWidget *parent = 0);
+ void setSettings();
+ void applySettings();
+
+ private:
+ QCheckBox *rememberPasswordCheckBox;
+ QCheckBox *importConfirmationcheckBox;
+ QCheckBox *saveCheckedKeysCheckBox;
+ QCheckBox *importConfirmationCheckBox;
+ QComboBox *langSelectBox;
+ QComboBox *ownKeySelectBox;
+ QHash<QString, QString> lang;
+ QHash<QString, QString> keyIds;
+ QString ownKeyId;
+ KeyList *mKeyList;
+ GpgME::GpgContext *mCtx; /** The current gpg context */
+
+private slots:
+ void slotOwnKeyIdChanged();
+ void slotLanguageChanged();
+
+signals:
+ void signalRestartNeeded(bool needed);
+
+};
+
+ class MimeTab : public QWidget
+ {
+ Q_OBJECT
+
+ public:
+ MimeTab(QWidget *parent = 0);
+ void setSettings();
+ void applySettings();
+
+ private:
+ QCheckBox *mimeParseCheckBox;
+ QCheckBox *mimeQPCheckBox;
+ QCheckBox *mimeOpenAttachmentCheckBox;
+
+ signals:
+ void signalRestartNeeded(bool needed);
+
+ };
+
+ class AppearanceTab : public QWidget
+ {
+ Q_OBJECT
+
+ public:
+ //void setSettings();
+ AppearanceTab(QWidget *parent = 0);
+ void setSettings();
+ void applySettings();
+
+ private:
+ QButtonGroup *iconStyleGroup;
+ QRadioButton *iconSizeSmall;
+ QRadioButton *iconSizeMedium;
+ QRadioButton *iconSizeLarge;
+ QButtonGroup *iconSizeGroup;
+ QRadioButton *iconTextButton;
+ QRadioButton *iconIconsButton;
+ QRadioButton *iconAllButton;
+ QCheckBox *windowSizeCheckBox;
+
+ signals:
+ void signalRestartNeeded(bool needed);
+
+ };
+
+ class KeyserverTab : public QWidget
+ {
+ Q_OBJECT
+
+ public:
+ KeyserverTab(QWidget *parent = 0);
+ void setSettings();
+ void applySettings();
+
+ private:
+ QComboBox *comboBox;
+ QLineEdit *newKeyServerEdit;
+
+ private slots:
+ void addKeyServer();
+
+ signals:
+ void signalRestartNeeded(bool needed);
+
+ };
+
+ class AdvancedTab : public QWidget
+ {
+ Q_OBJECT
+
+ public:
+ AdvancedTab(QWidget *parent = 0);
+ void setSettings();
+ void applySettings();
+
+ private:
+ QCheckBox *steganoCheckBox;
+
+ signals:
+ void signalRestartNeeded(bool needed);
+
+ };
+
+ class GpgPathsTab : public QWidget
+ {
+ Q_OBJECT
+ public:
+ GpgPathsTab(QWidget *parent = 0);
+ void applySettings();
+
+private:
+ QString getRelativePath(const QString dir1,const QString dir2);
+ QString defKeydbPath; /** The default keydb path used by gpg4usb */
+ QString accKeydbPath; /** The currently used keydb path */
+ QLabel *keydbLabel;
+ void setSettings();
+
+ private slots:
+ QString chooseKeydbDir();
+ void setKeydbPathToDefault();
+
+ };
+
+ class SettingsDialog : public QDialog
+{
+ Q_OBJECT
+
+ public:
+ SettingsDialog(GpgME::GpgContext *ctx, QWidget *parent = 0);
+ GeneralTab *generalTab;
+ MimeTab *mimeTab;
+ AppearanceTab *appearanceTab;
+ KeyserverTab *keyserverTab;
+ AdvancedTab *advancedTab;
+ GpgPathsTab *gpgPathsTab;
+ static QHash<QString, QString> listLanguages();
+
+ public slots:
+ void slotAccept();
+
+ signals:
+ void signalRestartNeeded(bool needed);
+
+ private:
+ QTabWidget *tabWidget;
+ QDialogButtonBox *buttonBox;
+ GpgME::GpgContext *mCtx; /** The current gpg context */
+ bool restartNeeded;
+ bool getRestartNeeded();
+
+ private slots:
+ void slotSetRestartNeeded(bool needed);
+
+};
+
+#endif // __SETTINGSDIALOG_H__
diff --git a/src/textedit.cpp b/src/textedit.cpp
new file mode 100644
index 0000000..e28304d
--- /dev/null
+++ b/src/textedit.cpp
@@ -0,0 +1,573 @@
+/*
+ * textedit.cpp
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "textedit.h"
+
+TextEdit::TextEdit()
+{
+ countPage = 0;
+ tabWidget = new QTabWidget(this);
+ tabWidget->setMovable(true);
+ tabWidget->setTabsClosable(true);
+ tabWidget->setDocumentMode(true);
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(tabWidget);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+ setLayout(layout);
+
+ connect(tabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(removeTab(int)));
+ slotNewTab();
+ setAcceptDrops(false);
+}
+
+void TextEdit::slotNewTab()
+{
+ QString header = tr("untitled") +
+ QString::number(++countPage)+".txt";
+
+ EditorPage *page = new EditorPage();
+ tabWidget->addTab(page, header);
+ tabWidget->setCurrentIndex(tabWidget->count() - 1);
+ page->getTextPage()->setFocus();
+ connect(page->getTextPage()->document(), SIGNAL(modificationChanged(bool)), this, SLOT(slotShowModified()));
+ }
+
+void TextEdit::slotNewHelpTab(QString title, QString path)
+{
+
+ HelpPage *page = new HelpPage(path);
+ tabWidget->addTab(page, title);
+ tabWidget->setCurrentIndex(tabWidget->count() - 1);
+
+}
+
+void TextEdit::slotOpen()
+{
+ QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Open file"),
+ QDir::currentPath());
+ foreach (QString fileName,fileNames){
+ if (!fileName.isEmpty()) {
+ QFile file(fileName);
+
+ if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ EditorPage *page = new EditorPage(fileName);
+
+ QTextStream in(&file);
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ page->getTextPage()->setPlainText(in.readAll());
+ page->setFilePath(fileName);
+ QTextDocument *document = page->getTextPage()->document();
+ document->setModified(false);
+
+ tabWidget->addTab(page, strippedName(fileName));
+ tabWidget->setCurrentIndex(tabWidget->count() - 1);
+ QApplication::restoreOverrideCursor();
+ page->getTextPage()->setFocus();
+ connect(page->getTextPage()->document(), SIGNAL(modificationChanged(bool)), this, SLOT(slotShowModified()));
+ //enableAction(true)
+ file.close();
+ } else {
+ QMessageBox::warning(this, tr("Application"),
+ tr("Cannot read file %1:\n%2.")
+ .arg(fileName)
+ .arg(file.errorString()));
+ }
+ }
+ }
+}
+
+void TextEdit::slotSave()
+{
+ if (tabWidget->count() == 0 || slotCurPage() == 0) {
+ return;
+ }
+
+ QString fileName = slotCurPage()->getFilePath();
+
+ if (fileName.isEmpty()) {
+ //QString docname = tabWidget->tabText(tabWidget->currentIndex());
+ //docname.remove(0,2);
+ slotSaveAs();
+ } else {
+ saveFile(fileName);
+ }
+}
+
+bool TextEdit::saveFile(const QString &fileName)
+{
+ if (fileName.isEmpty()) {
+ return false;
+ }
+
+ QFile file(fileName);
+
+ if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ EditorPage *page = slotCurPage();
+
+ QTextStream outputStream(&file);
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ outputStream << page->getTextPage()->toPlainText();
+ QApplication::restoreOverrideCursor();
+ QTextDocument *document = page->getTextPage()->document();
+
+ document->setModified(false);
+
+ int curIndex = tabWidget->currentIndex();
+ tabWidget->setTabText(curIndex, strippedName(fileName));
+ page->setFilePath(fileName);
+ // statusBar()->showMessage(tr("File saved"), 2000);
+ file.close();
+ return true;
+ } else {
+ QMessageBox::warning(this, tr("File"),
+ tr("Cannot write file %1:\n%2.")
+ .arg(fileName)
+ .arg(file.errorString()));
+ return false;
+ }
+}
+
+
+bool TextEdit::slotSaveAs()
+{
+ if (tabWidget->count() == 0 || slotCurPage() == 0) {
+ return true;
+ }
+
+ EditorPage *page = slotCurPage();
+ QString path;
+ if(page->getFilePath() != "") {
+ path = page->getFilePath();
+ } else {
+ path = tabWidget->tabText(tabWidget->currentIndex()).remove(0,2);
+ }
+
+ QString fileName = QFileDialog::getSaveFileName(this, tr("Save file "),
+ path);
+ return saveFile(fileName);
+}
+
+void TextEdit::slotCloseTab()
+{
+ removeTab(tabWidget->currentIndex());
+ if (tabWidget->count() != 0) {
+ slotCurPage()->getTextPage()->setFocus();
+ }
+}
+
+void TextEdit::removeTab(int index)
+{
+ // Do nothing, if no tab is opened
+ if (tabWidget->count() == 0) {
+ return;
+ }
+
+ // get the index of the actual current tab
+ int lastIndex = tabWidget->currentIndex();
+
+ // set the focus to argument index
+ tabWidget->setCurrentIndex(index);
+
+ if (maybeSaveCurrentTab(true)) {
+ tabWidget->removeTab(index);
+
+ if(index >= lastIndex) {
+ tabWidget->setCurrentIndex(lastIndex);
+ } else {
+ tabWidget->setCurrentIndex(lastIndex-1);
+ }
+ }
+
+ if (tabWidget->count() == 0) {
+ // enableAction(false);
+ }
+}
+
+
+ /**
+ * Check if current may need to be saved.
+ * Call this function before closing the currently active tab-
+ *
+ * If it returns false, the close event should be aborted.
+ */
+bool TextEdit::maybeSaveCurrentTab(bool askToSave) {
+
+ EditorPage *page = slotCurPage();
+ // if this page is no textedit, there should be nothing to save
+ if(page == 0) {
+ return true;
+ }
+ QTextDocument *document = page->getTextPage()->document();
+
+ if (document->isModified()) {
+ QMessageBox::StandardButton result = QMessageBox::Cancel;
+
+ // write title of tab to docname and remove the leading *
+ QString docname = tabWidget->tabText(tabWidget->currentIndex());
+ docname.remove(0,2);
+
+ QString filePath = page->getFilePath();
+ if (askToSave) {
+ result = QMessageBox::warning(this, tr("Unsaved document"),
+ tr("<h3>The document \"%1\" has been modified.<br/>Do you want to save your changes?</h3>").arg(docname)+
+ tr("<b>Note:</b> If you don't save these files, all changes are lost.<br/>"),
+ QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
+ }
+ if ((result == QMessageBox::Save) || (!askToSave)) {
+ if (filePath == "") {
+ //QString docname = tabWidget->tabText(tabWidget->currentIndex());
+ //docname.remove(0,2);
+ return slotSaveAs();
+ } else {
+ return saveFile(filePath);
+ }
+ } else if (result == QMessageBox::Discard) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool TextEdit::maybeSaveAnyTab()
+{
+ // get a list of all unsaved documents and their tabids
+ QHash<int, QString> unsavedDocs = this->unsavedDocuments();
+
+ /*
+ * no unsaved documents, so app can be closed
+ */
+ if (unsavedDocs.size() == 0) {
+ return true;
+ }
+ /*
+ * only 1 unsaved document -> set modified tab as current
+ * and show normal unsaved doc dialog
+ */
+ if(unsavedDocs.size() == 1) {
+ int modifiedTab = unsavedDocs.keys().at(0);
+ tabWidget->setCurrentIndex(modifiedTab);
+ return maybeSaveCurrentTab(true);
+ }
+
+ /*
+ * more than one unsaved documents
+ */
+ if(unsavedDocs.size() > 1) {
+ QHashIterator<int, QString> i (unsavedDocs);
+
+ QuitDialog *dialog;
+ dialog=new QuitDialog(this, unsavedDocs);
+ int result = dialog->exec();
+
+ // if result is QDialog::Rejected, discard or cancel was clicked
+ if (result == QDialog::Rejected){
+ // return true, if discard is clicked, so app can be closed
+ if (dialog->isDiscarded()){
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ bool allsaved=true;
+ QList <int> tabIdsToSave = dialog->getTabIdsToSave();
+
+ foreach (int tabId, tabIdsToSave) {
+ tabWidget->setCurrentIndex(tabId);
+ if (! maybeSaveCurrentTab(false)) {
+ allsaved=false;
+ }
+ }
+ if (allsaved) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+ // code should never reach this statement
+ return false;
+}
+
+
+QTextEdit* TextEdit::curTextPage()
+{
+ EditorPage *curTextPage = qobject_cast<EditorPage *>(tabWidget->currentWidget());
+ if(curTextPage != 0) {
+ return curTextPage->getTextPage();
+ } else {
+ return 0;
+ }
+}
+
+QTextBrowser* TextEdit::curHelpPage() {
+ HelpPage *curHelpPage = qobject_cast<HelpPage *>(tabWidget->currentWidget());
+ if(curHelpPage != 0) {
+ return curHelpPage->getBrowser();
+ } else {
+ return 0;
+ }
+}
+
+int TextEdit::tabCount()
+{
+ return tabWidget->count();
+}
+
+EditorPage* TextEdit::slotCurPage()
+{
+ EditorPage *curPage = qobject_cast<EditorPage *>(tabWidget->currentWidget());
+ return curPage;
+}
+
+void TextEdit::slotQuote()
+{
+ if (tabWidget->count() == 0 || curTextPage() == 0) {
+ return;
+ }
+
+ QTextCursor cursor(curTextPage()->document());
+
+ // beginEditBlock and endEditBlock() let operation look like single undo/redo operation
+ cursor.beginEditBlock();
+ cursor.setPosition(0);
+ cursor.insertText("> ");
+ while (!cursor.isNull() && !cursor.atEnd()) {
+ cursor.movePosition(QTextCursor::EndOfLine);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ if(!cursor.atEnd()) {
+ cursor.insertText("> ");
+ }
+ }
+ cursor.endEditBlock();
+}
+
+void TextEdit::slotFillTextEditWithText(QString text) {
+ QTextCursor cursor(curTextPage()->document());
+ cursor.beginEditBlock();
+ this->curTextPage()->selectAll();
+ this->curTextPage()->insertPlainText(text);
+ cursor.endEditBlock();
+}
+
+void TextEdit::loadFile(const QString &fileName)
+{
+ QFile file(fileName);
+ if (!file.open(QFile::ReadOnly | QFile::Text)) {
+ QMessageBox::warning(this, tr("Application"),
+ tr("Cannot read file %1:\n%2.")
+ .arg(fileName)
+ .arg(file.errorString()));
+ return;
+ }
+ QTextStream in(&file);
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ curTextPage()->setPlainText(in.readAll());
+ QApplication::restoreOverrideCursor();
+ slotCurPage()->setFilePath(fileName);
+ tabWidget->setTabText(tabWidget->currentIndex(), strippedName(fileName));
+ file.close();
+ // statusBar()->showMessage(tr("File loaded"), 2000);
+}
+
+QString TextEdit::strippedName(const QString &fullFileName)
+{
+ return QFileInfo(fullFileName).fileName();
+}
+
+void TextEdit::slotPrint()
+{
+ if (tabWidget->count() == 0) {
+ return;
+ }
+
+#ifndef QT_NO_PRINTER
+ QTextDocument *document;
+ if(curTextPage() == 0) {
+ document = curHelpPage()->document();
+ } else {
+ document = curTextPage()->document();
+ }
+ QPrinter printer;
+
+ QPrintDialog *dlg = new QPrintDialog(&printer, this);
+ if (dlg->exec() != QDialog::Accepted) {
+ return;
+ }
+ document->print(&printer);
+
+ //statusBar()->showMessage(tr("Ready"), 2000);
+#endif
+}
+
+void TextEdit::slotShowModified() {
+ int index=tabWidget->currentIndex();
+ QString title= tabWidget->tabText(index);
+ // if doc is modified now, add leading * to title,
+ // otherwise remove the leading * from the title
+ if(curTextPage()->document()->isModified()) {
+ tabWidget->setTabText(index, title.prepend("* "));
+ } else {
+ tabWidget->setTabText(index, title.remove(0,2));
+ }
+}
+
+void TextEdit::slotSwitchTabUp() {
+ if (tabWidget->count() > 1) {
+ int newindex=(tabWidget->currentIndex()+1)%(tabWidget->count());
+ tabWidget->setCurrentIndex(newindex);
+ }
+}
+
+void TextEdit::slotSwitchTabDown() {
+ if (tabWidget->count() > 1) {
+ int newindex=(tabWidget->currentIndex()-1+tabWidget->count())%tabWidget->count();
+ tabWidget->setCurrentIndex(newindex);
+ }
+}
+
+/*
+ * return a hash of tabindexes and title of unsaved tabs
+ */
+QHash<int, QString> TextEdit::unsavedDocuments() {
+ QHash<int, QString> unsavedDocs; // this list could be used to implement gedit like "unsaved changed"-dialog
+
+ for(int i=0; i < tabWidget->count(); i++) {
+ EditorPage *ep = qobject_cast<EditorPage *> (tabWidget->widget(i));
+ if(ep != 0 && ep->getTextPage()->document()->isModified()) {
+ QString docname = tabWidget->tabText(i);
+ // remove * before name of modified doc
+ docname.remove(0,2);
+ unsavedDocs.insert(i, docname);
+ }
+ }
+ return unsavedDocs;
+}
+
+void TextEdit::slotCut()
+{
+ if (tabWidget->count() == 0 || curTextPage() == 0) {
+ return;
+ }
+
+ curTextPage()->cut();
+}
+
+void TextEdit::slotCopy()
+{
+ if (tabWidget->count() == 0) {
+ return;
+ }
+
+ if(curTextPage() != 0) {
+ curTextPage()->copy();
+ } else {
+ curHelpPage()->copy();
+ }
+
+
+}
+
+void TextEdit::slotPaste()
+{
+ if (tabWidget->count() == 0 || curTextPage() == 0) {
+ return;
+ }
+
+ curTextPage()->paste();
+}
+
+void TextEdit::slotUndo()
+{
+ if (tabWidget->count() == 0 || curTextPage() == 0) {
+ return;
+ }
+
+ curTextPage()->undo();
+}
+
+void TextEdit::slotRedo()
+{
+ if (tabWidget->count() == 0 || curTextPage() == 0) {
+ return;
+ }
+
+ curTextPage()->redo();
+}
+
+void TextEdit::slotZoomIn()
+{
+ if (tabWidget->count() == 0 ) {
+ return;
+ }
+
+ if(curTextPage() != 0) {
+ curTextPage()->zoomIn();
+ } else {
+ curHelpPage()->zoomIn();
+ }
+
+}
+
+void TextEdit::slotZoomOut()
+{
+ if (tabWidget->count() == 0 ) {
+ return;
+ }
+
+ if(curTextPage() != 0) {
+ curTextPage()->zoomOut();
+ } else {
+ curHelpPage()->zoomOut();
+ }
+}
+
+void TextEdit::slotSelectAll()
+{
+ if (tabWidget->count() == 0 || curTextPage() == 0) {
+ return;
+ }
+
+ curTextPage()->selectAll();
+}
+
+/*void TextEdit::dragEnterEvent(QDragEnterEvent *event)
+{
+ if (event->mimeData()->hasFormat("text/plain"))
+ qDebug() << "enter textedit drag action";
+ event->acceptProposedAction();
+}
+
+void TextEdit::dropEvent(QDropEvent* event)
+{
+ curTextPage()->setPlainText(event->mimeData()->text());
+
+ foreach (QUrl tmp, event->mimeData()->urls())
+ {
+ qDebug() << tmp;
+ }
+
+ //event->acceptProposedAction();
+}
+*/
diff --git a/src/textedit.h b/src/textedit.h
new file mode 100644
index 0000000..12e4970
--- /dev/null
+++ b/src/textedit.h
@@ -0,0 +1,275 @@
+/*
+ * textedit.h
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef __TEXTEDIT_H__
+#define __TEXTEDIT_H__
+
+#include "editorpage.h"
+#include "helppage.h"
+#include "quitdialog.h"
+
+QT_BEGIN_NAMESPACE
+class QDebug;
+class QtGui;
+class QFileDialog;
+class QMessageBox;
+class QFileInfo;
+class QApplication;
+class QFile;
+class QTextEdit;
+class QFileDialog;
+class QMessageBox;
+class QWidget;
+class QString;
+class QTabWidget;
+QT_END_NAMESPACE
+
+/**
+ * @brief TextEdit class
+ */
+class TextEdit : public QWidget
+{
+ Q_OBJECT
+public:
+ /**
+ * @brief
+ */
+ TextEdit();
+
+ /**
+ * @details Load the content of file into the current textpage
+ *
+ * @param fileName QString containing the filename to load
+ * @return nothing
+ */
+ void loadFile(const QString &fileName);
+
+
+ /**
+ * @details Checks if there are unsaved documents in any tab,
+ * which may need to be saved. Call this function before
+ * closing the programme or all tabs.
+ * @return \li false, if the close event should be aborted.
+ * \li true, otherwise
+ */
+ bool maybeSaveAnyTab();
+
+ int tabCount();
+ /**
+ * @details textpage of the currently activated tab
+ * @return \li reference to QTextEdit if tab has one
+ * \li 0 otherwise (e.g. if helppage)
+ */
+ QTextEdit* curTextPage();
+
+ QTextBrowser* curHelpPage();
+
+ /**
+ * @details List of currently unsaved tabs.
+ * @returns QHash<int, QString> Hash of tabindexes and title of unsaved tabs.
+ */
+ QHash<int, QString> unsavedDocuments();
+
+ QTabWidget *tabWidget; /** Widget containing the tabs of the editor */
+
+public slots:
+ /**
+ * @details Return pointer to the currently activated tabpage.
+ *
+ */
+ EditorPage *slotCurPage();
+
+ /**
+ * @details Insert a ">" at the begining of every line of current textedit.
+ */
+ void slotQuote();
+
+ /**
+ * @details replace the text of currently active textedit with given text.
+ * @param text to fill on.
+ */
+ void slotFillTextEditWithText(QString text);
+
+ /**
+ * @details Saves the content of the current tab, if it has a filepath
+ * otherwise it calls saveAs for the current tab
+ */
+ void slotSave();
+
+ /**
+ * @details Opens a savefiledialog and calls saveFile with the choosen filename.
+ *
+ * @return Return the return value of the savefile method
+ */
+ bool slotSaveAs();
+
+ /**
+ * @details Show an OpenFileDoalog and open the file in a new tab.
+ * Shows an error dialog, if the open fails.
+ * Set the focus to the tab of the opened file.
+ */
+ void slotOpen();
+
+ /**
+ * @details Open a print-dialog for the current tab
+ */
+ void slotPrint();
+
+ /**
+ * @details Adds a new tab with the title "untitled"+countpage+".txt"
+ * Sets the focus to the new tab. Increase Tab-Count by one
+ */
+ void slotNewTab();
+
+ /**
+ * @details Adds a new tab with the given title and opens given html file.
+ * Increase Tab-Count by one
+ * @param title title for the tab
+ * @param path path for html file to show
+ */
+ void slotNewHelpTab(QString title, QString path);
+
+ /**
+ * @details put a * in front of current tabs title, if current textedit is modified
+ */
+ void slotShowModified();
+
+ /**
+ * @details close the current tab and decrease TabWidget->count by \a 1
+ *
+ */
+ void slotCloseTab();
+
+ /**
+ * @details Switch to the next tab.
+ *
+ */
+ void slotSwitchTabUp();
+
+ /**
+ * @details Switch to the previous tab.
+ *
+ */
+ void slotSwitchTabDown();
+
+private:
+ /**
+ * @details return just a filename stripped of a whole path
+ *
+ * @param a filename path
+ * @return QString containing the filename
+ */
+ QString strippedName(const QString &fullFileName);
+
+ /**
+ * @brief
+ *
+ */
+ bool maybeSaveFile();
+
+ /**
+ * @brief
+ *
+ * @param askToSave
+ */
+ bool maybeSaveCurrentTab(bool askToSave);
+
+ /****************************************************************************************
+ * Name: countPage
+ * Description: int cotaining the number of added tabs
+ */
+ int countPage; /* TODO */
+
+private slots:
+ /**
+ * @details Remove the tab with given index
+ *
+ * @param index Tab-number to remove
+ */
+ void removeTab(int index);
+
+ /**
+ * @details Cut selected text in current textpage.
+ */
+ void slotCut();
+
+ /**
+ * @details Copy selected text of current textpage to clipboard.
+ */
+ void slotCopy();
+
+ /**
+ * @details Paste text from clipboard to current textpage.
+ */
+ void slotPaste();
+
+ /**
+ * @details Undo last change in current textpage.
+ *
+ */
+ void slotUndo();
+ /****************************************************************************************
+ * Name: redo
+ * Description: redo last change in current textpage
+ * Parameters: none
+ * Return Values: none
+ * Change on members: none
+ */
+ /**
+ * @brief
+ *
+ */
+ void slotRedo();
+
+ void slotZoomIn();
+ void slotZoomOut();
+ /****************************************************************************************
+ * Name: selectAll
+ * Description: select all in current textpage
+ * Parameters: none
+ * Return Values: none
+ * Change on members: none
+ */
+ /**
+ * @brief
+ *
+ */
+ void slotSelectAll();
+
+protected:
+ // void dragEnterEvent(QDragEnterEvent *event);
+ // void dropEvent(QDropEvent* event);
+ /****************************************************************************************
+ * Name: saveFile
+ * Description: Saves the content of currentTab to the file filename
+ * Parameters: QString filename contains the full path of the file to save
+ * Return Values: true, if the file was saved succesfully
+ * false, if parameter filename is empty or the saving failed
+ * Change on members: sets isModified of the current tab to false
+ */
+ /**
+ * @brief
+ *
+ * @param fileName
+ */
+ bool saveFile(const QString &fileName);
+};
+#endif // __TEXTEDIT_H__
diff --git a/src/verifydetailsdialog.cpp b/src/verifydetailsdialog.cpp
new file mode 100644
index 0000000..fc9ab6c
--- /dev/null
+++ b/src/verifydetailsdialog.cpp
@@ -0,0 +1,103 @@
+/*
+ * verifydetailsdialog.cpp
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "verifydetailsdialog.h"
+
+VerifyDetailsDialog::VerifyDetailsDialog(QWidget *parent, GpgME::GpgContext* ctx, KeyList* keyList, QByteArray* inputData, QByteArray* inputSignature) :
+ QDialog(parent)
+{
+ mCtx = ctx;
+ mKeyList = keyList;
+ //mTextpage = edit;
+ mInputData = inputData;
+ mInputSignature = inputSignature;
+
+ this->setWindowTitle(tr("Signaturedetails"));
+
+ connect(mCtx, SIGNAL(keyDBChanged()), this, SLOT(slotRefresh()));
+ mainLayout = new QHBoxLayout();
+ this->setLayout(mainLayout);
+
+ mVbox = new QWidget();
+ slotRefresh();
+
+ this->exec();
+}
+
+void VerifyDetailsDialog::slotRefresh()
+{
+ mVbox->close();
+
+ mVbox = new QWidget();
+ QVBoxLayout *mVboxLayout = new QVBoxLayout(mVbox);
+ mainLayout->addWidget(mVbox);
+
+ // Button Box for close button
+ buttonBox = new QDialogButtonBox(QDialogButtonBox::Close);
+ connect(buttonBox, SIGNAL(rejected()), this, SLOT(close()));
+
+ // Get signature information of current text
+ //QByteArray text = mTextpage->toPlainText().toUtf8();
+ //mCtx->preventNoDataErr(&text);
+ gpgme_signature_t sign;
+ if(mInputSignature != 0) {
+ sign = mCtx->verify(mInputData, mInputSignature);
+ } else {
+ sign = mCtx->verify(mInputData);
+ }
+
+ if(sign==0) {
+ mVboxLayout->addWidget(new QLabel(tr("No valid input found")));
+ mVboxLayout->addWidget(buttonBox);
+ return;
+ }
+
+ // Get timestamp of signature of current text
+ QDateTime timestamp;
+ timestamp.setTime_t(sign->timestamp);
+
+ // Set the title widget depending on sign status
+ if(gpg_err_code(sign->status) == GPG_ERR_BAD_SIGNATURE) {
+ mVboxLayout->addWidget(new QLabel(tr("Error Validating signature")));
+ } else if (mInputSignature != 0) {
+ mVboxLayout->addWidget(new QLabel(tr("File was signed on <br/> %1 by:<br/>").arg(timestamp.toString(Qt::SystemLocaleLongDate))));
+ } else {
+ switch (mCtx->textIsSigned(*mInputData))
+ {
+ case 2:
+ {
+ mVboxLayout->addWidget(new QLabel(tr("Text was completely signed on <br/> %1 by:<br/>").arg(timestamp.toString(Qt::SystemLocaleLongDate)))); break;
+ }
+ case 1:
+ {
+ mVboxLayout->addWidget(new QLabel(tr("Text was partially signed on <br/> %1 by:<br/>").arg(timestamp.toString(Qt::SystemLocaleLongDate)))); break;
+ }
+ }
+ }
+ // Add informationbox for every single key
+ while (sign) {
+ VerifyKeyDetailBox *sbox = new VerifyKeyDetailBox(this,mCtx,mKeyList,sign);
+ sign = sign->next;
+ mVboxLayout->addWidget(sbox);
+ }
+
+ mVboxLayout->addWidget(buttonBox);
+}
diff --git a/src/verifydetailsdialog.h b/src/verifydetailsdialog.h
new file mode 100644
index 0000000..b138f46
--- /dev/null
+++ b/src/verifydetailsdialog.h
@@ -0,0 +1,48 @@
+/*
+ * verifydetailsdialog.h
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef __VERIFYDETAILSDIALOG_H__
+#define __VERIFYDETAILSDIALOG_H__
+
+#include "editorpage.h"
+#include "verifykeydetailbox.h"
+#include <QDialog>
+
+class VerifyDetailsDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ explicit VerifyDetailsDialog(QWidget *parent, GpgME::GpgContext* ctx, KeyList* mKeyList, QByteArray* inputData, QByteArray* inputSignature = 0);
+
+private slots:
+ void slotRefresh();
+
+private:
+ GpgME::GpgContext *mCtx;
+ KeyList *mKeyList;
+ QHBoxLayout *mainLayout;
+ QWidget *mVbox;
+ QByteArray* mInputData; /** Data to be verified */
+ QByteArray* mInputSignature; /** Data to be verified */
+ QDialogButtonBox* buttonBox;
+};
+
+#endif // __VERIFYDETAILSDIALOG_H__
diff --git a/src/verifykeydetailbox.cpp b/src/verifykeydetailbox.cpp
new file mode 100644
index 0000000..b040d4f
--- /dev/null
+++ b/src/verifykeydetailbox.cpp
@@ -0,0 +1,99 @@
+/*
+ * verifydetailbox.cpp
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "verifykeydetailbox.h"
+
+VerifyKeyDetailBox::VerifyKeyDetailBox(QWidget *parent, GpgME::GpgContext* ctx, KeyList* keyList, gpgme_signature_t signature) :
+ QGroupBox(parent)
+{
+ this->mCtx = ctx;
+ this->mKeyList = keyList;
+ this->fpr=signature->fpr;
+
+ QGridLayout *grid = new QGridLayout();
+
+ switch (gpg_err_code(signature->status))
+ {
+ case GPG_ERR_NO_PUBKEY:
+ {
+ QPushButton *importButton = new QPushButton(tr("Import from keyserver"));
+ connect(importButton, SIGNAL(clicked()), this, SLOT(slotImportFormKeyserver()));
+
+ this->setTitle(tr("Key not present with id 0x") + signature->fpr);
+
+ grid->addWidget(new QLabel(tr("Status:")), 0, 0);
+ //grid->addWidget(new QLabel(tr("Fingerprint:")), 1, 0);
+ grid->addWidget(new QLabel(tr("Key not present in keylist")), 0, 1);
+ //grid->addWidget(new QLabel(signature->fpr), 1, 1);
+ grid->addWidget(importButton, 2,0,2,1);
+ break;
+ }
+ case GPG_ERR_NO_ERROR:
+ {
+ GpgKey key = mCtx->getKeyByFpr(signature->fpr);
+
+ this->setTitle(key.name);
+ grid->addWidget(new QLabel(tr("Name:")), 0, 0);
+ grid->addWidget(new QLabel(tr("EMail:")), 1, 0);
+ grid->addWidget(new QLabel(tr("Fingerprint:")), 2, 0);
+ grid->addWidget(new QLabel(tr("Status:")), 3, 0);
+
+ grid->addWidget(new QLabel(key.name), 0, 1);
+ grid->addWidget(new QLabel(key.email), 1, 1);
+ grid->addWidget(new QLabel(beautifyFingerprint(signature->fpr)), 2, 1);
+ grid->addWidget(new QLabel(tr("OK")), 3, 1);
+
+ break;
+ }
+ default:
+ {
+ GpgKey key = mCtx->getKeyById(signature->fpr);
+ this->setTitle(tr("Error for key with id 0x") + fpr);
+ grid->addWidget(new QLabel(tr("Name:")), 0, 0);
+ grid->addWidget(new QLabel(tr("EMail:")), 1, 0);
+ grid->addWidget(new QLabel(tr("Status:")), 2, 0);
+ grid->addWidget(new QLabel(tr("Fingerprint:")), 3, 0);
+
+ grid->addWidget(new QLabel(key.name), 0, 1);
+ grid->addWidget(new QLabel(key.email), 1, 1);
+ grid->addWidget(new QLabel(gpg_strerror(signature->status)), 2, 1);
+ grid->addWidget(new QLabel(beautifyFingerprint(key.fpr)), 3, 1);
+
+ break;
+ }
+ }
+ this->setLayout(grid);
+}
+
+void VerifyKeyDetailBox::slotImportFormKeyserver()
+{
+ KeyServerImportDialog *importDialog =new KeyServerImportDialog(mCtx,mKeyList,this);
+ importDialog->slotImport(QStringList(fpr));
+}
+
+QString VerifyKeyDetailBox::beautifyFingerprint(QString fingerprint)
+{
+ uint len = fingerprint.length();
+ if ((len > 0) && (len % 4 == 0))
+ for (uint n = 0; 4 *(n + 1) < len; ++n)
+ fingerprint.insert(5 * n + 4, ' ');
+ return fingerprint;
+}
diff --git a/src/verifykeydetailbox.h b/src/verifykeydetailbox.h
new file mode 100644
index 0000000..29d198e
--- /dev/null
+++ b/src/verifykeydetailbox.h
@@ -0,0 +1,47 @@
+/*
+ * verifydetailbox.h
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef __VERIFYKEYDETAILBOX_H__
+#define __VERIFYKEYDETAILBOX_H__
+
+#include "keylist.h"
+#include "keyserverimportdialog.h"
+#include <QDialog>
+#include <QGroupBox>
+
+class VerifyKeyDetailBox: public QGroupBox
+{
+ Q_OBJECT
+public:
+ explicit VerifyKeyDetailBox(QWidget *parent, GpgME::GpgContext* ctx, KeyList* mKeyList, gpgme_signature_t signature);
+
+private slots:
+ void slotImportFormKeyserver();
+
+private:
+ GpgME::GpgContext* mCtx;
+ KeyList* mKeyList;
+ QString beautifyFingerprint(QString fingerprint);
+ QString fpr;
+};
+
+#endif // __VERIFYKEYDETAILBOX_H__
+
diff --git a/src/verifynotification.cpp b/src/verifynotification.cpp
new file mode 100644
index 0000000..6e73961
--- /dev/null
+++ b/src/verifynotification.cpp
@@ -0,0 +1,185 @@
+/*
+ * verifynotification.cpp
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "verifynotification.h"
+
+VerifyNotification::VerifyNotification(QWidget *parent, GpgME::GpgContext *ctx, KeyList *keyList,QTextEdit *edit) :
+ QWidget(parent)
+{
+ mCtx = ctx;
+ mKeyList = keyList;
+ mTextpage = edit;
+ verifyLabel = new QLabel(this);
+
+ connect(mCtx, SIGNAL(keyDBChanged()), this, SLOT(slotRefresh()));
+ connect(edit, SIGNAL(textChanged()), this, SLOT(close()));
+
+ importFromKeyserverAct = new QAction(tr("Import missing key from Keyserver"), this);
+ connect(importFromKeyserverAct, SIGNAL(triggered()), this, SLOT(slotImportFromKeyserver()));
+
+ showVerifyDetailsAct = new QAction(tr("Show detailed verify information"), this);
+ connect(showVerifyDetailsAct, SIGNAL(triggered()), this, SLOT(slotShowVerifyDetails()));
+
+ detailMenu = new QMenu(this);
+ detailMenu->addAction(showVerifyDetailsAct);
+ detailMenu->addAction(importFromKeyserverAct);
+ importFromKeyserverAct->setVisible(false);
+
+ keysNotInList = new QStringList();
+ detailsButton = new QPushButton(tr("Details"),this);
+ detailsButton->setMenu(detailMenu);
+ QHBoxLayout *notificationWidgetLayout = new QHBoxLayout(this);
+ notificationWidgetLayout->setContentsMargins(10,0,0,0);
+ notificationWidgetLayout->addWidget(verifyLabel,2);
+ notificationWidgetLayout->addWidget(detailsButton);
+ this->setLayout(notificationWidgetLayout);
+}
+
+void VerifyNotification::slotImportFromKeyserver()
+{
+ KeyServerImportDialog *importDialog =new KeyServerImportDialog(mCtx,mKeyList, this);
+ importDialog->slotImport(*keysNotInList);
+}
+
+void VerifyNotification::setVerifyLabel(QString text, verify_label_status verifyLabelStatus)
+{
+ QString color;
+ verifyLabel->setText(text);
+ switch (verifyLabelStatus) {
+ case VERIFY_ERROR_OK: color="#ccffcc";
+ break;
+ case VERIFY_ERROR_WARN: color="#ececba";
+ break;
+ case VERIFY_ERROR_CRITICAL: color="#ff8080";
+ break;
+ default:
+ break;
+ }
+
+ verifyLabel->setAutoFillBackground(true);
+ QPalette status = verifyLabel->palette();
+ status.setColor(QPalette::Background, color);
+ verifyLabel->setPalette(status);
+}
+
+void VerifyNotification::showImportAction(bool visible)
+{
+ importFromKeyserverAct->setVisible(visible);
+}
+
+void VerifyNotification::slotShowVerifyDetails()
+{
+ QByteArray text = mTextpage->toPlainText().toUtf8();
+ mCtx->preventNoDataErr(&text);
+ new VerifyDetailsDialog(this, mCtx, mKeyList, &text);
+}
+
+bool VerifyNotification::slotRefresh()
+{
+ verify_label_status verifyStatus=VERIFY_ERROR_OK;
+
+ QByteArray text = mTextpage->toPlainText().toUtf8();
+ mCtx->preventNoDataErr(&text);
+ int textIsSigned = mCtx->textIsSigned(text);
+
+ gpgme_signature_t sign = mCtx->verify(&text);
+
+ if (sign == NULL) {
+ return false;
+ }
+
+ QString verifyLabelText;
+ bool unknownKeyFound=false;
+
+ while (sign) {
+
+ switch (gpg_err_code(sign->status))
+ {
+ case GPG_ERR_NO_PUBKEY:
+ {
+ verifyStatus=VERIFY_ERROR_WARN;
+ verifyLabelText.append(tr("Key not present with id 0x")+QString(sign->fpr));
+ this->keysNotInList->append(sign->fpr);
+ unknownKeyFound=true;
+ break;
+ }
+ case GPG_ERR_NO_ERROR:
+ {
+ GpgKey key = mCtx->getKeyByFpr(sign->fpr);
+ verifyLabelText.append(key.name);
+ if (!key.email.isEmpty()) {
+ verifyLabelText.append("<"+key.email+">");
+ }
+ break;
+ }
+ case GPG_ERR_BAD_SIGNATURE:
+ {
+ textIsSigned = 3;
+ verifyStatus=VERIFY_ERROR_CRITICAL;
+ GpgKey key = mCtx->getKeyById(sign->fpr);
+ verifyLabelText.append(key.name);
+ if (!key.email.isEmpty()) {
+ verifyLabelText.append("<"+key.email+">");
+ }
+ break;
+ }
+ default:
+ {
+ //textIsSigned = 3;
+ verifyStatus=VERIFY_ERROR_WARN;
+ //GpgKey key = mKeyList->getKeyByFpr(sign->fpr);
+ verifyLabelText.append(tr("Error for key with fingerprint ")+mCtx->beautifyFingerprint(QString(sign->fpr)));
+ break;
+ }
+ }
+ verifyLabelText.append("\n");
+ sign = sign->next;
+ }
+
+ switch (textIsSigned)
+ {
+ case 3:
+ {
+ verifyLabelText.prepend(tr("Error validating signature by: "));
+ break;
+ }
+ case 2:
+ {
+ verifyLabelText.prepend(tr("Text was completely signed by: "));
+ break;
+ }
+ case 1:
+ {
+ verifyLabelText.prepend(tr("Text was partially signed by: "));
+ break;
+ }
+ }
+
+ // If an unknown key is found, enable the importfromkeyserveraction
+ this->showImportAction(unknownKeyFound);
+
+ // Remove the last linebreak
+ verifyLabelText.remove(verifyLabelText.length()-1,1);
+
+ this->setVerifyLabel(verifyLabelText,verifyStatus);
+
+ return true;
+}
diff --git a/src/verifynotification.h b/src/verifynotification.h
new file mode 100644
index 0000000..60e55f9
--- /dev/null
+++ b/src/verifynotification.h
@@ -0,0 +1,109 @@
+/*
+ * verifynotification.h
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef __VERIFYNOTIFICATION_H__
+#define __VERIFYNOTIFICATION_H__
+
+#include "editorpage.h"
+#include "verifydetailsdialog.h"
+#include <gpgme.h>
+#include <QWidget>
+
+QT_BEGIN_NAMESPACE
+class QLabel;
+class QHBoxLayout;
+class QMenu;
+class QPushButton;
+QT_END_NAMESPACE
+
+/**
+ * @details Enumeration for the status of Verifylabel
+ */
+typedef enum
+{
+ VERIFY_ERROR_OK = 0,
+ VERIFY_ERROR_WARN = 1,
+ VERIFY_ERROR_CRITICAL = 2,
+ VERIFY_ERROR_NEUTRAL =3,
+} verify_label_status;
+
+/**
+ * @brief Class for handling the verifylabel shown at buttom of a textedit-page
+ */
+class VerifyNotification : public QWidget
+{
+ Q_OBJECT
+public:
+ /**
+ * @brief
+ *
+ * @param ctx The GPGme-Context
+ * @param parent The parent widget
+ */
+ explicit VerifyNotification(QWidget *parent, GpgME::GpgContext *ctx, KeyList *keyList,QTextEdit *edit);
+ /**
+ * @details Set the text and background-color of verify notification.
+ *
+ * @param text The text to be set.
+ * @param verifyLabelStatus The status of label to set the specified color.
+ */
+ void setVerifyLabel(QString text, verify_label_status verifyLabelStatus);
+
+ /**
+ * @details Show the import from keyserver-action in detailsmenu.
+ * @param visible show the action, if visible is true, otherwise hide it.
+ */
+ void showImportAction(bool visible);
+
+ QStringList *keysNotInList; /** List with keys, which are in signature but not in keylist */
+
+
+public slots:
+ /**
+ * @details Import the keys contained in keysNotInList from keyserver
+ *
+ */
+ void slotImportFromKeyserver();
+
+ /**
+ * @details Show a dialog with signing details.
+ */
+ void slotShowVerifyDetails();
+
+ /**
+ * @details Refresh the contents of dialog.
+ */
+ bool slotRefresh();
+
+private:
+ QMenu *detailMenu; /** Menu for te Button in verfiyNotification */
+ QAction *importFromKeyserverAct; /** Action for importing keys from keyserver which are notin keylist */
+ QAction *showVerifyDetailsAct; /** Action for showing verify detail dialog */
+ QPushButton *detailsButton; /** Button shown in verifynotification */
+ QLabel *verifyLabel; /** Label holding the text shown in verifyNotification */
+ GpgME::GpgContext *mCtx; /** GpgME Context */
+ KeyList *mKeyList; /** Table holding the keys */
+ QTextEdit *mTextpage; /** Textedit associated to the notification */
+ QVector<QString> verifyDetailStringVector; /** Vector containing the text for labels in verifydetaildialog */
+ QVector<verify_label_status> verifyDetailStatusVector; /** Vector containing the status for labels in verifydetaildialog */
+
+};
+#endif // __VERIFYNOTIFICATION_H__
diff --git a/src/wizard.cpp b/src/wizard.cpp
new file mode 100644
index 0000000..675af55
--- /dev/null
+++ b/src/wizard.cpp
@@ -0,0 +1,431 @@
+/* * wizard.cpp
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include <QtGui>
+
+#include "wizard.h"
+
+#ifdef Q_OS_WIN
+#include "windows.h"
+#endif
+
+Wizard::Wizard(GpgME::GpgContext *ctx, KeyMgmt *keyMgmt, QWidget *parent)
+ : QWizard(parent)
+{
+ mCtx=ctx;
+ mKeyMgmt=keyMgmt;
+
+ setPage(Page_Intro,new IntroPage(this));
+ setPage(Page_Choose, new ChoosePage(this));
+ setPage(Page_ImportFromGpg4usb,new ImportFromGpg4usbPage(mCtx, mKeyMgmt, this));
+ setPage(Page_ImportFromGnupg,new ImportFromGnupgPage(mCtx, mKeyMgmt, this));
+ setPage(Page_GenKey,new KeyGenPage(mCtx, this));
+ setPage(Page_Conclusion,new ConclusionPage(this));
+#ifndef Q_WS_MAC
+ setWizardStyle(ModernStyle);
+#endif
+ setWindowTitle(tr("First Start Wizard"));
+
+ // http://www.flickr.com/photos/laureenp/6141822934/
+ setPixmap(QWizard::WatermarkPixmap, QPixmap(":/keys2.jpg"));
+ setPixmap(QWizard::LogoPixmap, QPixmap(":/logo_small.png"));
+ setPixmap(QWizard::BannerPixmap, QPixmap(":/banner.png"));
+
+ QSettings settings;
+ setStartId(settings.value("wizard/nextPage", -1).toInt());
+ settings.remove("wizard/nextPage");
+
+ connect(this, SIGNAL(accepted()), this, SLOT(slotWizardAccepted()));
+ connect(this, SIGNAL(signalOpenHelp(QString)), parentWidget(), SLOT(signalOpenHelp(QString)));
+
+}
+
+void Wizard::slotWizardAccepted() {
+ QSettings settings;
+ // Don't show is mapped to show -> negation
+ settings.setValue("wizard/showWizard", !field("showWizard").toBool());
+
+ if(field("openHelp").toBool()) {
+ emit signalOpenHelp("docu.html#content");
+ }
+}
+
+bool Wizard::importPubAndSecKeysFromDir(const QString dir, KeyMgmt *keyMgmt)
+{
+ QFile secRingFile(dir+"/secring.gpg");
+ QFile pubRingFile(dir+"/pubring.gpg");
+
+ // Return, if no keyrings are found in subdir of chosen dir
+ if (!(pubRingFile.exists() or secRingFile.exists())) {
+ QMessageBox::critical(0, tr("Import Error"), tr("Couldn't locate any keyring file in %1").arg(dir));
+ return false;
+ }
+
+ QByteArray inBuffer;
+ if (secRingFile.exists()) {
+ // write content of secringfile to inBuffer
+ if (!secRingFile.open(QIODevice::ReadOnly)) {
+ QMessageBox::critical(0, tr("Import error"), tr("Couldn't open private keyringfile: %1").arg(secRingFile.fileName()));
+ return false;
+ }
+ inBuffer = secRingFile.readAll();
+ secRingFile.close();
+ }
+
+ if (pubRingFile.exists()) {
+ // try to import public keys
+ if (!pubRingFile.open(QIODevice::ReadOnly)) {
+ QMessageBox::critical(0, tr("Import error"), tr("Couldn't open public keyringfile: %1").arg(pubRingFile.fileName()));
+ return false;
+ }
+ inBuffer.append(pubRingFile.readAll());
+ pubRingFile.close();
+ }
+ keyMgmt->slotImportKeys(inBuffer);
+ inBuffer.clear();
+
+ return true;
+}
+
+IntroPage::IntroPage(QWidget *parent)
+ : QWizardPage(parent)
+{
+ setTitle(tr("Getting started..."));
+ setSubTitle(tr("... with gpg4usb"));
+
+ QLabel *topLabel = new QLabel(tr("To use gpg4usb for decrypting and signing messages, you need a "
+ "private key. The next page will help you with "
+ "key generation or import.<br><br>"
+ "For more information have a look at the <a href='docu_concepts.html'>concepts</a> "
+ "(by clicking the link, the page will open in the main window). <br>"));
+ topLabel->setWordWrap(true);
+ connect(topLabel, SIGNAL(linkActivated(const QString&)), parentWidget()->parentWidget(), SLOT(openHelp(const QString&)));
+
+ // QComboBox for language selection
+ QLabel *langLabel = new QLabel(tr("Choose a Language"));
+ langLabel->setWordWrap(true);
+
+ languages = SettingsDialog::listLanguages();
+ QComboBox *langSelectBox = new QComboBox();
+
+ foreach(QString l, languages) {
+ langSelectBox->addItem(l);
+ }
+ // selected entry from config
+ QSettings settings;
+ QString langKey = settings.value("int/lang").toString();
+ QString langValue = languages.value(langKey);
+ if (langKey != "") {
+ langSelectBox->setCurrentIndex(langSelectBox->findText(langValue));
+ }
+
+ connect(langSelectBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(slotLangChange(QString)));
+
+ // set layout and add widgets
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(topLabel);
+ layout->addWidget(langLabel);
+ layout->addWidget(langSelectBox);
+ setLayout(layout);
+}
+
+void IntroPage::slotLangChange(QString lang) {
+ QSettings settings;
+ settings.setValue("int/lang", languages.key(lang));
+ settings.setValue("wizard/nextPage", this->wizard()->currentId());
+ qApp->exit(RESTART_CODE);
+}
+
+int IntroPage::nextId() const
+{
+ return Wizard::Page_Choose;
+}
+ChoosePage::ChoosePage(QWidget *parent)
+ : QWizardPage(parent)
+{
+ setTitle(tr("Choose your action..."));
+ setSubTitle(tr("...by clicking on the apropriate link."));
+
+ QLabel *keygenLabel = new QLabel(tr("If you have never used gpg4usb before and also don't own a gpg key yet you "
+ "may possibly want to ")+"<a href=""Wizard::Page_GenKey"">"
+ +tr("create a new keypair")+"</a><hr>");
+ keygenLabel->setWordWrap(true);
+ connect(keygenLabel, SIGNAL(linkActivated(const QString&)), this, SLOT(slotJumpPage(const QString&)));
+
+ QLabel *importGpg4usbLabel = new QLabel(tr("If you upgrade from an older version of gpg4usb you may want to ")
+ +"<a href=""Wizard::Page_ImportFromGpg4usb"">"
+ +tr("import settings and/or keys from gpg4usb")+"</a>");
+ importGpg4usbLabel->setWordWrap(true);
+ connect(importGpg4usbLabel, SIGNAL(linkActivated(const QString&)), this, SLOT(slotJumpPage(const QString&)));
+
+ QLabel *importGnupgLabel = new QLabel(tr("If you are already using GnuPG you may want to ")
+ +"<a href=""Wizard::Page_ImportFromGnupg"">"
+ +tr("import keys from GnuPG")+"</a><hr>");
+ importGnupgLabel->setWordWrap(true);
+ connect(importGnupgLabel, SIGNAL(linkActivated(const QString&)), this, SLOT(slotJumpPage(const QString&)));
+
+ QVBoxLayout *layout = new QVBoxLayout();
+ layout->addWidget(keygenLabel);
+ layout->addWidget(importGnupgLabel);
+ layout->addWidget(importGpg4usbLabel);
+ setLayout(layout);
+ nextPage=Wizard::Page_Conclusion;
+}
+
+int ChoosePage::nextId() const
+{
+ return nextPage;
+}
+
+void ChoosePage::slotJumpPage(const QString& page)
+{
+ QMetaObject qmo = Wizard::staticMetaObject;
+ int index = qmo.indexOfEnumerator("WizardPages");
+ QMetaEnum m = qmo.enumerator(index);
+
+ nextPage = m.keyToValue(page.toAscii().data());
+ wizard()->next();
+}
+
+ImportFromGpg4usbPage::ImportFromGpg4usbPage(GpgME::GpgContext *ctx, KeyMgmt *keyMgmt, QWidget *parent)
+ : QWizardPage(parent)
+{
+ mCtx=ctx;
+ mKeyMgmt=keyMgmt;
+ setTitle(tr("Import from..."));
+ setSubTitle(tr("...existing gpg4usb"));
+
+ QLabel *topLabel = new QLabel(tr("You can import keys and/or settings from existing gpg4usb. <br><br>"
+ "Just check what you want to import, click the import button and choose "
+ "the directory of your other gpg4usb in the appearing file dialog."), this);
+ topLabel->setWordWrap(true);
+
+ gpg4usbKeyCheckBox = new QCheckBox();
+ gpg4usbKeyCheckBox->setChecked(true);
+ QLabel *keyLabel = new QLabel(tr("Keys"));
+
+ gpg4usbConfigCheckBox = new QCheckBox();
+ gpg4usbConfigCheckBox->setChecked(true);
+ QLabel *configLabel = new QLabel(tr("Configuration"));
+
+ QPushButton *importFromGpg4usbButton = new QPushButton(tr("Import from gpg4usb"));
+ connect(importFromGpg4usbButton, SIGNAL(clicked()), this, SLOT(slotImportFromOlderGpg4usb()));
+
+ QGridLayout *gpg4usbLayout = new QGridLayout();
+ gpg4usbLayout->addWidget(topLabel,1,1,1,2);
+ gpg4usbLayout->addWidget(gpg4usbKeyCheckBox,2,1,Qt::AlignRight);
+ gpg4usbLayout->addWidget(keyLabel,2,2);
+ gpg4usbLayout->addWidget(gpg4usbConfigCheckBox,3,1,Qt::AlignRight);
+ gpg4usbLayout->addWidget(configLabel,3,2);
+ gpg4usbLayout->addWidget(importFromGpg4usbButton,4,2);
+
+ this->setLayout(gpg4usbLayout);
+}
+
+void ImportFromGpg4usbPage::slotImportFromOlderGpg4usb()
+{
+ QString dir = QFileDialog::getExistingDirectory(this,tr("Other gpg4usb directory"));
+
+ // Return, if cancel was hit
+ if (dir.isEmpty()) {
+ return;
+ }
+
+ // try to import keys, if appropriate box is checked, return, if import was unsuccessful
+ if (gpg4usbKeyCheckBox->isChecked()) {
+ if (!Wizard::importPubAndSecKeysFromDir(dir+"/keydb",mKeyMgmt)) {
+ return;
+ }
+ }
+
+ // try to import config, if appropriate box is checked
+ if (gpg4usbConfigCheckBox->isChecked()) {
+ slotImportConfFromGpg4usb(dir);
+
+ QSettings settings;
+ settings.setValue("wizard/nextPage", this->nextId());
+ QMessageBox::information(0,tr("Configuration Imported"),tr("Imported Configuration from old gpg4usb.<br>"
+ "Will now restart to activate the configuration."));
+ // TODO: edit->maybesave?
+ qApp->exit(RESTART_CODE);
+ }
+ wizard()->next();
+}
+
+bool ImportFromGpg4usbPage::slotImportConfFromGpg4usb(QString dir) {
+ QString path = dir+"/conf/gpg4usb.ini";
+ QSettings oldconf(path, QSettings::IniFormat, this);
+ QSettings actualConf;
+ foreach(QString key, oldconf.allKeys()) {
+ actualConf.setValue(key, oldconf.value(key));
+ }
+ return true;
+}
+
+int ImportFromGpg4usbPage::nextId() const
+{
+ return Wizard::Page_Conclusion;
+}
+
+ImportFromGnupgPage::ImportFromGnupgPage(GpgME::GpgContext *ctx, KeyMgmt *keyMgmt, QWidget *parent)
+ : QWizardPage(parent)
+{
+ mCtx=ctx;
+ mKeyMgmt=keyMgmt;
+ setTitle(tr("Import keys..."));
+ setSubTitle(tr("...from existing GnuPG installation"));
+
+ QLabel *gnupgLabel = new QLabel(tr("You can import keys from a locally installed GnuPG.<br><br> The location is read "
+ "from registry in Windows or assumed to be the .gnupg folder in the your home directory in Linux.<br>"));
+ gnupgLabel->setWordWrap(true);
+
+ importFromGnupgButton = new QPushButton(tr("Import keys from GnuPG"));
+ connect(importFromGnupgButton, SIGNAL(clicked()), this, SLOT(slotrImportKeysFromGnupg()));
+
+ QGridLayout *layout = new QGridLayout();
+ layout->addWidget(gnupgLabel);
+ layout->addWidget(importFromGnupgButton);
+
+ this->setLayout(layout);
+}
+
+void ImportFromGnupgPage::slotrImportKeysFromGnupg()
+{
+ // first get gnupghomedir and check, if it exists
+ QString gnuPGHome = getGnuPGHome();
+ if (gnuPGHome == NULL) {
+ QMessageBox::critical(0, tr("Import Error"), tr("Couldn't locate GnuPG home directory"));
+ return;
+ }
+
+ // Try to import the keyring files and return the return value of the method
+ Wizard::importPubAndSecKeysFromDir(gnuPGHome,mKeyMgmt);
+ wizard()->next();
+}
+
+QString ImportFromGnupgPage::getGnuPGHome()
+{
+ QString gnuPGHome="";
+ #ifdef _WIN32
+ bool existsAndSuccess = false;
+
+ HKEY hKey;
+
+ existsAndSuccess = (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\GNU\\GNUPG", 0, KEY_READ, &hKey) == ERROR_SUCCESS);
+
+ if (existsAndSuccess) {
+ QSettings gnuPGsettings("HKEY_CURRENT_USER\\Software\\GNU\\GNUPG", QSettings::NativeFormat);
+ if (gnuPGsettings.contains("HomeDir")) {
+ gnuPGHome = gnuPGsettings.value("HomeDir").toString();
+ } else {
+ return NULL;
+ }
+ }
+ #else
+ gnuPGHome=QDir::homePath()+"/.gnupg";
+ if (! QFile(gnuPGHome).exists()) {
+ return NULL;
+ }
+ #endif
+
+ return gnuPGHome;
+}
+
+int ImportFromGnupgPage::nextId() const
+{
+ return Wizard::Page_Conclusion;
+}
+
+KeyGenPage::KeyGenPage(GpgME::GpgContext *ctx, QWidget *parent)
+ : QWizardPage(parent)
+{
+ mCtx=ctx;
+ setTitle(tr("Create a keypair..."));
+ setSubTitle(tr("...for decrypting and signing messages"));
+ QLabel *topLabel = new QLabel(tr("You should create a new keypair."
+ "The pair consists of a public and a private key.<br>"
+ "Other users can use the public key to encrypt messages for you "
+ "and verify messages signed by you."
+ "You can use the private key to decrypt and sign messages.<br>"
+ "For more information have a look at the offline tutorial (which then is shown in the main window):"));
+ topLabel->setWordWrap(true);
+ QLabel *linkLabel = new QLabel("<a href=""docu_keygen.html#content"">"+tr("Offline tutorial")+"</a>");
+ //linkLabel->setOpenExternalLinks(true);
+
+ connect(linkLabel, SIGNAL(linkActivated(const QString&)), parentWidget()->parentWidget(), SLOT(openHelp(const QString&)));
+
+ QWidget *createKeyButtonBox = new QWidget(this);
+ QHBoxLayout *createKeyButtonBoxLayout = new QHBoxLayout(createKeyButtonBox);
+ QPushButton *createKeyButton = new QPushButton(tr("Create New Key"));
+ createKeyButtonBoxLayout->addWidget(createKeyButton);
+ createKeyButtonBoxLayout->addStretch(1);
+ QVBoxLayout *layout = new QVBoxLayout();
+ layout->addWidget(topLabel);
+ layout->addWidget(linkLabel);
+ layout->addWidget(createKeyButtonBox);
+ connect(createKeyButton, SIGNAL(clicked()), this, SLOT(slotGenerateKeyDialog()));
+
+ setLayout(layout);
+}
+
+int KeyGenPage::nextId() const
+{
+ return Wizard::Page_Conclusion;
+}
+
+void KeyGenPage::slotGenerateKeyDialog()
+{
+ KeyGenDialog *keyGenDialog = new KeyGenDialog(mCtx, this);
+ keyGenDialog->exec();
+ wizard()->next();
+}
+
+ConclusionPage::ConclusionPage(QWidget *parent)
+ : QWizardPage(parent)
+{
+ setTitle(tr("Ready."));
+ setSubTitle(tr("Have fun with gpg4usb!"));
+
+ QLabel *bottomLabel = new QLabel(tr("You are ready to use gpg4usb now.<br><br>"
+ "The offline help will get you started with gpg4usb. "
+ "It will open in the main window.<br>"));
+ bottomLabel->setWordWrap(true);
+
+ openHelpCheckBox = new QCheckBox(tr("Open offline help."));
+ openHelpCheckBox->setChecked(Qt::Checked);
+
+ dontShowWizardCheckBox = new QCheckBox(tr("Dont show the wizard again."));
+ dontShowWizardCheckBox->setChecked(Qt::Checked);
+
+ registerField("showWizard", dontShowWizardCheckBox);
+ registerField("openHelp", openHelpCheckBox);
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(bottomLabel);
+ layout->addWidget(openHelpCheckBox);
+ layout->addWidget(dontShowWizardCheckBox);
+ setLayout(layout);
+ setVisible(true);
+}
+
+int ConclusionPage::nextId() const
+{
+ return -1;
+}
diff --git a/src/wizard.h b/src/wizard.h
new file mode 100644
index 0000000..4ed34c1
--- /dev/null
+++ b/src/wizard.h
@@ -0,0 +1,167 @@
+/*
+ * wizard.h
+ *
+ * Copyright 2008 gpg4usb-team <[email protected]>
+ *
+ * This file is part of gpg4usb.
+ *
+ * Gpg4usb 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.
+ *
+ * Gpg4usb 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 gpg4usb. If not, see <http://www.gnu.org/licenses/>
+ */
+
+
+#ifndef WIZARD_H
+#define WIZARD_H
+
+#include <QWizard>
+#include "keygendialog.h"
+#include "keymgmt.h"
+#include "gpgconstants.h"
+#include "settingsdialog.h"
+
+class QCheckBox;
+class QLabel;
+class QLineEdit;
+class QRadioButton;
+
+class Wizard : public QWizard
+{
+ Q_OBJECT
+ Q_ENUMS(WizardPages)
+
+public:
+ enum WizardPages { Page_Intro, Page_Choose, Page_ImportFromGpg4usb, Page_ImportFromGnupg, Page_GenKey,
+ Page_Conclusion };
+
+ Wizard(GpgME::GpgContext *ctx, KeyMgmt *keyMgmt, QWidget *parent = 0);
+ static bool importPubAndSecKeysFromDir(const QString dir, KeyMgmt *keyMgmt);
+
+private:
+ GpgME::GpgContext *mCtx;
+ KeyMgmt *mKeyMgmt;
+
+private slots:
+ void slotWizardAccepted();
+
+signals:
+ void signalOpenHelp(QString page);
+};
+
+class IntroPage : public QWizardPage
+{
+ Q_OBJECT
+
+public:
+ IntroPage(QWidget *parent = 0);
+ QHash<QString,QString> languages;
+ int nextId() const;
+
+private slots:
+ void slotLangChange(QString lang);
+};
+
+class ChoosePage : public QWizardPage
+{
+ Q_OBJECT
+
+public:
+ ChoosePage(QWidget *parent = 0);
+
+private slots:
+ void slotJumpPage(const QString& page);
+
+private:
+ int nextId() const;
+ int nextPage;
+};
+
+class ImportFromGpg4usbPage : public QWizardPage
+{
+ Q_OBJECT
+
+public:
+ ImportFromGpg4usbPage(GpgME::GpgContext *ctx, KeyMgmt *keyMgmt, QWidget *parent = 0);
+
+private slots:
+ /**
+ * @details Import keys from gnupg-homedir, private or/and public depend on the checked boxes
+ */
+ void slotImportFromOlderGpg4usb();
+ bool slotImportConfFromGpg4usb(QString dir);
+
+private:
+ int nextId() const;
+
+ KeyMgmt *mKeyMgmt;
+ GpgME::GpgContext *mCtx;
+ QCheckBox *gpg4usbKeyCheckBox;
+ QCheckBox *gpg4usbConfigCheckBox;
+};
+
+class ImportFromGnupgPage : public QWizardPage
+{
+ Q_OBJECT
+
+public:
+ ImportFromGnupgPage(GpgME::GpgContext *ctx, KeyMgmt *keyMgmt, QWidget *parent = 0);
+
+private slots:
+ /**
+ * @details Import keys from gnupg-homedir, private or/and public depend on the checked boxes
+ */
+ void slotrImportKeysFromGnupg();
+
+private:
+ KeyMgmt *mKeyMgmt;
+ int nextId() const;
+
+ /**
+ * @details String containing the gnupg-homedir
+ * @returns String containg the gnupg-homedir, but NULL, if the in windows registry entry
+ * doesn't exist or in linux ~/.gnupg doesn't exist
+ */
+ QString getGnuPGHome();
+
+ GpgME::GpgContext *mCtx;
+ QPushButton *importFromGnupgButton;
+};
+
+class KeyGenPage : public QWizardPage
+{
+ Q_OBJECT
+
+public:
+ KeyGenPage(GpgME::GpgContext *ctx, QWidget *parent = 0);
+ int nextId() const;
+
+private slots:
+ void slotGenerateKeyDialog();
+
+private:
+ GpgME::GpgContext *mCtx;
+};
+
+class ConclusionPage : public QWizardPage
+{
+ Q_OBJECT
+
+public:
+ ConclusionPage(QWidget *parent = 0);
+ int nextId() const;
+
+private:
+ QCheckBox *dontShowWizardCheckBox;
+ QCheckBox *openHelpCheckBox;
+};
+
+#endif