Page MenuHome GnuPG

No OneTemporary

diff --git a/src/utils/keyexportdraghandler.cpp b/src/utils/keyexportdraghandler.cpp
index 29494263d..b08e9b885 100644
--- a/src/utils/keyexportdraghandler.cpp
+++ b/src/utils/keyexportdraghandler.cpp
@@ -1,156 +1,159 @@
// SPDX-FileCopyrightText: 2024 g10 Code GmbH
// SPDX-License-Identifier: GPL-2.0-or-later
#include "keyexportdraghandler.h"
+#include <kleopatraapplication.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 <QTemporaryDir>
#include <QUrl>
#include <KFileUtils>
#include <KLocalizedString>
+#include <KMessageBox>
using namespace GpgME;
using namespace Kleo;
static QStringList supportedMimeTypes = {
QStringLiteral("text/uri-list"),
QStringLiteral("application/pgp-keys"),
QStringLiteral("text/plain"),
};
class KeyExportMimeData : public QMimeData
{
+ // cached data
+ mutable QByteArray pgpData;
+ mutable QByteArray smimeData;
+ mutable QUrl tempFileUrl;
+
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()) {
+ if (pgpData.isEmpty() && !pgpFprs.isEmpty()) {
auto job = QGpgME::openpgp()->publicKeyExportJob(true);
job->exec(pgpFprs, pgpData);
}
- if (!smimeFprs.isEmpty()) {
+ if (smimeData.isEmpty() && !smimeFprs.isEmpty()) {
auto job = QGpgME::smime()->publicKeyExportJob(true);
job->exec(smimeFprs, smimeData);
}
#endif
if (mimeType == QLatin1StringView("text/uri-list")) {
- file->open();
- file->write(pgpData + smimeData);
- file->close();
- return QUrl(QStringLiteral("file://%1").arg(file->fileName()));
+ if (tempFileUrl.isEmpty()) {
+ auto tempDirWeak = KleopatraApplication::instance()->createTemporaryDirectory();
+ if (auto tempDir = tempDirWeak.lock()) {
+ QFile file{tempDir->filePath(fileName)};
+ if (file.open(QFile::NewOnly)) {
+ file.write(pgpData + smimeData);
+ file.close();
+ qCDebug(KLEOPATRA_LOG) << "Wrote file" << file.fileName();
+ tempFileUrl = QUrl(QStringLiteral("file://%1").arg(file.fileName()));
+ } else {
+ KMessageBox::error(nullptr, xi18nc("@info", "Failed to write the certificates to a temporary file."));
+ return {};
+ }
+ } else {
+ KMessageBox::error(nullptr, xi18nc("@info", "Failed to write the certificates to a temporary file."));
+ return {};
+ }
+ }
+ return tempFileUrl;
} else if (mimeType == QLatin1StringView("application/pgp-keys")) {
return pgpData;
} else if (mimeType == QLatin1StringView("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;
- QTemporaryFile *file;
+ QString fileName;
};
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 keyName = Formatting::prettyName(key);
if (keyName.isEmpty()) {
keyName = Formatting::prettyEMail(key);
}
- name = QStringLiteral("%1_%2_public.%3")
- .arg(keyName, Formatting::prettyKeyID(key.keyID()), pgpFprs.isEmpty() ? QStringLiteral("pem") : QStringLiteral("asc"));
+ mimeData->fileName = QStringLiteral("%1_%2_public.%3")
+ .arg(keyName, Formatting::prettyKeyID(key.keyID()), pgpFprs.isEmpty() ? QStringLiteral("pem") : QStringLiteral("asc"));
} else {
- name = i18nc("A generic filename for exported certificates", "certificates.%1", pgpFprs.isEmpty() ? QStringLiteral("pem") : QStringLiteral("asc"));
+ mimeData->fileName =
+ 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::exists(path)) {
- 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
Tue, May 5, 6:13 AM (1 d, 23 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
3d/54/1791d852261cbe9f6b6f8cfe4616

Event Timeline