File indexing completed on 2024-06-23 05:13:41
0001 /* -*- mode: c++; c-basic-offset:4 -*- 0002 importcertificatefromfilecommand.cpp 0003 0004 This file is part of Kleopatra, the KDE keymanager 0005 SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 #include <config-kleopatra.h> 0011 0012 #include "importcertificatefromfilecommand.h" 0013 #include "importcertificatescommand_p.h" 0014 0015 #include <kleopatra_debug.h> 0016 0017 #include <QGpgME/Protocol> 0018 0019 #include <Libkleo/Classify> 0020 0021 #include <gpgme++/global.h> 0022 #include <gpgme++/importresult.h> 0023 0024 #include <KConfigGroup> 0025 #include <KLocalizedString> 0026 0027 #include <QDir> 0028 #include <QFile> 0029 #include <QFileDialog> 0030 #include <QFileInfo> 0031 #include <QString> 0032 #include <QStringDecoder> 0033 #include <QWidget> 0034 0035 #include <KSharedConfig> 0036 0037 #include <memory> 0038 0039 using namespace GpgME; 0040 using namespace Kleo; 0041 using namespace QGpgME; 0042 0043 class ImportCertificateFromFileCommand::Private : public ImportCertificatesCommand::Private 0044 { 0045 friend class ::ImportCertificateFromFileCommand; 0046 ImportCertificateFromFileCommand *q_func() const 0047 { 0048 return static_cast<ImportCertificateFromFileCommand *>(q); 0049 } 0050 0051 public: 0052 explicit Private(ImportCertificateFromFileCommand *qq, KeyListController *c); 0053 ~Private() override; 0054 0055 bool ensureHaveFile(); 0056 0057 private: 0058 QStringList files; 0059 }; 0060 0061 ImportCertificateFromFileCommand::Private *ImportCertificateFromFileCommand::d_func() 0062 { 0063 return static_cast<Private *>(d.get()); 0064 } 0065 const ImportCertificateFromFileCommand::Private *ImportCertificateFromFileCommand::d_func() const 0066 { 0067 return static_cast<const Private *>(d.get()); 0068 } 0069 0070 ImportCertificateFromFileCommand::Private::Private(ImportCertificateFromFileCommand *qq, KeyListController *c) 0071 : ImportCertificatesCommand::Private(qq, c) 0072 , files() 0073 { 0074 } 0075 0076 ImportCertificateFromFileCommand::Private::~Private() 0077 { 0078 } 0079 0080 #define d d_func() 0081 #define q q_func() 0082 0083 ImportCertificateFromFileCommand::ImportCertificateFromFileCommand() 0084 : ImportCertificatesCommand(new Private(this, nullptr)) 0085 { 0086 } 0087 0088 ImportCertificateFromFileCommand::ImportCertificateFromFileCommand(KeyListController *p) 0089 : ImportCertificatesCommand(new Private(this, p)) 0090 { 0091 } 0092 0093 ImportCertificateFromFileCommand::ImportCertificateFromFileCommand(QAbstractItemView *v, KeyListController *p) 0094 : ImportCertificatesCommand(v, new Private(this, p)) 0095 { 0096 } 0097 0098 ImportCertificateFromFileCommand::ImportCertificateFromFileCommand(const QStringList &files, KeyListController *p) 0099 : ImportCertificatesCommand(new Private(this, p)) 0100 { 0101 d->files = files; 0102 } 0103 0104 ImportCertificateFromFileCommand::ImportCertificateFromFileCommand(const QStringList &files, QAbstractItemView *v, KeyListController *p) 0105 : ImportCertificatesCommand(v, new Private(this, p)) 0106 { 0107 d->files = files; 0108 } 0109 0110 ImportCertificateFromFileCommand::~ImportCertificateFromFileCommand() 0111 { 0112 } 0113 0114 void ImportCertificateFromFileCommand::setFiles(const QStringList &files) 0115 { 0116 d->files = files; 0117 } 0118 0119 void ImportCertificateFromFileCommand::doStart() 0120 { 0121 if (!d->ensureHaveFile()) { 0122 Q_EMIT canceled(); 0123 d->finished(); 0124 return; 0125 } 0126 0127 d->setProgressWindowTitle(i18nc("@title:window", "Importing Certificates")); 0128 d->setProgressLabelText(i18np("Importing certificates from 1 file...", "Importing certificates from %1 files...", d->files.size())); 0129 0130 // TODO: use KIO here 0131 d->setWaitForMoreJobs(true); 0132 for (const QString &fn : std::as_const(d->files)) { 0133 QFile in(fn); 0134 if (!in.open(QIODevice::ReadOnly)) { 0135 d->error(i18n("Could not open file %1 for reading: %2", in.fileName(), in.errorString()), i18n("Certificate Import Failed")); 0136 d->addImportResult({fn, GpgME::UnknownProtocol, ImportType::Local, ImportResult{}, AuditLogEntry{}}); 0137 continue; 0138 } 0139 auto data = in.readAll(); 0140 // check for UTF-16- (or UTF-32- or UTF-8-with-BOM-)encoded text file; 0141 // binary certificate files don't start with a BOM, so that it's safe 0142 // to assume that data starting with a BOM is UTF-encoded text 0143 if (const auto encoding = QStringDecoder::encodingForData(data)) { 0144 QStringDecoder codec(*encoding); 0145 qCDebug(KLEOPATRA_LOG) << this << __func__ << "Decoding" << codec.name() << "encoded data"; 0146 data = QString(codec.decode(data)).toUtf8(); 0147 } 0148 d->startImport(GpgME::OpenPGP, data, fn); 0149 d->startImport(GpgME::CMS, data, fn); 0150 d->importGroupsFromFile(fn); 0151 } 0152 d->setWaitForMoreJobs(false); 0153 } 0154 0155 static QStringList get_file_name(QWidget *parent) 0156 { 0157 const QString certificateFilter = i18n("Certificates") + QLatin1StringView(" (*.asc *.cer *.cert *.crt *.der *.pem *.gpg *.p7c *.p12 *.pfx *.pgp *.kgrp)"); 0158 const QString anyFilesFilter = i18n("Any files") + QLatin1StringView(" (*)"); 0159 QString previousDir; 0160 if (const KSharedConfig::Ptr config = KSharedConfig::openConfig()) { 0161 const KConfigGroup group(config, QStringLiteral("Import Certificate")); 0162 previousDir = group.readPathEntry("last-open-file-directory", QDir::homePath()); 0163 } 0164 const QStringList files = 0165 QFileDialog::getOpenFileNames(parent, i18n("Select Certificate File"), previousDir, certificateFilter + QLatin1StringView(";;") + anyFilesFilter); 0166 if (!files.empty()) 0167 if (const KSharedConfig::Ptr config = KSharedConfig::openConfig()) { 0168 KConfigGroup group(config, QStringLiteral("Import Certificate")); 0169 group.writePathEntry("last-open-file-directory", QFileInfo(files.front()).path()); 0170 } 0171 return files; 0172 } 0173 0174 bool ImportCertificateFromFileCommand::Private::ensureHaveFile() 0175 { 0176 if (files.empty()) { 0177 files = get_file_name(parentWidgetOrView()); 0178 } 0179 return !files.empty(); 0180 } 0181 0182 #undef d 0183 #undef q 0184 0185 #include "moc_importcertificatefromfilecommand.cpp"