kde-extraapps/ark/plugins/libarchive/libarchivehandler.cpp

253 lines
8.7 KiB
C++
Raw Normal View History

2014-11-18 17:46:34 +00:00
/*
* Copyright (C) 2022 Ivailo Monev <xakepa10@gmail.com>
2014-11-18 17:46:34 +00:00
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ( INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libarchivehandler.h"
#include "kerfuffle/kerfuffle_export.h"
#include "kerfuffle/queries.h"
#include <QFileInfo>
#include <QDir>
2014-11-18 17:46:34 +00:00
#include <KDebug>
#include <KLocale>
#include <KArchive>
2014-11-18 17:46:34 +00:00
#include <sys/stat.h>
2014-11-18 17:46:34 +00:00
static void copyEntry(ArchiveEntry *archiveentry, const KArchiveEntry *karchiveentry)
{
archiveentry->insert(FileName, karchiveentry->pathname);
archiveentry->insert(InternalID, karchiveentry->pathname);
archiveentry->insert(Size, qlonglong(karchiveentry->size));
archiveentry->insert(IsDirectory, S_ISDIR(karchiveentry->mode));
archiveentry->insert(Permissions, ReadWriteArchiveInterface::permissionsString(karchiveentry->mode));
archiveentry->insert(Owner, karchiveentry->username);
archiveentry->insert(Group, karchiveentry->groupname);
archiveentry->insert(Timestamp, QDateTime::fromTime_t(karchiveentry->mtime));
archiveentry->insert(IsPasswordProtected, karchiveentry->encrypted);
if (!karchiveentry->symlink.isEmpty()) {
archiveentry->insert(Link, karchiveentry->symlink);
}
}
LibArchiveInterface::LibArchiveInterface(QObject *parent, const QVariantList &args)
2014-11-18 17:46:34 +00:00
: ReadWriteArchiveInterface(parent, args)
{
}
LibArchiveInterface::~LibArchiveInterface()
{
}
bool LibArchiveInterface::list()
{
KArchive karchive(filename());
if (!karchive.isReadable()) {
emit error(i18nc("@info", "Could not open the archive <filename>%1</filename>: %2.", filename(), karchive.errorString()));
2014-11-18 17:46:34 +00:00
return false;
}
emit progress(0.1);
foreach (const KArchiveEntry &karchiveentry, karchive.list()) {
ArchiveEntry archiveentry;
copyEntry(&archiveentry, &karchiveentry);
emit entry(archiveentry);
2014-11-18 17:46:34 +00:00
}
emit progress(1.0);
2014-11-18 17:46:34 +00:00
return true;
}
bool LibArchiveInterface::copyFiles(const QVariantList& files, const QString &destinationDirectory, ExtractionOptions options)
2014-11-18 17:46:34 +00:00
{
const bool extractAll = files.isEmpty();
const bool preservePaths = options.value(QLatin1String("PreservePaths")).toBool();
2014-11-18 17:46:34 +00:00
KArchive karchive(filename());
if (!karchive.isReadable()) {
emit error(i18nc("@info", "Could not open the archive <filename>%1</filename>: %2.", filename(), karchive.errorString()));
2014-11-18 17:46:34 +00:00
return false;
}
if (karchive.requiresPassphrase()) {
PasswordNeededQuery passwordquery(filename());
emit userQuery(&passwordquery);
passwordquery.waitForResponse();
if (passwordquery.responseCancelled()) {
return false;
}
karchive.setReadPassphrase(passwordquery.password());
}
QStringList fileslist;
2014-11-18 17:46:34 +00:00
if (extractAll) {
foreach (const KArchiveEntry &karchiveentry, karchive.list()) {
fileslist.append(QFile::decodeName(karchiveentry.pathname));
2014-11-18 17:46:34 +00:00
}
} else {
foreach (const QVariant &variant, files) {
fileslist.append(variant.toString());
2014-11-18 17:46:34 +00:00
}
}
bool autoskip = false;
QStringList::iterator it = fileslist.begin();
while (it != fileslist.end()) {
const QString fullpath = destinationDirectory + QLatin1Char('/') + (*it);
if (QFile::exists(fullpath)) {
if (autoskip) {
it = fileslist.erase(it);
it++;
continue;
}
Kerfuffle::OverwriteQuery overwritequery(fullpath);
overwritequery.setNoRenameMode(true);
emit userQuery(&overwritequery);
overwritequery.waitForResponse();
if (overwritequery.responseCancelled()) {
return false;
} else if (overwritequery.responseOverwriteAll()) {
// KArchive will overwrite
break;
} else if (overwritequery.responseOverwrite()) {
it++;
continue;
} else if (overwritequery.responseRename()) {
Q_ASSERT(false);
} else if (overwritequery.responseSkip()) {
it = fileslist.erase(it);
continue;
} else if (overwritequery.responseAutoSkip()) {
autoskip = true;
it = fileslist.erase(it);
}
}
it++;
}
connect(&karchive, SIGNAL(progress(qreal)), this, SLOT(emitProgress(qreal)));
if (!karchive.extract(fileslist, destinationDirectory, preservePaths)) {
emit error(karchive.errorString());
return false;
}
2014-11-18 17:46:34 +00:00
return true;
2014-11-18 17:46:34 +00:00
}
bool LibArchiveInterface::addFiles(const QStringList &files, const CompressionOptions &options)
2014-11-18 17:46:34 +00:00
{
const QString globalWorkDir = options.value(QLatin1String("GlobalWorkDir")).toString();
2014-11-18 17:46:34 +00:00
if (!globalWorkDir.isEmpty()) {
kDebug() << "GlobalWorkDir is set, changing dir to" << globalWorkDir;
2014-11-18 17:46:34 +00:00
QDir::setCurrent(globalWorkDir);
}
QString rootNode = options.value(QLatin1String("RootNode"), QVariant()).toString();
if (!rootNode.isEmpty() && !rootNode.endsWith(QLatin1Char('/'))) {
rootNode.append(QLatin1Char('/'));
2014-11-18 17:46:34 +00:00
}
KArchive karchive(filename());
if (!karchive.isWritable()) {
emit error(i18nc("@info", "Could not open the archive <filename>%1</filename>: %2.", filename(), karchive.errorString()));
2014-11-18 17:46:34 +00:00
return false;
}
if (karchive.requiresPassphrase()) {
emit error(i18nc("@info", "Writing password-protected archives is not supported."));
return false;
}
if (!globalWorkDir.isEmpty()) {
const QString tempprefix(QDir::cleanPath(globalWorkDir) + QDir::separator() + QLatin1String("ark-"));
kDebug() << "GlobalWorkDir is set, setting temporary prefix to" << tempprefix;
karchive.setTempPrefix(tempprefix);
}
const QList<KArchiveEntry> oldEntries = karchive.list();
const QString strip(QDir::cleanPath(globalWorkDir) + QDir::separator());
connect(&karchive, SIGNAL(progress(qreal)), this, SLOT(emitProgress(qreal)));
if (!karchive.add(files, QFile::encodeName(strip), QFile::encodeName(rootNode))) {
emit error(karchive.errorString());
return false;
2014-11-18 17:46:34 +00:00
}
foreach (const KArchiveEntry &karchiveentry, karchive.list()) {
if (!oldEntries.contains(karchiveentry)) {
ArchiveEntry archiveentry;
copyEntry(&archiveentry, &karchiveentry);
emit entry(archiveentry);
}
}
return true;
2014-11-18 17:46:34 +00:00
}
bool LibArchiveInterface::deleteFiles(const QVariantList &files)
2014-11-18 17:46:34 +00:00
{
KArchive karchive(filename());
if (!karchive.isWritable()) {
emit error(i18nc("@info", "Could not open the archive <filename>%1</filename>: %2.", filename(), karchive.errorString()));
2014-11-18 17:46:34 +00:00
return false;
}
if (karchive.requiresPassphrase()) {
emit error(i18nc("@info", "Writing password-protected archives is not supported."));
return false;
}
QStringList fileslist;
foreach (const QVariant &variant, files) {
fileslist.append(variant.toString());
2014-11-18 17:46:34 +00:00
}
connect(&karchive, SIGNAL(progress(qreal)), this, SLOT(emitProgress(qreal)));
if (!karchive.remove(fileslist)) {
emit error(karchive.errorString());
return false;
}
foreach (const QString &file, fileslist) {
emit entryRemoved(file);
2014-11-18 17:46:34 +00:00
}
return true;
2014-11-18 17:46:34 +00:00
}
bool LibArchiveInterface::isReadOnly() const
{
KArchive karchive(filename());
return !karchive.isWritable();
}
void LibArchiveInterface::emitProgress(const qreal value)
{
emit progress(value);
}
2014-11-18 17:46:34 +00:00
KERFUFFLE_EXPORT_PLUGIN(LibArchiveInterface)
2015-02-27 11:02:43 +00:00
#include "moc_libarchivehandler.cpp"