• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeutils API Reference
  • KDE Home
  • Contact Us
 

ark

  • sources
  • kde-4.14
  • kdeutils
  • ark
  • kerfuffle
archive.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
3  * Copyright (c) 2008 Harald Hvaal <haraldhv@stud.ntnu.no>
4  * Copyright (c) 2009-2011 Raphael Kubo da Costa <rakuco@FreeBSD.org>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ( INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "archive.h"
29 #include "archiveinterface.h"
30 #include "jobs.h"
31 
32 #include <QByteArray>
33 #include <QEventLoop>
34 #include <QFile>
35 #include <QFileInfo>
36 
37 #include <KDebug>
38 #include <KPluginLoader>
39 #include <KMimeType>
40 #include <KMimeTypeTrader>
41 #include <KServiceTypeTrader>
42 
43 static bool comparePlugins(const KService::Ptr &p1, const KService::Ptr &p2)
44 {
45  return (p1->property(QLatin1String( "X-KDE-Priority" )).toInt()) > (p2->property(QLatin1String( "X-KDE-Priority" )).toInt());
46 }
47 
48 static QString determineMimeType(const QString& filename)
49 {
50  if (!QFile::exists(filename)) {
51  return KMimeType::findByPath(filename)->name();
52  }
53 
54  QFile file(filename);
55  if (!file.open(QIODevice::ReadOnly)) {
56  return QString();
57  }
58 
59  const qint64 maxSize = 0x100000; // 1MB
60  const qint64 bufferSize = qMin(maxSize, file.size());
61  const QByteArray buffer = file.read(bufferSize);
62 
63  return KMimeType::findByNameAndContent(filename, buffer)->name();
64 }
65 
66 static KService::List findPluginOffers(const QString& filename, const QString& fixedMimeType)
67 {
68  KService::List offers;
69 
70  const QString mimeType = fixedMimeType.isEmpty() ? determineMimeType(filename) : fixedMimeType;
71 
72  if (!mimeType.isEmpty()) {
73  offers = KMimeTypeTrader::self()->query(mimeType, QLatin1String( "Kerfuffle/Plugin" ), QLatin1String( "(exist Library)" ));
74  qSort(offers.begin(), offers.end(), comparePlugins);
75  }
76 
77  return offers;
78 }
79 
80 namespace Kerfuffle
81 {
82 
83 Archive *Archive::create(const QString &fileName, QObject *parent)
84 {
85  return create(fileName, QString(), parent);
86 }
87 
88 Archive *Archive::create(const QString &fileName, const QString &fixedMimeType, QObject *parent)
89 {
90  qRegisterMetaType<ArchiveEntry>("ArchiveEntry");
91 
92  const KService::List offers = findPluginOffers(fileName, fixedMimeType);
93 
94  if (offers.isEmpty()) {
95  kDebug() << "Could not find a plugin to handle" << fileName;
96  return NULL;
97  }
98 
99  const QString pluginName = offers.first()->library();
100  kDebug() << "Loading plugin" << pluginName;
101 
102  KPluginFactory * const factory = KPluginLoader(pluginName).factory();
103  if (!factory) {
104  kDebug() << "Invalid plugin factory for" << pluginName;
105  return NULL;
106  }
107 
108  QVariantList args;
109  args.append(QVariant(QFileInfo(fileName).absoluteFilePath()));
110 
111  ReadOnlyArchiveInterface * const iface = factory->create<ReadOnlyArchiveInterface>(0, args);
112  if (!iface) {
113  kDebug() << "Could not create plugin instance" << pluginName << "for" << fileName;
114  return NULL;
115  }
116 
117  return new Archive(iface, parent);
118 }
119 
120 Archive::Archive(ReadOnlyArchiveInterface *archiveInterface, QObject *parent)
121  : QObject(parent),
122  m_iface(archiveInterface),
123  m_hasBeenListed(false),
124  m_isPasswordProtected(false),
125  m_isSingleFolderArchive(false)
126 {
127  Q_ASSERT(archiveInterface);
128  archiveInterface->setParent(this);
129 }
130 
131 Archive::~Archive()
132 {
133 }
134 
135 bool Archive::isReadOnly() const
136 {
137  return m_iface->isReadOnly();
138 }
139 
140 KJob* Archive::open()
141 {
142  return 0;
143 }
144 
145 KJob* Archive::create()
146 {
147  return 0;
148 }
149 
150 ListJob* Archive::list()
151 {
152  ListJob *job = new ListJob(m_iface, this);
153  job->setAutoDelete(false);
154 
155  //if this job has not been listed before, we grab the opportunity to
156  //collect some information about the archive
157  if (!m_hasBeenListed) {
158  connect(job, SIGNAL(result(KJob*)),
159  this, SLOT(onListFinished(KJob*)));
160  }
161  return job;
162 }
163 
164 DeleteJob* Archive::deleteFiles(const QList<QVariant> & files)
165 {
166  if (m_iface->isReadOnly()) {
167  return 0;
168  }
169  DeleteJob *newJob = new DeleteJob(files, static_cast<ReadWriteArchiveInterface*>(m_iface), this);
170 
171  return newJob;
172 }
173 
174 AddJob* Archive::addFiles(const QStringList & files, const CompressionOptions& options)
175 {
176  Q_ASSERT(!m_iface->isReadOnly());
177  AddJob *newJob = new AddJob(files, options, static_cast<ReadWriteArchiveInterface*>(m_iface), this);
178  connect(newJob, SIGNAL(result(KJob*)),
179  this, SLOT(onAddFinished(KJob*)));
180  return newJob;
181 }
182 
183 ExtractJob* Archive::copyFiles(const QList<QVariant> & files, const QString & destinationDir, ExtractionOptions options)
184 {
185  ExtractionOptions newOptions = options;
186  if (isPasswordProtected()) {
187  newOptions[QLatin1String( "PasswordProtectedHint" )] = true;
188  }
189 
190  ExtractJob *newJob = new ExtractJob(files, destinationDir, newOptions, m_iface, this);
191  return newJob;
192 }
193 
194 QString Archive::fileName() const
195 {
196  return m_iface->filename();
197 }
198 
199 void Archive::onAddFinished(KJob* job)
200 {
201  //if the archive was previously a single folder archive and an add job
202  //has successfully finished, then it is no longer a single folder
203  //archive (for the current implementation, which does not allow adding
204  //folders/files other places than the root.
205  //TODO: handle the case of creating a new file and singlefolderarchive
206  //then.
207  if (m_isSingleFolderArchive && !job->error()) {
208  m_isSingleFolderArchive = false;
209  }
210 }
211 
212 void Archive::onListFinished(KJob* job)
213 {
214  ListJob *ljob = qobject_cast<ListJob*>(job);
215  m_extractedFilesSize = ljob->extractedFilesSize();
216  m_isSingleFolderArchive = ljob->isSingleFolderArchive();
217  m_isPasswordProtected = ljob->isPasswordProtected();
218  m_subfolderName = ljob->subfolderName();
219  if (m_subfolderName.isEmpty()) {
220  QFileInfo fi(fileName());
221  QString base = fi.completeBaseName();
222 
223  //special case for tar.gz/bzip2 files
224  if (base.right(4).toUpper() == QLatin1String(".TAR")) {
225  base.chop(4);
226  }
227 
228  m_subfolderName = base;
229  }
230 
231  m_hasBeenListed = true;
232 }
233 
234 void Archive::listIfNotListed()
235 {
236  if (!m_hasBeenListed) {
237  KJob *job = list();
238 
239  connect(job, SIGNAL(userQuery(Kerfuffle::Query*)),
240  SLOT(onUserQuery(Kerfuffle::Query*)));
241 
242  QEventLoop loop(this);
243 
244  connect(job, SIGNAL(result(KJob*)),
245  &loop, SLOT(quit()));
246  job->start();
247  loop.exec(); // krazy:exclude=crashy
248  }
249 }
250 
251 void Archive::onUserQuery(Query* query)
252 {
253  query->execute();
254 }
255 
256 bool Archive::isSingleFolderArchive()
257 {
258  listIfNotListed();
259  return m_isSingleFolderArchive;
260 }
261 
262 bool Archive::isPasswordProtected()
263 {
264  listIfNotListed();
265  return m_isPasswordProtected;
266 }
267 
268 QString Archive::subfolderName()
269 {
270  listIfNotListed();
271  return m_subfolderName;
272 }
273 
274 void Archive::setPassword(const QString &password)
275 {
276  m_iface->setPassword(password);
277 }
278 
279 QStringList supportedMimeTypes()
280 {
281  const QLatin1String constraint("(exist Library)");
282  const QLatin1String basePartService("Kerfuffle/Plugin");
283 
284  const KService::List offers = KServiceTypeTrader::self()->query(basePartService, constraint);
285  KService::List::ConstIterator it = offers.constBegin();
286  KService::List::ConstIterator itEnd = offers.constEnd();
287 
288  QStringList supported;
289 
290  for (; it != itEnd; ++it) {
291  KService::Ptr service = *it;
292  QStringList mimeTypes = service->serviceTypes();
293 
294  foreach (const QString& mimeType, mimeTypes) {
295  if (mimeType != basePartService && !supported.contains(mimeType)) {
296  supported.append(mimeType);
297  }
298  }
299  }
300 
301  kDebug() << "Returning" << supported;
302 
303  return supported;
304 }
305 
306 QStringList supportedWriteMimeTypes()
307 {
308  const QLatin1String constraint("(exist Library) and ([X-KDE-Kerfuffle-ReadWrite] == true)");
309  const QLatin1String basePartService("Kerfuffle/Plugin");
310 
311  const KService::List offers = KServiceTypeTrader::self()->query(basePartService, constraint);
312  KService::List::ConstIterator it = offers.constBegin();
313  KService::List::ConstIterator itEnd = offers.constEnd();
314 
315  QStringList supported;
316 
317  for (; it != itEnd; ++it) {
318  KService::Ptr service = *it;
319  QStringList mimeTypes = service->serviceTypes();
320 
321  foreach (const QString& mimeType, mimeTypes) {
322  if (mimeType != basePartService && !supported.contains(mimeType)) {
323  supported.append(mimeType);
324  }
325  }
326  }
327 
328  kDebug() << "Returning" << supported;
329 
330  return supported;
331 }
332 
333 } // namespace Kerfuffle
findPluginOffers
static KService::List findPluginOffers(const QString &filename, const QString &fixedMimeType)
Definition: archive.cpp:66
QString::append
QString & append(QChar ch)
QString::toUpper
QString toUpper() const
QEventLoop
Kerfuffle::Query
Definition: queries.h:44
QByteArray
Kerfuffle::supportedWriteMimeTypes
QStringList supportedWriteMimeTypes()
Definition: archive.cpp:306
Kerfuffle::DeleteJob
Definition: jobs.h:155
Kerfuffle::Archive::subfolderName
QString subfolderName()
Definition: archive.cpp:268
QStringList::contains
bool contains(const QString &str, Qt::CaseSensitivity cs) const
Kerfuffle::AddJob
Definition: jobs.h:140
Kerfuffle::ReadOnlyArchiveInterface::filename
QString filename() const
Returns the filename of the archive currently being handled.
Definition: archiveinterface.cpp:48
archive.h
QFile::exists
bool exists() const
QString::chop
void chop(int n)
Kerfuffle::Archive::create
KJob * create()
Definition: archive.cpp:145
QFile
Kerfuffle::ReadOnlyArchiveInterface
Definition: archiveinterface.h:43
Kerfuffle::Archive::~Archive
~Archive()
Definition: archive.cpp:131
Kerfuffle::Archive::isPasswordProtected
bool isPasswordProtected()
Definition: archive.cpp:262
Kerfuffle::ListJob
Definition: jobs.h:92
QList::append
void append(const T &value)
Kerfuffle::supportedMimeTypes
QStringList supportedMimeTypes()
Definition: archive.cpp:279
archiveinterface.h
Kerfuffle::Archive::isSingleFolderArchive
bool isSingleFolderArchive()
Definition: archive.cpp:256
QHash< QString, QVariant >
Kerfuffle::ReadOnlyArchiveInterface::setPassword
void setPassword(const QString &password)
Definition: archiveinterface.cpp:63
QObject
QString::isEmpty
bool isEmpty() const
determineMimeType
static QString determineMimeType(const QString &filename)
Definition: archive.cpp:48
QIODevice::read
qint64 read(char *data, qint64 maxSize)
Kerfuffle::Archive::list
ListJob * list()
Definition: archive.cpp:150
QString
QList
QFile::open
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
QStringList
Kerfuffle::Archive::fileName
QString fileName() const
Definition: archive.cpp:194
QString::right
QString right(int n) const
Kerfuffle::Archive
Definition: archive.h:88
QFileInfo
QObject::setParent
void setParent(QObject *parent)
Kerfuffle::Archive::open
KJob * open()
Definition: archive.cpp:140
QFile::size
virtual qint64 size() const
comparePlugins
static bool comparePlugins(const KService::Ptr &p1, const KService::Ptr &p2)
Definition: archive.cpp:43
Kerfuffle::ExtractJob
Definition: jobs.h:118
jobs.h
Kerfuffle::ReadOnlyArchiveInterface::isReadOnly
virtual bool isReadOnly() const
Returns whether the file can only be read.
Definition: archiveinterface.cpp:53
QLatin1String
Kerfuffle::Archive::copyFiles
ExtractJob * copyFiles(const QList< QVariant > &files, const QString &destinationDir, ExtractionOptions options=ExtractionOptions())
Definition: archive.cpp:183
Kerfuffle::Archive::setPassword
void setPassword(const QString &password)
Definition: archive.cpp:274
Kerfuffle::Archive::deleteFiles
DeleteJob * deleteFiles(const QList< QVariant > &files)
Definition: archive.cpp:164
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Kerfuffle::Archive::addFiles
AddJob * addFiles(const QStringList &files, const CompressionOptions &options=CompressionOptions())
Compression options that should be handled by all interfaces:
Definition: archive.cpp:174
KJob
Kerfuffle::Archive::isReadOnly
bool isReadOnly() const
Definition: archive.cpp:135
QVariant
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:42:36 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

ark

Skip menu "ark"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdeutils API Reference

Skip menu "kdeutils API Reference"
  • ark
  • filelight
  • kcalc
  • kcharselect
  • kdf
  • kfloppy
  • kgpg
  • ktimer
  • kwallet
  • sweeper

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal