1 /*
2     SPDX-FileCopyrightText: 2011, 2012, 2013 Rolf Eike Beer <kde@opensource.sf-tec.de>
3     SPDX-License-Identifier: GPL-2.0-or-later
4 */
5 
6 #include "foldercompressjob.h"
7 
8 #include <KArchive>
9 #include <KLocalizedString>
10 #include <KTar>
11 #include <KZip>
12 
13 #include <QDir>
14 #include <QMetaObject>
15 #include <QStringList>
16 #include <QTemporaryFile>
17 
18 class FolderCompressJobPrivate {
19 	FolderCompressJob * const q_ptr;
20 	Q_DECLARE_PUBLIC(FolderCompressJob)
21 
22 public:
23 	FolderCompressJobPrivate(FolderCompressJob *parent, const QList<QUrl> &sources, const QUrl &dest, QTemporaryFile *tempfile, const QStringList &keys, const QStringList &options, const KGpgEncrypt::EncryptOptions encOptions, const int archive);
24 
25 	const QString m_description;
26 	const QList<QUrl> m_sources;
27 	const QUrl m_dest;
28 	QTemporaryFile * const m_tempfile;
29 	const QStringList m_keys;
30 	QStringList m_options;
31 	const KGpgEncrypt::EncryptOptions m_encOptions;
32 	const int m_archiveType;
33 };
34 
FolderCompressJobPrivate(FolderCompressJob * parent,const QList<QUrl> & sources,const QUrl & dest,QTemporaryFile * tempfile,const QStringList & keys,const QStringList & options,const KGpgEncrypt::EncryptOptions encOptions,const int archive)35 FolderCompressJobPrivate::FolderCompressJobPrivate(FolderCompressJob *parent, const QList<QUrl> &sources, const QUrl &dest, QTemporaryFile *tempfile, const QStringList &keys, const QStringList &options, const KGpgEncrypt::EncryptOptions encOptions, const int archive)
36 	: q_ptr(parent),
37 	m_description(i18n("Processing folder compression and encryption")),
38 	m_sources(sources),
39 	m_dest(dest),
40 	m_tempfile(tempfile),
41 	m_keys(keys),
42 	m_options(options),
43 	m_encOptions(encOptions),
44 	m_archiveType(archive)
45 {
46 }
47 
FolderCompressJob(QObject * parent,const QList<QUrl> & sources,const QUrl & dest,QTemporaryFile * tempfile,const QStringList & keys,const QStringList & options,const KGpgEncrypt::EncryptOptions encOptions,const int archive)48 FolderCompressJob::FolderCompressJob(QObject *parent, const QList<QUrl> &sources, const QUrl &dest, QTemporaryFile *tempfile, const QStringList &keys, const QStringList &options,  const KGpgEncrypt::EncryptOptions encOptions, const int archive)
49 	: KJob(parent),
50 	d_ptr(new FolderCompressJobPrivate(this, sources, dest, tempfile, keys, options, encOptions, archive))
51 {
52 }
53 
~FolderCompressJob()54 FolderCompressJob::~FolderCompressJob()
55 {
56 	delete d_ptr;
57 }
58 
59 void
start()60 FolderCompressJob::start()
61 {
62 	Q_D(FolderCompressJob);
63 
64 	Q_EMIT description(this, d->m_description, qMakePair(i18nc("State of operation as in status", "State"), i18nc("Job is started up", "Startup")));
65 	QMetaObject::invokeMethod(this, "doWork", Qt::QueuedConnection);
66 }
67 
68 void
doWork()69 FolderCompressJob::doWork()
70 {
71 	Q_D(FolderCompressJob);
72 	KArchive *arch = nullptr;
73 
74 	switch (d->m_archiveType) {
75 	case 0:
76 		arch = new KZip(d->m_tempfile->fileName());
77 		break;
78 	case 1:
79 		arch = new KTar(d->m_tempfile->fileName(), QLatin1String( "application/x-gzip" ));
80 		break;
81 	case 2:
82 		arch = new KTar(d->m_tempfile->fileName(), QLatin1String( "application/x-bzip" ));
83 		break;
84 	case 3:
85 		arch = new KTar(d->m_tempfile->fileName(), QLatin1String( "application/x-tar" ));
86 		break;
87 	case 4:
88 		arch = new KTar(d->m_tempfile->fileName(), QLatin1String( "application/x-xz" ));
89 		break;
90 	default:
91 		Q_ASSERT(0);
92 		return;
93 	}
94 
95 	if (!arch->open(QIODevice::WriteOnly)) {
96 		setError(UserDefinedError);
97 		setErrorText(i18n("Unable to create temporary file"));
98 		delete arch;
99 		emitResult();
100 		return;
101 	}
102 
103 	for (const QUrl &url : d->m_sources)
104 		arch->addLocalDirectory(url.path(), url.fileName());
105 	arch->close();
106 	delete arch;
107 
108 	setPercent(50);
109 
110 	QDir outPath = d->m_sources.first().path();
111 	outPath.cdUp();
112 
113 	d->m_options << QLatin1String("--output") << QDir::toNativeSeparators(outPath.path() + QDir::separator()) + d->m_dest.fileName();
114 
115 	Q_EMIT description(this, d->m_description, qMakePair(i18nc("State of operation as in status", "State"),
116 			i18nc("Status message 'Encrypting <filename>' (operation starts)", "Encrypting %1", d->m_dest.path())));
117 
118 
119 	KGpgEncrypt *enc = new KGpgEncrypt(this, d->m_keys, QList<QUrl>({QUrl::fromLocalFile(d->m_tempfile->fileName())}), d->m_encOptions, d->m_options);
120 	connect(enc, &KGpgEncrypt::done, this, &FolderCompressJob::slotEncryptionDone);
121 	enc->start();
122 }
123 
124 void
slotEncryptionDone(int result)125 FolderCompressJob::slotEncryptionDone(int result)
126 {
127 	Q_D(FolderCompressJob);
128 
129 	sender()->deleteLater();
130 
131 	if ((result != KGpgTransaction::TS_OK) && (result != KGpgTransaction::TS_USER_ABORTED)) {
132 		setError(KJob::UserDefinedError + 1);
133 		setErrorText(i18n("The encryption failed with error code %1", result));
134 		Q_EMIT description(this, d->m_description, qMakePair(i18nc("State of operation as in status", "State"), i18n("Encryption failed.")));
135 	} else {
136 		Q_EMIT description(this, d->m_description, qMakePair(i18nc("State of operation as in status", "State"),
137 				i18nc("Status message 'Encrypted <filename>' (operation was completed)", "Encrypted %1", d->m_dest.path())));
138 	}
139 
140 	emitResult();
141 }
142 
143 QString
extensionForArchive(const int archive)144 FolderCompressJob::extensionForArchive(const int archive)
145 {
146 	switch (archive) {
147 	case 0:
148 		return QLatin1String(".zip");
149 	case 1:
150 		return QLatin1String(".tar.gz");
151 	case 2:
152 		return QLatin1String(".tar.bz2");
153 	case 3:
154 		return QLatin1String(".tar");
155 	case 4:
156 		return QLatin1String(".tar.xz");
157 	default:
158 		Q_ASSERT(archive <= archiveNames().count());
159 		Q_ASSERT(archive >= 0);
160 		return QString();
161 	}
162 }
163 
164 const QStringList &
archiveNames()165 FolderCompressJob::archiveNames()
166 {
167 	static const QStringList archives =
168 			QStringList(i18n("Zip")) <<
169 					i18n("Tar/Gzip") <<
170 					i18n("Tar/Bzip2") <<
171 					i18n("Tar") <<
172 					i18n("Tar/XZ");
173 
174 	return archives;
175 }
176