Page MenuHome GnuPG

No OneTemporary

diff --git a/src/utils/keyexportdraghandler.cpp b/src/utils/keyexportdraghandler.cpp
index 690a23e78..9024bf844 100644
--- a/src/utils/keyexportdraghandler.cpp
+++ b/src/utils/keyexportdraghandler.cpp
@@ -1,140 +1,157 @@
// SPDX-FileCopyrightText: 2024 g10 Code GmbH
// SPDX-License-Identifier: GPL-2.0-or-later
#include "keyexportdraghandler.h"
#include "kleopatra_debug.h"
#include <Libkleo/Formatting>
#include <Libkleo/KeyList>
#include <QGpgME/ExportJob>
#include <QGpgME/Protocol>
#include <gpgme++/key.h>
// needed for GPGME_VERSION_NUMBER
#include <gpgme.h>
+#include <QApplication>
#include <QFileInfo>
#include <QRegularExpression>
#include <QTemporaryFile>
#include <QUrl>
+#include <KFileUtils>
+#include <KLocalizedString>
+
using namespace GpgME;
using namespace Kleo;
static QStringList supportedMimeTypes = {
QStringLiteral("text/uri-list"),
QStringLiteral("application/pgp-keys"),
QStringLiteral("text/plain"),
};
class KeyExportMimeData : public QMimeData
{
public:
QVariant retrieveData(const QString &mimeType, QMetaType type) const override
{
Q_UNUSED(type);
QByteArray pgpData;
QByteArray smimeData;
#if GPGME_VERSION_NUMBER >= 0x011800 // 1.24.0
if (!pgpFprs.isEmpty()) {
auto job = QGpgME::openpgp()->publicKeyExportJob(true);
job->exec(pgpFprs, pgpData);
}
if (!smimeFprs.isEmpty()) {
auto job = QGpgME::smime()->publicKeyExportJob(true);
job->exec(smimeFprs, smimeData);
}
#endif
if (mimeType == QStringLiteral("text/uri-list")) {
- auto file = new QTemporaryFile();
-
- file->setFileTemplate(name);
file->open();
- const auto newName = file->fileName().remove(QRegularExpression(QStringLiteral("\\.[^.]+$")));
- if (QFileInfo(newName).exists()) {
- QFile(newName).remove();
- }
file->write(pgpData + smimeData);
- file->rename(newName);
file->close();
- return QUrl(QStringLiteral("file://%1").arg(newName));
+ return QUrl(QStringLiteral("file://%1").arg(file->fileName()));
} else if (mimeType == QStringLiteral("application/pgp-keys")) {
return pgpData;
} else if (mimeType == QStringLiteral("text/plain")) {
QByteArray data = pgpData + smimeData;
return data;
}
return {};
}
bool hasFormat(const QString &mimeType) const override
{
return supportedMimeTypes.contains(mimeType);
}
QStringList formats() const override
{
return supportedMimeTypes;
}
QStringList pgpFprs;
QStringList smimeFprs;
QString name;
+ QTemporaryFile *file;
};
KeyExportDragHandler::KeyExportDragHandler()
{
}
QStringList KeyExportDragHandler::mimeTypes() const
{
return supportedMimeTypes;
}
Qt::ItemFlags KeyExportDragHandler::flags(const QModelIndex &index) const
{
Q_UNUSED(index);
return Qt::ItemIsDragEnabled | Qt::ItemIsSelectable | Qt::ItemIsEnabled;
}
+static QString suggestFileName(const QString &fileName)
+{
+ const QFileInfo fileInfo{fileName};
+ const QString path = fileInfo.absolutePath();
+ const QString newFileName = KFileUtils::suggestName(QUrl::fromLocalFile(path), fileInfo.fileName());
+ return path + QLatin1Char{'/'} + newFileName;
+}
+
QMimeData *KeyExportDragHandler::mimeData(const QModelIndexList &indexes) const
{
auto mimeData = new KeyExportMimeData();
QSet<QString> pgpFprs;
QSet<QString> smimeFprs;
// apparently we're getting an index for each column even though we're selecting whole rows
// so figure out whether we're actually selecting more than one row
bool singleRow = true;
int row = indexes[0].row();
auto parent = indexes[0].parent();
for (const auto &index : indexes) {
auto key = index.data(KeyList::KeyRole).value<Key>();
(key.protocol() == GpgME::OpenPGP ? pgpFprs : smimeFprs) += QString::fromLatin1(key.primaryFingerprint());
if (index.row() != row || index.parent() != parent) {
singleRow = false;
}
}
+ QString name;
if (singleRow) {
auto key = indexes[0].data(KeyList::KeyRole).value<Key>();
- auto name = Formatting::prettyName(key);
- if (name.isEmpty()) {
- name = Formatting::prettyEMail(key);
+ auto keyName = Formatting::prettyName(key);
+ if (keyName.isEmpty()) {
+ keyName = Formatting::prettyEMail(key);
}
- mimeData->name = QStringLiteral("%1_%2_public.%3")
- .arg(name, Formatting::prettyKeyID(key.shortKeyID()), pgpFprs.isEmpty() ? QStringLiteral("pem") : QStringLiteral("asc"));
+ name = QStringLiteral("%1_%2_public.%3")
+ .arg(keyName, Formatting::prettyKeyID(key.shortKeyID()), pgpFprs.isEmpty() ? QStringLiteral("pem") : QStringLiteral("asc"));
} else {
- mimeData->name = QStringLiteral("keys.%1").arg(pgpFprs.isEmpty() ? QStringLiteral("pem") : QStringLiteral("asc"));
+ name = i18nc("A generic filename for exported certificates", "certificates.%1", pgpFprs.isEmpty() ? QStringLiteral("pem") : QStringLiteral("asc"));
}
+ // The file is deliberately not destroyed when the mimedata is destroyed, to give the receiver more time to read it.
+ mimeData->file = new QTemporaryFile(qApp);
+ mimeData->file->setFileTemplate(name);
+ mimeData->file->open();
+ auto path = mimeData->file->fileName().remove(QRegularExpression(QStringLiteral("\\.[^.]+$")));
+
+ if (QFileInfo(path).exists()) {
+ path = suggestFileName(path);
+ }
+ mimeData->file->rename(path);
+
mimeData->pgpFprs = QStringList(pgpFprs.begin(), pgpFprs.end());
mimeData->smimeFprs = QStringList(smimeFprs.begin(), smimeFprs.end());
return mimeData;
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Mar 19, 5:32 AM (13 h, 40 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
cb/65/23e1108094ca1e7ce428bd057d07

Event Timeline