Commit 2dd4b816 authored by Elvis Angelaccio's avatar Elvis Angelaccio
Browse files

Improve password-protection status in the properties dialog

An archive could be just password-protected but also header-encrypted.
This is now displayed to the user in the properties dialog.

Differential Revision: D1124
parent 18a4de44
......@@ -53,7 +53,7 @@ void ArchiveTest::testProperties_data()
QTest::addColumn<bool>("isReadOnly");
QTest::addColumn<bool>("canFallbackOnReadOnly");
QTest::addColumn<bool>("isSingleFolder");
QTest::addColumn<bool>("isPasswordProtected");
QTest::addColumn<Archive::EncryptionType>("expectedEncryptionType");
QTest::addColumn<QString>("expectedSubfolderName");
// Test non-existent tar archive.
......@@ -61,7 +61,7 @@ void ArchiveTest::testProperties_data()
QTest::newRow("non-existent tar archive")
<< archivePath
<< QStringLiteral("foo")
<< false << false << true << false
<< false << false << true << Archive::Unencrypted
<< QStringLiteral("foo");
// Test dummy source code tarball.
......@@ -69,42 +69,42 @@ void ArchiveTest::testProperties_data()
QTest::newRow("dummy source code tarball")
<< archivePath
<< QStringLiteral("code-x.y.z")
<< false << false << true << false
<< false << false << true << Archive::Unencrypted
<< QStringLiteral("awesome_project");
archivePath = QFINDTESTDATA("data/simplearchive.tar.gz");
QTest::newRow("simple compressed tar archive")
<< archivePath
<< QStringLiteral("simplearchive")
<< false << false << false << false
<< false << false << false << Archive::Unencrypted
<< QStringLiteral("simplearchive");
archivePath = QFINDTESTDATA("data/archivetest_encrypted.zip");
QTest::newRow("encrypted zip, single entry")
<< archivePath
<< QStringLiteral("archivetest_encrypted")
<< false << true << false << true
<< false << true << false << Archive::Encrypted
<< QStringLiteral("archivetest_encrypted");
archivePath = QFINDTESTDATA("data/archivetest_unencrypted.zip");
QTest::newRow("simple zip, one unencrypted entry")
<< archivePath
<< QStringLiteral("archivetest_unencrypted")
<< false << true << false << false
<< false << true << false << Archive::Unencrypted
<< QStringLiteral("archivetest_unencrypted");
archivePath = QFINDTESTDATA("data/wget.rpm");
QTest::newRow("rpm archive, no single folder")
<< archivePath
<< QStringLiteral("wget")
<< true << false << false << false
<< true << false << false << Archive::Unencrypted
<< QStringLiteral("wget");
archivePath = QFINDTESTDATA("data/simplearchive.tar.lz");
QTest::newRow("lzipped tarball")
<< archivePath
<< QStringLiteral("simplearchive")
<< false << false << false << false
<< false << false << false << Archive::Unencrypted
<< QStringLiteral("simplearchive");
}
......@@ -133,8 +133,8 @@ void ArchiveTest::testProperties()
QFETCH(bool, isSingleFolder);
QCOMPARE(archive->isSingleFolderArchive(), isSingleFolder);
QFETCH(bool, isPasswordProtected);
QCOMPARE(archive->isPasswordProtected(), isPasswordProtected);
QFETCH(Archive::EncryptionType, expectedEncryptionType);
QCOMPARE(archive->encryptionType(), expectedEncryptionType);
QFETCH(QString, expectedSubfolderName);
QCOMPARE(archive->subfolderName(), expectedSubfolderName);
......@@ -366,10 +366,10 @@ void ArchiveTest::testCreateEncryptedArchive()
QSKIP("Could not find a plugin to handle the archive. Skipping test.", SkipSingle);
}
QVERIFY(!archive->isPasswordProtected());
QCOMPARE(archive->encryptionType(), Archive::Unencrypted);
archive->setPassword(QStringLiteral("1234"));
QVERIFY(archive->isPasswordProtected());
archive->encrypt(QStringLiteral("1234"), false);
QCOMPARE(archive->encryptionType(), Archive::Encrypted);
archive->deleteLater();
}
......
......@@ -41,7 +41,7 @@ void CliUnarchiverTest::testArchive_data()
QTest::addColumn<QString>("expectedFileName");
QTest::addColumn<bool>("isReadOnly");
QTest::addColumn<bool>("isSingleFolder");
QTest::addColumn<bool>("isPasswordProtected");
QTest::addColumn<Archive::EncryptionType>("expectedEncryptionType");
QTest::addColumn<QString>("expectedSubfolderName");
......@@ -49,21 +49,21 @@ void CliUnarchiverTest::testArchive_data()
QTest::newRow("archive with one top-level folder")
<< archivePath
<< QFileInfo(archivePath).fileName()
<< true << true << false
<< true << true << Archive::Unencrypted
<< QStringLiteral("A");
archivePath = QFINDTESTDATA("data/multiple_toplevel_entries.rar");
QTest::newRow("archive with multiple top-level entries")
<< archivePath
<< QFileInfo(archivePath).fileName()
<< true << false << false
<< true << false << Archive::Unencrypted
<< QStringLiteral("multiple_toplevel_entries");
archivePath = QFINDTESTDATA("data/encrypted_entries.rar");
QTest::newRow("archive with encrypted entries")
<< archivePath
<< QFileInfo(archivePath).fileName()
<< true << true << true
<< true << true << Archive::Encrypted
<< QStringLiteral("A");
}
......@@ -86,8 +86,8 @@ void CliUnarchiverTest::testArchive()
QFETCH(bool, isSingleFolder);
QCOMPARE(archive->isSingleFolderArchive(), isSingleFolder);
QFETCH(bool, isPasswordProtected);
QCOMPARE(archive->isPasswordProtected(), isPasswordProtected);
QFETCH(Archive::EncryptionType, expectedEncryptionType);
QCOMPARE(archive->encryptionType(), expectedEncryptionType);
QFETCH(QString, expectedSubfolderName);
QCOMPARE(archive->subfolderName(), expectedSubfolderName);
......
......@@ -195,8 +195,7 @@ void AddToArchive::slotStartJob()
}
if (!m_password.isEmpty()) {
archive->setPassword(m_password);
archive->enableHeaderEncryption(m_enableHeaderEncryption);
archive->encrypt(m_password, m_enableHeaderEncryption);
}
if (m_changeToFirstPath) {
......
......@@ -206,9 +206,9 @@ Archive::Archive(ReadOnlyArchiveInterface *archiveInterface, bool isReadOnly, QO
, m_iface(archiveInterface)
, m_hasBeenListed(false)
, m_isReadOnly(isReadOnly)
, m_isPasswordProtected(false)
, m_isSingleFolderArchive(false)
, m_error(NoError)
, m_encryptionType(Unencrypted)
, m_numberOfFiles(0)
{
qCDebug(ARK) << "Created archive instance";
......@@ -259,12 +259,6 @@ bool Archive::isReadOnly() const
return (m_iface->isReadOnly() || m_isReadOnly);
}
bool Archive::isPasswordProtected()
{
listIfNotListed();
return m_isPasswordProtected;
}
bool Archive::isSingleFolderArchive()
{
listIfNotListed();
......@@ -276,6 +270,12 @@ bool Archive::hasComment() const
return !m_iface->comment().isEmpty();
}
Archive::EncryptionType Archive::encryptionType()
{
listIfNotListed();
return m_encryptionType;
}
qulonglong Archive::numberOfFiles() const
{
return m_numberOfFiles;
......@@ -363,7 +363,7 @@ AddJob* Archive::addFiles(const QStringList & files, const CompressionOptions& o
ExtractJob* Archive::copyFiles(const QList<QVariant>& files, const QString& destinationDir, const ExtractionOptions& options)
{
ExtractionOptions newOptions = options;
if (isPasswordProtected()) {
if (encryptionType() != Unencrypted) {
newOptions[QStringLiteral( "PasswordProtectedHint" )] = true;
}
......@@ -371,6 +371,13 @@ ExtractJob* Archive::copyFiles(const QList<QVariant>& files, const QString& dest
return newJob;
}
void Archive::encrypt(const QString &password, bool encryptHeader)
{
m_iface->setPassword(password);
m_iface->setHeaderEncryptionEnabled(encryptHeader);
m_encryptionType = encryptHeader ? HeaderEncrypted : Encrypted;
}
void Archive::onAddFinished(KJob* job)
{
//if the archive was previously a single folder archive and an add job
......@@ -389,12 +396,16 @@ void Archive::onListFinished(KJob* job)
ListJob *ljob = qobject_cast<ListJob*>(job);
m_extractedFilesSize = ljob->extractedFilesSize();
m_isSingleFolderArchive = ljob->isSingleFolderArchive();
m_isPasswordProtected = ljob->isPasswordProtected();
m_subfolderName = ljob->subfolderName();
if (m_subfolderName.isEmpty()) {
m_subfolderName = completeBaseName();
}
if (ljob->isPasswordProtected()) {
// If we already know the password, it means that the archive is header-encrypted.
m_encryptionType = m_iface->password().isEmpty() ? Encrypted : HeaderEncrypted;
}
m_hasBeenListed = true;
}
......@@ -418,17 +429,6 @@ void Archive::onUserQuery(Query* query)
query->execute();
}
void Archive::setPassword(const QString &password)
{
m_iface->setPassword(password);
m_isPasswordProtected = true;
}
void Archive::enableHeaderEncryption(bool enable)
{
m_iface->setHeaderEncryptionEnabled(enable);
}
QSet<QString> supportedMimeTypes()
{
const QVector<KPluginMetaData> offers = KPluginLoader::findPlugins(QStringLiteral("kerfuffle"), [](const KPluginMetaData& metaData) {
......
......@@ -135,6 +135,7 @@ QDebug operator<<(QDebug d, const fileRootNodePair &pair);
class KERFUFFLE_EXPORT Archive : public QObject
{
Q_OBJECT
Q_ENUMS(EncryptionType)
/**
* Complete base name, without the "tar" extension (if any).
......@@ -144,22 +145,30 @@ class KERFUFFLE_EXPORT Archive : public QObject
Q_PROPERTY(QString comment READ comment CONSTANT)
Q_PROPERTY(QMimeType mimeType READ mimeType CONSTANT)
Q_PROPERTY(bool isReadOnly READ isReadOnly CONSTANT)
Q_PROPERTY(bool isPasswordProtected READ isPasswordProtected)
Q_PROPERTY(bool isSingleFolderArchive READ isSingleFolderArchive)
Q_PROPERTY(EncryptionType encryptionType READ encryptionType)
Q_PROPERTY(qulonglong numberOfFiles READ numberOfFiles)
Q_PROPERTY(qulonglong unpackedSize READ unpackedSize)
Q_PROPERTY(qulonglong packedSize READ packedSize)
Q_PROPERTY(QString subfolderName READ subfolderName)
public:
enum EncryptionType
{
Unencrypted,
Encrypted,
HeaderEncrypted
};
QString completeBaseName() const;
QString fileName() const;
QString comment() const;
QMimeType mimeType() const;
bool isReadOnly() const;
bool isPasswordProtected();
bool isSingleFolderArchive();
bool hasComment() const;
EncryptionType encryptionType();
qulonglong numberOfFiles() const;
qulonglong unpackedSize() const;
qulonglong packedSize() const;
......@@ -197,8 +206,11 @@ public:
ExtractJob* copyFiles(const QList<QVariant> &files, const QString &destinationDir, const ExtractionOptions &options = ExtractionOptions());
void setPassword(const QString &password);
void enableHeaderEncryption(bool enable);
/**
* @param password The password to encrypt the archive with.
* @param encryptHeader Whether to encrypt also the list of files.
*/
void encrypt(const QString &password, bool encryptHeader);
private slots:
void onListFinished(KJob*);
......@@ -214,12 +226,12 @@ private:
ReadOnlyArchiveInterface *m_iface;
bool m_hasBeenListed;
bool m_isReadOnly;
bool m_isPasswordProtected;
bool m_isSingleFolderArchive;
QString m_subfolderName;
qulonglong m_extractedFilesSize;
ArchiveError m_error;
EncryptionType m_encryptionType;
qulonglong m_numberOfFiles;
};
......@@ -229,6 +241,7 @@ KERFUFFLE_EXPORT QSet<QString> supportedEncryptEntriesMimeTypes();
KERFUFFLE_EXPORT QSet<QString> supportedEncryptHeaderMimeTypes();
} // namespace Kerfuffle
Q_DECLARE_METATYPE(Kerfuffle::Archive::EncryptionType)
Q_DECLARE_METATYPE(Kerfuffle::fileRootNodePair)
#endif // ARCHIVE_H
......@@ -57,6 +57,11 @@ public:
*/
QString comment() const;
/**
* @return The password of the archive, if any.
*/
QString password() const;
/**
* Returns whether the file can only be read.
*
......@@ -114,7 +119,7 @@ signals:
void userQuery(Query *query);
protected:
QString password() const;
/**
* Setting this option to true will not exit the thread with the
* exit of the various functions, but rather when finished(bool) is
......
......@@ -61,7 +61,6 @@ PropertiesDialog::PropertiesDialog(QWidget *parent, Archive *archive)
m_ui->lblArchiveType->setText(archive->mimeType().comment());
m_ui->lblMimetype->setText(archive->mimeType().name());
m_ui->lblReadOnly->setText(archive->isReadOnly() ? i18n("yes") : i18n("no"));
m_ui->lblPasswordProtected->setText(archive->isPasswordProtected() ? i18n("yes") : i18n("no"));
m_ui->lblHasComment->setText(archive->hasComment() ? i18n("yes") : i18n("no"));
m_ui->lblNumberOfFiles->setText(QString::number(archive->numberOfFiles()));
m_ui->lblUnpackedSize->setText(KIO::convertSize(archive->unpackedSize()));
......@@ -69,6 +68,18 @@ PropertiesDialog::PropertiesDialog(QWidget *parent, Archive *archive)
m_ui->lblCompressionRatio->setText(QString::number(float(archive->unpackedSize()) / float(archive->packedSize()), 'f', 1));
m_ui->lblLastModified->setText(fi.lastModified().toString(QStringLiteral("yyyy-MM-dd HH:mm")));
switch (archive->encryptionType()) {
case Archive::Unencrypted:
m_ui->lblPasswordProtected->setText(i18n("no"));
break;
case Archive::Encrypted:
m_ui->lblPasswordProtected->setText(i18n("yes (excluding the list of files)"));
break;
case Archive::HeaderEncrypted:
m_ui->lblPasswordProtected->setText(i18n("yes (including the list of files)"));
break;
}
// Show an icon representing the mimetype of the archive.
QIcon icon = QIcon::fromTheme(archive->mimeType().iconName());
m_ui->lblIcon->setPixmap(icon.pixmap(IconSize(KIconLoader::Desktop), IconSize(KIconLoader::Desktop)));
......
......@@ -952,16 +952,13 @@ DeleteJob* ArchiveModel::deleteFiles(const QList<QVariant> & files)
return Q_NULLPTR;
}
void ArchiveModel::setPassword(const QString &password)
void ArchiveModel::encryptArchive(const QString &password, bool encryptHeader)
{
Q_ASSERT(m_archive);
m_archive->setPassword(password);
}
if (!m_archive) {
return;
}
void ArchiveModel::enableHeaderEncryption()
{
Q_ASSERT(m_archive);
m_archive->enableHeaderEncryption(true);
m_archive->encrypt(password, encryptHeader);
}
void ArchiveModel::slotCleanupEmptyDirs()
......
......@@ -75,8 +75,11 @@ public:
Kerfuffle::AddJob* addFiles(const QStringList & paths, const Kerfuffle::CompressionOptions& options = Kerfuffle::CompressionOptions());
Kerfuffle::DeleteJob* deleteFiles(const QList<QVariant> & files);
void setPassword(const QString &password);
void enableHeaderEncryption();
/**
* @param password The password to encrypt the archive with.
* @param encryptHeader Whether to encrypt also the list of files.
*/
void encryptArchive(const QString &password, bool encryptHeader);
signals:
void loadingStarted();
......
......@@ -588,11 +588,8 @@ bool Part::openFile()
const QString password = arguments().metaData()[QStringLiteral("encryptionPassword")];
if (!password.isEmpty()) {
m_model->setPassword(password);
if (arguments().metaData()[QStringLiteral("encryptHeader")] == QLatin1String("true")) {
m_model->enableHeaderEncryption();
}
m_model->encryptArchive(password,
arguments().metaData()[QStringLiteral("encryptHeader")] == QLatin1String("true"));
}
return true;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment