summaryrefslogtreecommitdiffstats
path: root/installerbuilder/libinstaller
diff options
context:
space:
mode:
Diffstat (limited to 'installerbuilder/libinstaller')
-rw-r--r--installerbuilder/libinstaller/3rdparty/7zip/lib7z_facade.cpp8
-rw-r--r--installerbuilder/libinstaller/3rdparty/7zip/lib7z_facade.h24
-rw-r--r--installerbuilder/libinstaller/adminauthorization_win.cpp3
-rw-r--r--installerbuilder/libinstaller/binaryformat.cpp1115
-rw-r--r--installerbuilder/libinstaller/binaryformat.h248
-rw-r--r--installerbuilder/libinstaller/binaryformatengine.cpp297
-rw-r--r--installerbuilder/libinstaller/binaryformatengine.h78
-rw-r--r--installerbuilder/libinstaller/binaryformatenginehandler.cpp116
-rw-r--r--installerbuilder/libinstaller/binaryformatenginehandler.h66
-rw-r--r--installerbuilder/libinstaller/component.cpp5
-rw-r--r--installerbuilder/libinstaller/createdesktopentryoperation.cpp20
-rw-r--r--installerbuilder/libinstaller/createlocalrepositoryoperation.cpp9
-rw-r--r--installerbuilder/libinstaller/createshortcutoperation.cpp20
-rw-r--r--installerbuilder/libinstaller/downloadarchivesjob.cpp7
-rw-r--r--installerbuilder/libinstaller/errors.h59
-rw-r--r--installerbuilder/libinstaller/extractarchiveoperation_p.h3
-rw-r--r--installerbuilder/libinstaller/fileutils.cpp507
-rw-r--r--installerbuilder/libinstaller/fileutils.h114
-rw-r--r--installerbuilder/libinstaller/fsengineserver.cpp3
-rw-r--r--installerbuilder/libinstaller/getrepositoriesmetainfojob.h12
-rw-r--r--installerbuilder/libinstaller/getrepositorymetainfojob.cpp7
-rw-r--r--installerbuilder/libinstaller/getrepositorymetainfojob.h12
-rw-r--r--installerbuilder/libinstaller/init.cpp13
-rw-r--r--installerbuilder/libinstaller/installiconsoperation.cpp7
-rw-r--r--installerbuilder/libinstaller/libinstaller.pro48
-rw-r--r--installerbuilder/libinstaller/operationrunner.cpp11
-rw-r--r--installerbuilder/libinstaller/packagemanagercore.cpp13
-rw-r--r--installerbuilder/libinstaller/packagemanagercore.h3
-rw-r--r--installerbuilder/libinstaller/packagemanagercore_p.cpp17
-rw-r--r--installerbuilder/libinstaller/packagemanagergui.cpp10
-rw-r--r--installerbuilder/libinstaller/range.h88
-rw-r--r--installerbuilder/libinstaller/repository.cpp213
-rw-r--r--installerbuilder/libinstaller/repository.h97
-rw-r--r--installerbuilder/libinstaller/settings.cpp5
-rw-r--r--installerbuilder/libinstaller/updater.cpp6
-rw-r--r--installerbuilder/libinstaller/updatesettings.cpp5
-rw-r--r--installerbuilder/libinstaller/utils.cpp341
-rw-r--r--installerbuilder/libinstaller/utils.h92
-rw-r--r--installerbuilder/libinstaller/zipjob.cpp206
-rw-r--r--installerbuilder/libinstaller/zipjob.h100
40 files changed, 3862 insertions, 146 deletions
diff --git a/installerbuilder/libinstaller/3rdparty/7zip/lib7z_facade.cpp b/installerbuilder/libinstaller/3rdparty/7zip/lib7z_facade.cpp
index 285f9bbbb..c679572fd 100644
--- a/installerbuilder/libinstaller/3rdparty/7zip/lib7z_facade.cpp
+++ b/installerbuilder/libinstaller/3rdparty/7zip/lib7z_facade.cpp
@@ -1,7 +1,10 @@
#include "lib7z_facade.h"
+#include "errors.h"
+#include "fileutils.h"
+
#ifndef Q_OS_WIN
-#include "StdAfx.h"
+# include "StdAfx.h"
#endif
#include "Common/MyInitGuid.h"
@@ -36,9 +39,6 @@
#include "Windows/PropVariant.h"
#include "Windows/PropVariantConversions.h"
-#include <common/errors.h>
-#include <common/fileutils.h>
-
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QDir>
diff --git a/installerbuilder/libinstaller/3rdparty/7zip/lib7z_facade.h b/installerbuilder/libinstaller/3rdparty/7zip/lib7z_facade.h
index 855648aa2..58774df11 100644
--- a/installerbuilder/libinstaller/3rdparty/7zip/lib7z_facade.h
+++ b/installerbuilder/libinstaller/3rdparty/7zip/lib7z_facade.h
@@ -1,21 +1,21 @@
#ifndef LIB7Z_FACADE_H
#define LIB7Z_FACADE_H
-#include <QCoreApplication>
-#include <QDateTime>
-#include <QFile>
-#include <QString>
-#include <QRunnable>
-#include <QVector>
-#include <QVariant>
-#include <QPoint>
-
-#include <stdexcept>
-#include <string>
+#include "installer_global.h"
#include "Common/MyWindows.h"
-#include "../../installerbuilder/libinstaller/installer_global.h"
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDateTime>
+#include <QtCore/QFile>
+#include <QtCore/QPoint>
+#include <QtCore/QRunnable>
+#include <QtCore/QString>
+#include <QtCore/QVector>
+#include <QtCore/QVariant>
+
+#include <stdexcept>
+#include <string>
QT_BEGIN_NAMESPACE
class QStringList;
diff --git a/installerbuilder/libinstaller/adminauthorization_win.cpp b/installerbuilder/libinstaller/adminauthorization_win.cpp
index 21a592b89..7cfd6b3dc 100644
--- a/installerbuilder/libinstaller/adminauthorization_win.cpp
+++ b/installerbuilder/libinstaller/adminauthorization_win.cpp
@@ -29,10 +29,9 @@
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
-
#include "adminauthorization.h"
-#include <common/utils.h>
+#include "utils.h"
#include <QtCore/QDebug>
#include <QtCore/QDir>
diff --git a/installerbuilder/libinstaller/binaryformat.cpp b/installerbuilder/libinstaller/binaryformat.cpp
new file mode 100644
index 000000000..133df3690
--- /dev/null
+++ b/installerbuilder/libinstaller/binaryformat.cpp
@@ -0,0 +1,1115 @@
+/**************************************************************************
+**
+** This file is part of Installer Framework
+**
+** Copyright (c) 2011-2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "binaryformat.h"
+
+#include "errors.h"
+#include "fileutils.h"
+#include "lib7z_facade.h"
+#include "utils.h"
+#include "zipjob.h"
+
+#include <kdupdaterupdateoperationfactory.h>
+
+#include <QtCore/QResource>
+#include <QtCore/QTemporaryFile>
+
+#include <errno.h>
+
+using namespace QInstaller;
+using namespace QInstallerCreator;
+
+/*
+TRANSLATOR QInstallerCreator::Archive
+*/
+
+/*
+TRANSLATOR QInstallerCreator::Component
+*/
+
+static inline QByteArray &theBuffer(int size)
+{
+ static QByteArray b;
+ if (size > b.size())
+ b.resize(size);
+ return b;
+}
+
+void QInstaller::appendFileData(QIODevice *out, QIODevice *in)
+{
+ Q_ASSERT(!in->isSequential());
+ const qint64 size = in->size();
+ blockingCopy(in, out, size);
+}
+
+
+void QInstaller::retrieveFileData(QIODevice *out, QIODevice *in)
+{
+ qint64 size = QInstaller::retrieveInt64(in);
+ appendData(in, out, size);
+/* QByteArray &b = theBuffer(size);
+ blockingRead(in, b.data(), size);
+ blockingWrite(out, b.constData(), size);*/
+}
+
+void QInstaller::appendInt64(QIODevice *out, qint64 n)
+{
+ blockingWrite(out, reinterpret_cast<const char*>(&n), sizeof(n));
+}
+
+void QInstaller::appendInt64Range(QIODevice *out, const Range<qint64> &r)
+{
+ appendInt64(out, r.start());
+ appendInt64(out, r.length());
+}
+
+qint64 QInstaller::retrieveInt64(QIODevice *in)
+{
+ qint64 n = 0;
+ blockingRead(in, reinterpret_cast<char*>(&n), sizeof(n));
+ return n;
+}
+
+Range<qint64> QInstaller::retrieveInt64Range(QIODevice *in)
+{
+ const quint64 start = retrieveInt64(in);
+ const quint64 length = retrieveInt64(in);
+ return Range<qint64>::fromStartAndLength(start, length);
+}
+
+void QInstaller::appendData(QIODevice *out, QIODevice *in, qint64 size)
+{
+ while (size > 0) {
+ const qint64 nextSize = qMin(size, 16384LL);
+ QByteArray &b = theBuffer(nextSize);
+ blockingRead(in, b.data(), nextSize);
+ blockingWrite(out, b.constData(), nextSize);
+ size -= nextSize;
+ }
+}
+
+void QInstaller::appendString(QIODevice *out, const QString &str)
+{
+ appendByteArray(out, str.toUtf8());
+}
+
+void QInstaller::appendByteArray(QIODevice *out, const QByteArray &ba)
+{
+ appendInt64(out, ba.size());
+ blockingWrite(out, ba.constData(), ba.size());
+}
+
+void QInstaller::appendStringList(QIODevice *out, const QStringList &list)
+{
+ appendInt64(out, list.size());
+ foreach (const QString &s, list)
+ appendString(out, s);
+}
+
+void QInstaller::appendDictionary(QIODevice *out, const QHash<QString,QString> &dict)
+{
+ appendInt64(out, dict.size());
+ foreach (const QString &key, dict.keys()) {
+ appendString(out, key);
+ appendString(out, dict.value(key));
+ }
+}
+
+qint64 QInstaller::appendCompressedData(QIODevice *out, QIODevice *in, qint64 size)
+{
+ QByteArray ba;
+ ba.resize(size);
+ blockingRead(in, ba.data(), size);
+
+ QByteArray cba = qCompress(ba);
+ blockingWrite(out, cba, cba.size());
+ return cba.size();
+}
+
+QString QInstaller::retrieveString(QIODevice *in)
+{
+ const QByteArray b = retrieveByteArray(in);
+ return QString::fromUtf8(b);
+}
+
+QByteArray QInstaller::retrieveByteArray(QIODevice *in)
+{
+ QByteArray ba;
+ const qint64 n = retrieveInt64(in);
+ ba.resize(n);
+ blockingRead(in, ba.data(), n);
+ return ba;
+}
+
+QStringList QInstaller::retrieveStringList(QIODevice *in)
+{
+ QStringList list;
+ for (qint64 i = retrieveInt64(in); --i >= 0;)
+ list << retrieveString(in);
+ return list;
+}
+
+QHash<QString,QString> QInstaller::retrieveDictionary(QIODevice *in)
+{
+ QHash<QString,QString> dict;
+ for (qint64 i = retrieveInt64(in); --i >= 0;) {
+ QString key = retrieveString(in);
+ dict.insert(key, retrieveString(in));
+ }
+ return dict;
+}
+
+QByteArray QInstaller::retrieveData(QIODevice *in, qint64 size)
+{
+ QByteArray ba;
+ ba.resize(size);
+ blockingRead(in, ba.data(), size);
+ return ba;
+}
+
+QByteArray QInstaller::retrieveCompressedData(QIODevice *in, qint64 size)
+{
+ QByteArray ba;
+ ba.resize(size);
+ blockingRead(in, ba.data(), size);
+ return qUncompress(ba);
+}
+
+qint64 QInstaller::findMagicCookie(QFile *in, quint64 magicCookie)
+{
+ Q_ASSERT(in);
+ Q_ASSERT(in->isOpen());
+ Q_ASSERT(in->isReadable());
+ const qint64 oldPos = in->pos();
+ const qint64 MAX_SEARCH = 1024 * 1024; // stop searching after one MB
+ qint64 searched = 0;
+ try {
+ while (searched < MAX_SEARCH) {
+ const qint64 pos = in->size() - searched - sizeof(qint64);
+ if (pos < 0)
+ throw Error(QObject::tr("Searched whole file, no marker found"));
+ if (!in->seek(pos)) {
+ throw Error(QObject::tr("Could not seek to %1 in file %2: %3").arg(QString::number(pos),
+ in->fileName(), in->errorString()));
+ }
+ const quint64 num = static_cast<quint64>(retrieveInt64(in));
+ if (num == magicCookie) {
+ in->seek(oldPos);
+ return pos;
+ }
+ searched += 1;
+ }
+ throw Error(QObject::tr("No marker found, stopped after %1 bytes.").arg(QString::number(MAX_SEARCH)));
+ } catch (const Error& err) {
+ in->seek(oldPos);
+ throw err;
+ } catch (...) {
+ in->seek(oldPos);
+ throw Error(QObject::tr("No marker found, unknown exception caught."));
+ }
+ return -1; // never reached
+}
+
+/*!
+ Creates an archive providing the data in \a path.
+ \a path can be a path to a file or to a directory. If it's a file, it's considered to be
+ pre-zipped and gets delivered as it is. If it's a directory, it gets zipped by Archive.
+ */
+Archive::Archive(const QString &path)
+ : m_device(0),
+ m_isTempFile(false),
+ m_path(path),
+ m_name(QFileInfo(path).fileName().toUtf8())
+{
+}
+
+Archive::Archive(const QByteArray &identifier, const QByteArray &data)
+ : m_device(0),
+ m_isTempFile(true),
+ m_path(generateTemporaryFileName()),
+ m_name(identifier)
+{
+ QFile file(m_path);
+ file.open(QIODevice::WriteOnly);
+ file.write(data);
+}
+
+/*!
+ Creates an archive identified by \a identifier providing a data \a segment within a \a device.
+ */
+Archive::Archive(const QByteArray &identifier, const QSharedPointer<QFile> &device, const Range<qint64> &segment)
+ : m_device(device),
+ m_segment(segment),
+ m_isTempFile(false),
+ m_name(identifier)
+{
+}
+
+Archive::~Archive()
+{
+ if (isOpen())
+ close();
+ if (m_isTempFile)
+ QFile::remove(m_path);
+}
+
+/*!
+ Copies the archives contents to the path \a name.
+ If the archive is a zipped directory, \a name is treated as a directory. The archive gets extracted there.
+
+ If the archive is a plain file and \a name an existing directory, it gets created
+ with it's name. Otherwise it gets saved as \a name.
+ Note that if a file with the \a name already exists, copy() return false (i.e. Archive will not overwrite it).
+ */
+bool Archive::copy(const QString &name)
+{
+ const QFileInfo fileInfo(name);
+ if (isZippedDirectory()) {
+ if (fileInfo.exists() && !fileInfo.isDir())
+ return false;
+
+ errno = 0;
+ const QString absoluteFilePath = fileInfo.absoluteFilePath();
+ if (!fileInfo.exists() && !QDir().mkpath(absoluteFilePath)) {
+ setErrorString(tr("Could not create %1: %2").arg(name, QString::fromLocal8Bit(strerror(errno))));
+ return false;
+ }
+
+ if (isOpen())
+ close();
+ open(QIODevice::ReadOnly);
+
+ UnzipJob job;
+ job.setInputDevice(this);
+ job.setOutputPath(absoluteFilePath);
+ job.run();
+ } else {
+ if (isOpen())
+ close();
+ open(QIODevice::ReadOnly);
+
+ QFile target(fileInfo.isDir() ? QString::fromLatin1("%1/%2").arg(name)
+ .arg(QString::fromUtf8(m_name.data(), m_name.count())) : name);
+ if (target.exists())
+ return false;
+ target.open(QIODevice::WriteOnly);
+ blockingCopy(this, &target, size());
+ }
+ close();
+ return true;
+}
+
+/*!
+ \reimp
+ */
+bool Archive::seek(qint64 pos)
+{
+ if (m_inputFile.isOpen())
+ return m_inputFile.seek(pos) && QIODevice::seek(pos);
+ return QIODevice::seek(pos);
+}
+
+/*!
+ Returns true, if this archive was created by zipping a directory.
+ */
+bool Archive::isZippedDirectory() const
+{
+ if (m_device == 0) {
+ // easy, just check whether it's a dir
+ return QFileInfo(m_path).isDir();
+ }
+
+ // more complex, check the zip header magic
+ Archive* const arch = const_cast<Archive*> (this);
+
+ const bool notOpened = !isOpen();
+ if (notOpened)
+ arch->open(QIODevice::ReadOnly);
+ const qint64 p = pos();
+ arch->seek(0);
+
+ const QByteArray ba = arch->read(4);
+ const bool result = ba == QByteArray("\x50\x4b\x03\04");
+
+ arch->seek(p);
+ if (notOpened)
+ arch->close();
+ return result;
+}
+
+QByteArray Archive::name() const
+{
+ return m_name;
+}
+
+void Archive::setName(const QByteArray &name)
+{
+ m_name = name;
+}
+
+/*!
+ \reimpl
+ */
+void Archive::close()
+{
+ m_inputFile.close();
+ if (QFileInfo(m_path).isDir())
+ m_inputFile.remove();
+ QIODevice::close();
+}
+
+/*!
+ \reimp
+ */
+bool Archive::open(OpenMode mode)
+{
+ if (isOpen())
+ return false;
+
+ const bool writeOnly = (mode & QIODevice::WriteOnly) != QIODevice::NotOpen;
+ const bool append = (mode & QIODevice::Append) != QIODevice::NotOpen;
+
+ // no write support
+ if (writeOnly || append)
+ return false;
+
+ if (m_device != 0)
+ return QIODevice::open(mode);
+
+ const QFileInfo fi(m_path);
+ if (fi.isFile()) {
+ m_inputFile.setFileName(m_path);
+ if (!m_inputFile.open(mode)) {
+ setErrorString(tr("Could not open archive file %1 for reading.").arg(m_path));
+ return false;
+ }
+ setOpenMode(mode);
+ return true;
+ }
+
+ if (fi.isDir()) {
+ if (m_inputFile.fileName().isEmpty() || !m_inputFile.exists()) {
+ if (!createZippedFile())
+ return false;
+ }
+ Q_ASSERT(!m_inputFile.fileName().isEmpty());
+ if (!m_inputFile.open(mode))
+ return false;
+ setOpenMode(mode);
+ return true;
+ }
+
+ setErrorString(tr("Could not create archive from %1: Not a file.").arg(m_path));
+ return false;
+}
+
+bool Archive::createZippedFile()
+{
+ QTemporaryFile file;
+ file.setAutoRemove(false);
+ if (!file.open())
+ return false;
+
+ m_inputFile.setFileName(file.fileName());
+ file.close();
+ m_inputFile.open(QIODevice::ReadWrite);
+ try {
+ Lib7z::createArchive(&m_inputFile, QStringList() << m_path);
+ } catch(Lib7z::SevenZipException &e) {
+ m_inputFile.close();
+ setErrorString(e.message());
+ return false;
+ }
+
+ if (!Lib7z::isSupportedArchive(&m_inputFile)) {
+ m_inputFile.close();
+ setErrorString(tr("Error while packing directory at %1").arg(m_path));
+ return false;
+ }
+ m_inputFile.close();
+ return true;
+}
+
+/*!
+ \reimp
+ */
+qint64 Archive::size() const
+{
+ // if we got a device, we just pass the length of the segment
+ if (m_device != 0)
+ return m_segment.length();
+
+ const QFileInfo fi(m_path);
+ // if we got a regular file, we pass the size of the file
+ if (fi.isFile())
+ return fi.size();
+
+ if (fi.isDir()) {
+ if (m_inputFile.fileName().isEmpty() || !m_inputFile.exists()) {
+ if (!const_cast< Archive* >(this)->createZippedFile()) {
+ throw Error(QObject::tr("Cannot create zipped file for path %1: %2").arg(m_path,
+ errorString()));
+ }
+ }
+ Q_ASSERT(!m_inputFile.fileName().isEmpty());
+ return m_inputFile.size();
+ }
+ return 0;
+}
+
+/*!
+ \reimp
+ */
+qint64 Archive::readData(char* data, qint64 maxSize)
+{
+ if (m_device == 0)
+ return m_inputFile.read(data, maxSize);
+
+ const qint64 p = m_device->pos();
+ m_device->seek(m_segment.start() + pos());
+ const qint64 amountRead = m_device->read(data, qMin<quint64>(maxSize, m_segment.length() - pos()));
+ m_device->seek(p);
+ return amountRead;
+}
+
+/*!
+ \reimp
+ */
+qint64 Archive::writeData(const char* data, qint64 maxSize)
+{
+ Q_UNUSED(data);
+ Q_UNUSED(maxSize);
+ // should never be called, as we're read only
+ return -1;
+}
+
+QByteArray Component::name() const
+{
+ return m_name;
+}
+
+void Component::setName(const QByteArray &ba)
+{
+ m_name = ba;
+}
+
+Range<qint64> Component::binarySegment() const
+{
+ return m_binarySegment;
+}
+
+void Component::setBinarySegment(const Range<qint64> &r)
+{
+ m_binarySegment = r;
+}
+
+Component Component::readFromIndexEntry(const QSharedPointer<QFile> &in, qint64 offset)
+{
+ Component c;
+ c.m_name = retrieveByteArray(in.data());
+ c.m_binarySegment = retrieveInt64Range(in.data()).moved(offset);
+
+ c.readData(in, offset);
+
+ return c;
+}
+
+void Component::writeIndexEntry(QIODevice *out, qint64 positionOffset) const
+{
+ appendByteArray(out, m_name);
+ const Range<qint64> relative = m_binarySegment.moved(positionOffset);
+ appendInt64(out, binarySegment().start());
+ appendInt64(out, binarySegment().length());
+}
+
+void Component::writeData(QIODevice *out, qint64 offset) const
+{
+ const qint64 dataBegin = out->pos() + offset;
+
+ appendInt64(out, m_archives.count());
+
+ qint64 start = out->pos() + offset;
+
+ // Why 16 + 16? This is 24, not 32???
+ const int foo = 3 * sizeof(qint64);
+ // add 16 + 16 + number of name characters for each archive (the size of the table)
+ foreach (const QSharedPointer<Archive> &archive, m_archives)
+ start += foo + archive->name().count();
+
+ QList<qint64> starts;
+ foreach (const QSharedPointer<Archive> &archive, m_archives) {
+ appendByteArray(out, archive->name());
+ starts.push_back(start);
+ appendInt64Range(out, Range<qint64>::fromStartAndLength(start, archive->size()));
+ start += archive->size();
+ }
+
+ foreach (const QSharedPointer<Archive> &archive, m_archives) {
+ if (!archive->open(QIODevice::ReadOnly)) {
+ throw Error(tr("Could not open archive %1: %2").arg(QLatin1String(archive->name()),
+ archive->errorString()));
+ }
+
+ const qint64 expectedStart = starts.takeFirst();
+ const qint64 actualStart = out->pos() + offset;
+ Q_UNUSED(expectedStart);
+ Q_UNUSED(actualStart);
+ Q_ASSERT(expectedStart == actualStart);
+ blockingCopy(archive.data(), out, archive->size());
+ }
+
+ m_binarySegment = Range<qint64>::fromStartAndEnd(dataBegin, out->pos() + offset);
+}
+
+void Component::readData(const QSharedPointer<QFile> &in, qint64 offset)
+{
+ const qint64 pos = in->pos();
+
+ in->seek(m_binarySegment.start());
+ const qint64 count = retrieveInt64(in.data());
+
+ QVector<QByteArray> names;
+ QVector<Range<qint64> > ranges;
+ for (int i = 0; i < count; ++i) {
+ names.push_back(retrieveByteArray(in.data()));
+ ranges.push_back(retrieveInt64Range(in.data()).moved(offset));
+ }
+
+ for (int i = 0; i < ranges.count(); ++i)
+ m_archives.append(QSharedPointer<Archive>(new Archive(names.at(i), in, ranges.at(i))));
+
+ in->seek(pos);
+}
+
+QString Component::dataDirectory() const
+{
+ return m_dataDirectory;
+}
+
+void Component::setDataDirectory(const QString &path)
+{
+ m_dataDirectory = path;
+}
+
+bool Component::operator<(const Component& other) const
+{
+ if (m_name != other.name())
+ return m_name < other.m_name;
+ return m_binarySegment < other.m_binarySegment;
+}
+
+bool Component::operator==(const Component& other) const
+{
+ return m_name == other.m_name && m_binarySegment == other.m_binarySegment;
+}
+
+/*!
+ Destroys this component.
+ */
+Component::~Component()
+{
+}
+
+/*!
+ Appends \a archive to this component. The component takes ownership of \a archive.
+ */
+void Component::appendArchive(const QSharedPointer<Archive>& archive)
+{
+ Q_ASSERT(archive);
+ archive->setParent(0);
+ m_archives.push_back(archive);
+}
+
+/*!
+ Returns the archives associated with this component.
+ */
+QVector<QSharedPointer<Archive> > Component::archives() const
+{
+ return m_archives;
+}
+
+QSharedPointer<Archive> Component::archiveByName(const QByteArray &name) const
+{
+ foreach (const QSharedPointer<Archive>& i, m_archives) {
+ if (i->name() == name)
+ return i;
+ }
+ return QSharedPointer<Archive>();
+}
+
+
+// -- ComponentIndex
+
+ComponentIndex::ComponentIndex()
+{
+}
+
+ComponentIndex ComponentIndex::read(const QSharedPointer<QFile> &dev, qint64 offset)
+{
+ ComponentIndex result;
+ const qint64 size = retrieveInt64(dev.data());
+ for (int i = 0; i < size; ++i)
+ result.insertComponent(Component::readFromIndexEntry(dev, offset));
+ retrieveInt64(dev.data());
+ return result;
+}
+
+void ComponentIndex::writeIndex(QIODevice *out, qint64 offset) const
+{
+ // Q: why do we write the size twice?
+ // A: for us to be able to read it beginning from the end of the file as well
+ appendInt64(out, componentCount());
+ foreach (const Component& i, components())
+ i.writeIndexEntry(out, offset);
+ appendInt64(out, componentCount());
+}
+
+void ComponentIndex::writeComponentData(QIODevice *out, qint64 offset) const
+{
+ appendInt64(out, componentCount());
+
+ foreach (const Component &component, m_components)
+ component.writeData(out, offset);
+}
+
+Component ComponentIndex::componentByName(const QByteArray &id) const
+{
+ return m_components.value(id);
+}
+
+void ComponentIndex::insertComponent(const Component& c)
+{
+ m_components.insert(c.name(), c);
+}
+
+void ComponentIndex::removeComponent(const QByteArray &name)
+{
+ m_components.remove(name);
+}
+
+QVector<Component> ComponentIndex::components() const
+{
+ return m_components.values().toVector();
+}
+
+int ComponentIndex::componentCount() const
+{
+ return m_components.size();
+}
+
+
+static QVector<QByteArray> sResourceVec;
+/*!
+ \internal
+ Registers the resource found at \a segment within \a file into the Qt resource system.
+ */
+static const uchar* addResourceFromBinary(QFile* file, const Range<qint64> &segment)
+{
+ if (segment.length() <= 0)
+ return 0;
+
+ if (!file->seek(segment.start())) {
+ throw Error(QObject::tr("Could not seek to in-binary resource. (offset: %1, length: %2)")
+ .arg(QString::number(segment.start()), QString::number(segment.length())));
+ }
+ sResourceVec.append(retrieveData(file, segment.length()));
+
+ if (!QResource::registerResource((const uchar*)(sResourceVec.last().constData()),
+ QLatin1String(":/metadata"))) {
+ throw Error(QObject::tr("Could not register in-binary resource."));
+ }
+ return (const uchar*)(sResourceVec.last().constData());
+}
+
+
+// -- BinaryContentPrivate
+
+BinaryContentPrivate::BinaryContentPrivate(const QString &path)
+ : m_magicMarker(0)
+ , m_dataBlockStart(0)
+ , m_appBinary(new QFile(path))
+ , m_binaryDataFile(0)
+ , m_binaryFormatEngineHandler(m_componentIndex)
+{
+}
+
+BinaryContentPrivate::BinaryContentPrivate(const BinaryContentPrivate &other)
+ : QSharedData(other)
+ , m_magicMarker(other.m_magicMarker)
+ , m_dataBlockStart(other.m_dataBlockStart)
+ , m_appBinary(other.m_appBinary)
+ , m_binaryDataFile(other.m_binaryDataFile)
+ , m_performedOperations(other.m_performedOperations)
+ , m_performedOperationsData(other.m_performedOperationsData)
+ , m_resourceMappings(other.m_resourceMappings)
+ , m_metadataResourceSegments(other.m_metadataResourceSegments)
+ , m_componentIndex(other.m_componentIndex)
+ , m_binaryFormatEngineHandler(other.m_binaryFormatEngineHandler)
+{
+}
+
+BinaryContentPrivate::~BinaryContentPrivate()
+{
+ foreach (const uchar *rccData, m_resourceMappings)
+ QResource::unregisterResource(rccData);
+ sResourceVec.clear();
+ m_resourceMappings.clear();
+}
+
+
+// -- BinaryContent
+
+BinaryContent::BinaryContent(const QString &path)
+ : d(new BinaryContentPrivate(path))
+{
+}
+
+BinaryContent::~BinaryContent()
+{
+}
+
+/*!
+ Reads binary content stored in the current application binary. Maps the embedded resources into memory
+ and instantiates performed operations if available.
+*/
+BinaryContent BinaryContent::readAndRegisterFromApplicationFile()
+{
+ BinaryContent c = BinaryContent::readFromApplicationFile();
+ c.registerEmbeddedQResources();
+ c.registerPerformedOperations();
+ return c;
+}
+
+/*!
+ Reads binary content stored in the passed application binary. Maps the embedded resources into memory
+ and instantiates performed operations if available.
+*/
+BinaryContent BinaryContent::readAndRegisterFromBinary(const QString &path)
+{
+ BinaryContent c = BinaryContent::readFromBinary(path);
+ c.registerEmbeddedQResources();
+ c.registerPerformedOperations();
+ return c;
+}
+
+/*!
+ Reads binary content stored in the current application binary.
+*/
+BinaryContent BinaryContent::readFromApplicationFile()
+{
+ return BinaryContent::readFromBinary(QCoreApplication::applicationFilePath());;
+}
+
+/*!
+ * \class QInstaller::BinaryContent
+ *
+ * BinaryContent handles binary information embedded into executables.
+ * Qt resources as well as component information can be stored.
+ *
+ * Explanation of the binary blob at the end of the installer or separate data file:
+ *
+ * \verbatim
+ * Meta data segment 0
+ * Meta data segment ...
+ * Meta data segment n
+ * ------------------------------------------------------
+ * Component data segment 0
+ * Component data segment ..
+ * Component data segment n
+ * ------------------------------------------------------
+ * Component index segment
+ * ------------------------------------------------------
+ * quint64 offset of component index segment
+ * quint64 length of component index segment
+ * ------------------------------------------------------
+ * qint64 offset of meta data segment 0
+ * qint64 length of meta data segment 0
+ * qint64 offset of meta data segment ..
+ * qint64 length of meta data segment ..
+ * qint64 offset of meta data segment n
+ * qint64 length of meta data segment n
+ * ------------------------------------------------------
+ * operations start offest
+ * operations end
+ * quint64 embedded resource count
+ * quint64 data block size
+ * quint64 Magic marker
+ * quint64 Magic cookie (0xc2 0x63 0x0a 0x1c 0x99 0xd6 0x68 0xf8)
+ * <eof>
+ *
+ * All offsets are addresses relative to the end of the file.
+ *
+ * Meta data segments are stored as Qt resources, which must be "mounted"
+ * via QResource::registerResource()
+ *
+ * Component index segment:
+ * quint64 number of index entries
+ * QString identifier of component 0
+ * quint64 offset of component data segment 0
+ * quint64 length of component data segment 0
+ * QString identifier of component ..
+ * quint64 offset of component data segment ..
+ * quint64 length of component data segment ..
+ * QString identifier of component n
+ * quint64 offset of component data segment n
+ * quint64 length of component data segment n
+ * quint64 number of index entries
+ *
+ * Component data segment:
+ * quint64 number of archives in this component
+ * QString name of archive 0
+ * quint64 offset of archive 0
+ * quint64 length of archive 0
+ * QString name of archive ..
+ * quint64 offset of archive ..
+ * quint64 length of archive ..
+ * QString name of archive n
+ * quint64 offset of archive n
+ * quint64 length of archive n
+ * Archive 0
+ * Archive ..
+ * Archive n
+ * \endverbatim
+ */
+
+BinaryContent BinaryContent::readFromBinary(const QString &path)
+{
+ BinaryContent c(path);
+ if (!c.d->m_appBinary->open(QIODevice::ReadOnly))
+ throw Error(QObject::tr("Could not open binary %1: %2").arg(path, c.d->m_appBinary->errorString()));
+
+ // check for supported binary, will throw if we can't find a marker
+ const BinaryLayout layout = readBinaryLayout(c.d->m_appBinary.data(),
+ findMagicCookie(c.d->m_appBinary.data(), QInstaller::MagicCookie));
+
+ bool retry = true;
+ if (layout.magicMarker != MagicInstallerMarker) {
+ QString binaryDataPath = path;
+ QFileInfo fi(path + QLatin1String("/../../.."));
+ if (QFileInfo(fi.absoluteFilePath()).isBundle())
+ binaryDataPath = fi.absoluteFilePath();
+ fi.setFile(binaryDataPath);
+
+ c.d->m_binaryDataFile = QSharedPointer<QFile>(new QFile(fi.absolutePath() + QLatin1Char('/')
+ + fi.baseName() + QLatin1String(".dat")));
+ if (c.d->m_binaryDataFile->exists() && c.d->m_binaryDataFile->open(QIODevice::ReadOnly)) {
+ // check for supported binary data file, will throw if we can't find a marker
+ try {
+ const qint64 cookiePos = findMagicCookie(c.d->m_binaryDataFile.data(),
+ QInstaller::MagicCookieDat);
+ const BinaryLayout binaryLayout = readBinaryLayout(c.d->m_binaryDataFile.data(), cookiePos);
+ readBinaryData(c, c.d->m_binaryDataFile, binaryLayout);
+ retry = false;
+ } catch (const Error &error) {
+ // this seems to be an unsupported dat file, try to read from original binary
+ c.d->m_binaryDataFile.clear();
+ qDebug() << error.message();
+ }
+ } else {
+ c.d->m_binaryDataFile.clear();
+ }
+ }
+
+ if (retry)
+ readBinaryData(c, c.d->m_appBinary, layout);
+
+ return c;
+}
+
+/* static */
+BinaryLayout BinaryContent::readBinaryLayout(QIODevice *const file, qint64 cookiePos)
+{
+ const qint64 indexSize = 5 * sizeof(qint64);
+ if (!file->seek(cookiePos - indexSize))
+ throw Error(QObject::tr("Could not seek to binary layout section."));
+
+ BinaryLayout layout;
+ layout.operationsStart = retrieveInt64(file);
+ layout.operationsEnd = retrieveInt64(file);
+ layout.resourceCount = retrieveInt64(file);
+ layout.dataBlockSize = retrieveInt64(file);
+ layout.magicMarker = retrieveInt64(file);
+ layout.magicCookie = retrieveInt64(file);
+ layout.indexSize = indexSize + sizeof(qint64);
+ layout.endOfData = file->pos();
+
+ qDebug() << "Operations start:" << layout.operationsStart;
+ qDebug() << "Operations end:" << layout.operationsEnd;
+ qDebug() << "Resource count:" << layout.resourceCount;
+ qDebug() << "Data block size:" << layout.dataBlockSize;
+ qDebug() << "Magic marker:" << layout.magicMarker;
+ qDebug() << "Magic cookie:" << layout.magicCookie;
+ qDebug() << "Index size:" << layout.indexSize;
+ qDebug() << "End of data:" << layout.endOfData;
+
+ const qint64 resourceOffsetAndLengtSize = 2 * sizeof(qint64);
+ const qint64 dataBlockStart = layout.endOfData - layout.dataBlockSize;
+ for (int i = 0; i < layout.resourceCount; ++i) {
+ if (!file->seek(layout.endOfData - layout.indexSize - resourceOffsetAndLengtSize * (i + 1)))
+ throw Error(QObject::tr("Could not seek to metadata index."));
+
+ const qint64 metadataResourceOffset = retrieveInt64(file);
+ const qint64 metadataResourceLength = retrieveInt64(file);
+ layout.metadataResourceSegments.append(Range<qint64>::fromStartAndLength(metadataResourceOffset
+ + dataBlockStart, metadataResourceLength));
+ }
+
+ return layout;
+}
+
+/* static */
+void BinaryContent::readBinaryData(BinaryContent &content, const QSharedPointer<QFile> &file,
+ const BinaryLayout &layout)
+{
+ content.d->m_magicMarker = layout.magicMarker;
+ content.d->m_metadataResourceSegments = layout.metadataResourceSegments;
+
+ const qint64 dataBlockStart = layout.endOfData - layout.dataBlockSize;
+ const qint64 operationsStart = layout.operationsStart + dataBlockStart;
+ if (!file->seek(operationsStart))
+ throw Error(QObject::tr("Could not seek to operation list."));
+
+ const qint64 operationsCount = retrieveInt64(file.data());
+ qDebug() << "Number of operations:" << operationsCount;
+
+ for (int i = 0; i < operationsCount; ++i) {
+ const QString name = retrieveString(file.data());
+ const QString data = retrieveString(file.data());
+ content.d->m_performedOperationsData.append(qMakePair(name, data));
+ }
+
+ // seek to the position of the component index
+ const qint64 resourceOffsetAndLengtSize = 2 * sizeof(qint64);
+ const qint64 resourceSectionSize = resourceOffsetAndLengtSize * layout.resourceCount;
+ if (!file->seek(layout.endOfData - layout.indexSize - resourceSectionSize - resourceOffsetAndLengtSize))
+ throw Error(QObject::tr("Could not seek to component index information."));
+
+ const qint64 compIndexStart = retrieveInt64(file.data()) + dataBlockStart;
+ if (!file->seek(compIndexStart))
+ throw Error(QObject::tr("Could not seek to component index."));
+
+ content.d->m_componentIndex = QInstallerCreator::ComponentIndex::read(file, dataBlockStart);
+ content.d->m_binaryFormatEngineHandler.setComponentIndex(content.d->m_componentIndex);
+
+ if (isVerbose()) {
+ const QVector<QInstallerCreator::Component> components = content.d->m_componentIndex.components();
+ qDebug() << "Number of components loaded:" << components.count();
+ foreach (const QInstallerCreator::Component &component, components) {
+ const QVector<QSharedPointer<Archive> > archives = component.archives();
+ qDebug() << component.name().data() << "loaded...";
+ QStringList archivesWithSize;
+ foreach (const QSharedPointer<Archive> &archive, archives) {
+ QString archiveWithSize(QLatin1String("%1 - %2 Bytes"));
+ archiveWithSize = archiveWithSize.arg(QString::fromLocal8Bit(archive->name()),
+ QString::number(archive->size()));
+ archivesWithSize.append(archiveWithSize);
+ }
+ if (!archivesWithSize.isEmpty()) {
+ qDebug() << " - " << archives.count() << "archives: "
+ << qPrintable(archivesWithSize.join(QLatin1String("; ")));
+ }
+ }
+ }
+}
+
+/*!
+ Registers already performed operations.
+*/
+int BinaryContent::registerPerformedOperations()
+{
+ if (d->m_performedOperations.count() > 0)
+ return d->m_performedOperations.count();
+
+ for (int i = 0; i < d->m_performedOperationsData.count(); ++ i) {
+ const QPair<QString, QString> opPair = d->m_performedOperationsData.at(i);
+ QScopedPointer<Operation> op(KDUpdater::UpdateOperationFactory::instance().create(opPair.first));
+ Q_ASSERT_X(!op.isNull(), __FUNCTION__, QString::fromLatin1("Invalid operation name: %1.")
+ .arg(opPair.first).toLatin1());
+
+ if (!op->fromXml(opPair.second)) {
+ qWarning() << "Failed to load XML for operation:" << opPair.first;
+ continue;
+ }
+ d->m_performedOperations.append(op.take());
+ }
+ return d->m_performedOperations.count();
+}
+
+/*!
+ Returns the operations performed during installation. Returns an empty list if no operations are
+ instantiated, performed or the binary is the installer application.
+*/
+OperationList BinaryContent::performedOperations() const
+{
+ return d->m_performedOperations;
+}
+
+/*!
+ Returns the magic marker found in the binary. Returns 0 if no marker has been found.
+*/
+qint64 BinaryContent::magicMarker() const
+{
+ return d->m_magicMarker;
+}
+
+/*!
+ Registers the Qt resources embedded in this binary.
+ */
+int BinaryContent::registerEmbeddedQResources()
+{
+ if (d->m_resourceMappings.count() > 0)
+ return d->m_resourceMappings.count();
+
+ const bool hasBinaryDataFile = !d->m_binaryDataFile.isNull();
+ QFile *const data = hasBinaryDataFile ? d->m_binaryDataFile.data() : d->m_appBinary.data();
+ if (!data->isOpen() && !data->open(QIODevice::ReadOnly)) {
+ throw Error(QObject::tr("Could not open binary %1: %2").arg(data->fileName(),
+ data->errorString()));
+ }
+
+ foreach (const Range<qint64> &i, d->m_metadataResourceSegments)
+ d->m_resourceMappings.append(addResourceFromBinary(data, i));
+
+ d->m_appBinary.clear();
+ if (hasBinaryDataFile)
+ d->m_binaryDataFile.clear();
+
+ return d->m_resourceMappings.count();
+}
+
+/*!
+ Returns the binary component index as read from the file.
+*/
+QInstallerCreator::ComponentIndex BinaryContent::componentIndex() const
+{
+ return d->m_componentIndex;
+}
diff --git a/installerbuilder/libinstaller/binaryformat.h b/installerbuilder/libinstaller/binaryformat.h
new file mode 100644
index 000000000..e2e1f6a0f
--- /dev/null
+++ b/installerbuilder/libinstaller/binaryformat.h
@@ -0,0 +1,248 @@
+/**************************************************************************
+**
+** This file is part of Installer Framework
+**
+** Copyright (c) 2010-2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef BINARYFORMAT_H
+#define BINARYFORMAT_H
+
+#include "binaryformatenginehandler.h"
+#include "range.h"
+#include "qinstallerglobal.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QFile>
+#include <QtCore/QHash>
+#include <QtCore/QStack>
+#include <QtCore/QVector>
+#include <QtCore/QSharedPointer>
+
+namespace QInstaller {
+ static const qint64 MagicInstallerMarker = 0x12023233UL;
+ static const qint64 MagicUninstallerMarker = 0x12023234UL;
+
+ static const qint64 MagicUpdaterMarker = 0x12023235UL;
+ static const qint64 MagicPackageManagerMarker = 0x12023236UL;
+
+ // this cookie is put at the end of the file to determine whether we have data
+ static const quint64 MagicCookie = 0xc2630a1c99d668f8LL;
+ static const quint64 MagicCookieDat = 0xc2630a1c99d668f9LL;
+
+ qint64 INSTALLER_EXPORT findMagicCookie(QFile *file, quint64 magicCookie = MagicCookie);
+ void INSTALLER_EXPORT appendFileData(QIODevice *out, QIODevice *in);
+ void INSTALLER_EXPORT appendInt64(QIODevice *out, qint64 n);
+ void INSTALLER_EXPORT appendInt64Range(QIODevice *out, const Range<qint64> &r);
+ void INSTALLER_EXPORT appendData(QIODevice *out, QIODevice *in, qint64 size);
+ void INSTALLER_EXPORT appendByteArray(QIODevice *out, const QByteArray &ba);
+ void INSTALLER_EXPORT appendString(QIODevice *out, const QString &str);
+ void INSTALLER_EXPORT appendStringList(QIODevice *out, const QStringList &list);
+ void INSTALLER_EXPORT appendDictionary(QIODevice *out, const QHash<QString,QString> &dict);
+ qint64 INSTALLER_EXPORT appendCompressedData(QIODevice *out, QIODevice *in, qint64 size);
+
+ void INSTALLER_EXPORT retrieveFileData(QIODevice *out, QIODevice *in);
+ qint64 INSTALLER_EXPORT retrieveInt64(QIODevice *in);
+ Range<qint64> INSTALLER_EXPORT retrieveInt64Range(QIODevice *in);
+ QByteArray INSTALLER_EXPORT retrieveByteArray(QIODevice *in);
+ QString INSTALLER_EXPORT retrieveString(QIODevice *in);
+ QStringList INSTALLER_EXPORT retrieveStringList(QIODevice *in);
+ QHash<QString,QString> INSTALLER_EXPORT retrieveDictionary(QIODevice *in);
+ QByteArray INSTALLER_EXPORT retrieveData(QIODevice *in, qint64 size);
+ QByteArray INSTALLER_EXPORT retrieveCompressedData(QIODevice *in, qint64 size);
+}
+
+namespace QInstallerCreator {
+class Component;
+
+class INSTALLER_EXPORT Archive : public QIODevice
+{
+ Q_OBJECT
+public:
+ explicit Archive(const QString &path);
+ Archive(const QByteArray &name, const QByteArray &data);
+ Archive(const QByteArray &name, const QSharedPointer<QFile> &device, const Range<qint64> &segment);
+ ~Archive();
+
+ bool open(OpenMode mode);
+ void close();
+
+ bool seek(qint64 pos);
+ qint64 size() const;
+
+ bool createZippedFile();
+ bool isZippedDirectory() const;
+ bool copy(const QString &name);
+
+ QByteArray name() const;
+ void setName(const QByteArray &name);
+
+protected:
+ qint64 readData(char *data, qint64 maxSize);
+ qint64 writeData(const char *data, qint64 maxSize);
+
+ Range< qint64 > binarySegment() const;
+
+private:
+ //used when when reading from the installer
+ QSharedPointer<QFile> m_device;
+ const Range<qint64> m_segment;
+
+ //used when creating the installer, archive input file
+ QFile m_inputFile;
+ const bool m_isTempFile;
+ const QString m_path;
+ QByteArray m_name;
+};
+
+class INSTALLER_EXPORT Component
+{
+ Q_DECLARE_TR_FUNCTIONS(Component)
+
+public:
+ virtual ~Component();
+
+ static Component readFromIndexEntry(const QSharedPointer<QFile> &dev, qint64 offset);
+ void writeIndexEntry(QIODevice *dev, qint64 offset) const;
+
+ void writeData(QIODevice *dev, qint64 positionOffset) const;
+ void readData(const QSharedPointer<QFile> &dev, qint64 offset);
+
+ QByteArray name() const;
+ void setName(const QByteArray &ba);
+
+ QString dataDirectory() const;
+ void setDataDirectory(const QString &path);
+
+ Range<qint64> binarySegment() const;
+ void setBinarySegment(const Range<qint64> &r);
+
+ void appendArchive(const QSharedPointer<Archive> &archive);
+ QSharedPointer<Archive> archiveByName(const QByteArray &name) const;
+ QVector< QSharedPointer<Archive> > archives() const;
+
+ bool operator<(const Component &other) const;
+ bool operator==(const Component &other) const;
+
+private:
+ QByteArray m_name;
+ QVector<QSharedPointer<Archive> > m_archives;
+ mutable Range<qint64> m_binarySegment;
+ QString m_dataDirectory;
+};
+
+
+class INSTALLER_EXPORT ComponentIndex
+{
+public:
+ ComponentIndex();
+ static ComponentIndex read(const QSharedPointer<QFile> &dev, qint64 offset);
+ void writeIndex(QIODevice *dev, qint64 offset) const;
+ void writeComponentData(QIODevice *dev, qint64 offset) const;
+ Component componentByName(const QByteArray &name) const;
+ void insertComponent(const Component &name);
+ void removeComponent(const QByteArray &name);
+ QVector<Component> components() const;
+ int componentCount() const;
+
+private:
+ QHash<QByteArray, Component> m_components;
+};
+}
+
+namespace QInstaller {
+
+struct BinaryLayout
+{
+ QVector<Range<qint64> > metadataResourceSegments;
+ qint64 operationsStart;
+ qint64 operationsEnd;
+ qint64 resourceCount;
+ qint64 dataBlockSize;
+ qint64 magicMarker;
+ quint64 magicCookie;
+ qint64 indexSize;
+ qint64 endOfData;
+};
+
+class BinaryContentPrivate : public QSharedData
+{
+public:
+ BinaryContentPrivate(const QString &path);
+ BinaryContentPrivate(const BinaryContentPrivate &other);
+ ~BinaryContentPrivate();
+
+ qint64 m_magicMarker;
+ qint64 m_dataBlockStart;
+
+ QSharedPointer<QFile> m_appBinary;
+ QSharedPointer<QFile> m_binaryDataFile;
+
+ QList<Operation *> m_performedOperations;
+ QList<QPair<QString, QString> > m_performedOperationsData;
+
+ QVector<const uchar *> m_resourceMappings;
+ QVector<Range<qint64> > m_metadataResourceSegments;
+
+ QInstallerCreator::ComponentIndex m_componentIndex;
+ QInstallerCreator::BinaryFormatEngineHandler m_binaryFormatEngineHandler;
+};
+
+class INSTALLER_EXPORT BinaryContent
+{
+ explicit BinaryContent(const QString &path);
+
+public:
+ virtual ~BinaryContent();
+
+ static BinaryContent readAndRegisterFromApplicationFile();
+ static BinaryContent readAndRegisterFromBinary(const QString &path);
+
+ static BinaryContent readFromApplicationFile();
+ static BinaryContent readFromBinary(const QString &path);
+
+ static BinaryLayout readBinaryLayout(QIODevice *const file, qint64 cookiePos);
+
+ int registerPerformedOperations();
+ OperationList performedOperations() const;
+
+ qint64 magicMarker() const;
+ int registerEmbeddedQResources();
+ QInstallerCreator::ComponentIndex componentIndex() const;
+
+private:
+ static void readBinaryData(BinaryContent &content, const QSharedPointer<QFile> &file,
+ const BinaryLayout &layout);
+
+private:
+ QSharedDataPointer<BinaryContentPrivate> d;
+};
+
+}
+
+#endif // BINARYFORMAT_H
diff --git a/installerbuilder/libinstaller/binaryformatengine.cpp b/installerbuilder/libinstaller/binaryformatengine.cpp
new file mode 100644
index 000000000..05affaf4b
--- /dev/null
+++ b/installerbuilder/libinstaller/binaryformatengine.cpp
@@ -0,0 +1,297 @@
+/**************************************************************************
+**
+** This file is part of Installer Framework
+**
+** Copyright (c) 2011-2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "binaryformatengine.h"
+
+using namespace QInstallerCreator;
+
+namespace {
+
+class StringListIterator : public QAbstractFileEngineIterator
+{
+public:
+ StringListIterator( const QStringList &list, QDir::Filters filters, const QStringList &nameFilters)
+ : QAbstractFileEngineIterator(filters, nameFilters),
+ list(list),
+ index(-1)
+ {
+ }
+
+ bool hasNext() const
+ {
+ return index < list.size() - 1;
+ }
+
+ QString next()
+ {
+ if(!hasNext())
+ return QString();
+ ++index;
+ return currentFilePath();
+ }
+
+ QString currentFileName() const
+ {
+ return index < 0 ? QString() : list[index];
+ }
+
+private:
+ const QStringList list;
+ int index;
+};
+
+} // anon namespace
+
+BinaryFormatEngine::BinaryFormatEngine(const ComponentIndex &index, const QString &fileName)
+ : m_index(index)
+ , m_hasComponent(false)
+ , m_hasArchive(false)
+ , m_archive(0)
+{
+ setArchive(fileName);
+}
+
+BinaryFormatEngine::~BinaryFormatEngine()
+{
+}
+
+void BinaryFormatEngine::setArchive(const QString &file)
+{
+ m_fileNamePath = file;
+
+ static const QChar sep = QLatin1Char('/');
+ static const QString prefix = QLatin1String("installer://");
+ Q_ASSERT(file.toLower().startsWith(prefix));
+
+ // cut the prefix
+ QString path = file.mid(prefix.length());
+ while (path.endsWith(sep))
+ path.chop(1);
+
+ QString arch;
+ const QString comp = path.section(sep, 0, 0);
+ m_hasComponent = !comp.isEmpty();
+ m_hasArchive = path.contains(sep);
+ if (m_hasArchive)
+ arch = path.section(sep, 1, 1);
+
+ m_component = m_index.componentByName(comp.toUtf8());
+ m_archive = m_component.archiveByName(arch.toUtf8());
+}
+
+/**
+ * \reimp
+ */
+void BinaryFormatEngine::setFileName(const QString &file)
+{
+ setArchive(file);
+}
+
+/**
+ * \reimp
+ */
+bool BinaryFormatEngine::close()
+{
+ if (m_archive == 0)
+ return false;
+
+ const bool result = m_archive->isOpen();
+ m_archive->close();
+ return result;
+}
+
+/**
+ * \reimp
+ */
+bool BinaryFormatEngine::open(QIODevice::OpenMode mode)
+{
+ return m_archive == 0 ? false : m_archive->open(mode);
+}
+
+/**
+ * \reimp
+ */
+qint64 BinaryFormatEngine::pos() const
+{
+ return m_archive == 0 ? 0 : m_archive->pos();
+}
+
+/**
+ * \reimp
+ */
+qint64 BinaryFormatEngine::read(char *data, qint64 maxlen)
+{
+ return m_archive == 0 ? -1 : m_archive->read(data, maxlen);
+}
+
+/**
+ * \reimp
+ */
+bool BinaryFormatEngine::seek(qint64 offset)
+{
+ return m_archive == 0 ? false : m_archive->seek(offset);
+}
+
+/**
+ * \reimp
+ */
+QString BinaryFormatEngine::fileName(FileName file) const
+{
+ switch(file) {
+ case BaseName:
+ return m_fileNamePath.section(QChar::fromLatin1('/'), -1, -1, QString::SectionSkipEmpty);
+ case PathName:
+ case AbsolutePathName:
+ case CanonicalPathName:
+ return m_fileNamePath.section(QChar::fromLatin1('/'), 0, -2, QString::SectionSkipEmpty);
+ case DefaultName:
+ case AbsoluteName:
+ case CanonicalName:
+ return m_fileNamePath;
+ default:
+ return QString();
+ }
+}
+
+/**
+ * \reimp
+ */
+bool BinaryFormatEngine::copy(const QString &newName)
+{
+ if (QFile::exists(newName))
+ return false;
+
+ QFile target(newName);
+ if (!target.open(QIODevice::WriteOnly))
+ return false;
+
+ qint64 bytesLeft = size();
+ if (!open(QIODevice::ReadOnly))
+ return false;
+
+ char data[4096];
+ while(bytesLeft > 0) {
+ const qint64 len = qMin<qint64>(bytesLeft, 4096);
+ const qint64 bytesRead = read(data, len);
+ if (bytesRead != len) {
+ close();
+ return false;
+ }
+ const qint64 bytesWritten = target.write(data, len);
+ if (bytesWritten != len) {
+ close();
+ return false;
+ }
+ bytesLeft -= len;
+ }
+ close();
+
+ return true;
+}
+
+/**
+ * \reimp
+ */
+QAbstractFileEngine::FileFlags BinaryFormatEngine::fileFlags(FileFlags type) const
+{
+ FileFlags result;
+ if ((type & FileType) && m_archive != 0)
+ result |= FileType;
+ if ((type & DirectoryType) && !m_hasArchive)
+ result |= DirectoryType;
+ if ((type & ExistsFlag) && m_hasArchive && m_archive != 0)
+ result |= ExistsFlag;
+ if ((type & ExistsFlag) && !m_hasArchive && !m_component.name().isEmpty())
+ result |= ExistsFlag;
+
+ return result;
+}
+
+/**
+ * \reimp
+ */
+QAbstractFileEngineIterator *BinaryFormatEngine::beginEntryList(QDir::Filters filters, const QStringList &filterNames)
+{
+ const QStringList entries = entryList(filters, filterNames);
+ return new StringListIterator(entries, filters, filterNames);
+}
+
+/**
+ * \reimp
+ */
+QStringList BinaryFormatEngine::entryList(QDir::Filters filters, const QStringList &filterNames) const
+{
+ if (m_hasArchive)
+ return QStringList();
+
+ QStringList result;
+
+ if (m_hasComponent && (filters & QDir::Files)) {
+ const QVector< QSharedPointer<Archive> > archives = m_component.archives();
+ foreach (const QSharedPointer<Archive> &i, archives)
+ result.push_back(QString::fromUtf8(i->name()));
+ }
+ else if (!m_hasComponent && (filters & QDir::Dirs)) {
+ const QVector<Component> components = m_index.components();
+ foreach (const Component &i, components)
+ result.push_back(QString::fromUtf8(i.name()));
+ }
+
+ if (filterNames.isEmpty())
+ return result;
+
+ QList<QRegExp> regexps;
+ foreach (const QString &i, filterNames)
+ regexps.push_back(QRegExp(i, Qt::CaseInsensitive, QRegExp::Wildcard));
+
+ QStringList entries;
+ foreach (const QString &i, result) {
+ bool matched = false;
+ foreach (const QRegExp &reg, regexps) {
+ matched = reg.exactMatch(i);
+ if (matched)
+ break;
+ }
+ if (matched)
+ entries.push_back(i);
+ }
+
+ return entries;
+}
+
+/**
+ * \reimp
+ */
+qint64 BinaryFormatEngine::size() const
+{
+ return m_archive == 0 ? 0 : m_archive->size();
+}
diff --git a/installerbuilder/libinstaller/binaryformatengine.h b/installerbuilder/libinstaller/binaryformatengine.h
new file mode 100644
index 000000000..d5ac18a45
--- /dev/null
+++ b/installerbuilder/libinstaller/binaryformatengine.h
@@ -0,0 +1,78 @@
+/**************************************************************************
+**
+** This file is part of Installer Framework
+**
+** Copyright (c) 2010-2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef BINARYFORMATENGINE_H
+#define BINARYFORMATENGINE_H
+
+#include <QAbstractFileEngine>
+
+#include "binaryformat.h"
+
+namespace QInstallerCreator {
+
+class BinaryFormatEngine : public QAbstractFileEngine
+{
+public:
+ BinaryFormatEngine(const ComponentIndex &index, const QString &fileName);
+ ~BinaryFormatEngine();
+
+ void setFileName(const QString &file);
+
+ Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames);
+
+ bool copy(const QString &newName);
+ bool close();
+ bool open(QIODevice::OpenMode mode);
+ qint64 pos() const;
+ qint64 read(char *data, qint64 maxlen);
+ bool seek(qint64 offset);
+ qint64 size() const;
+
+ QString fileName(FileName file = DefaultName) const;
+ FileFlags fileFlags(FileFlags type = FileInfoAll) const;
+ QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const;
+
+protected:
+ void setArchive(const QString &file);
+
+private:
+ const ComponentIndex m_index;
+ bool m_hasComponent;
+ bool m_hasArchive;
+ Component m_component;
+ QSharedPointer<Archive> m_archive;
+ QString m_fileNamePath;
+};
+
+} // namespace QInstallerCreator
+
+#endif
diff --git a/installerbuilder/libinstaller/binaryformatenginehandler.cpp b/installerbuilder/libinstaller/binaryformatenginehandler.cpp
new file mode 100644
index 000000000..2b1bbcad4
--- /dev/null
+++ b/installerbuilder/libinstaller/binaryformatenginehandler.cpp
@@ -0,0 +1,116 @@
+/**************************************************************************
+**
+** This file is part of Installer Framework
+**
+** Copyright (c) 2011-2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "binaryformatenginehandler.h"
+#include "binaryformatengine.h"
+#include "binaryformat.h"
+
+#include <QDebug>
+#include <QFile>
+#include <QFSFileEngine>
+
+using namespace QInstallerCreator;
+
+static BinaryFormatEngineHandler *s_instance = 0;
+
+
+class BinaryFormatEngineHandler::Private
+{
+public:
+ Private(const ComponentIndex &i)
+ : index(i)
+ {
+ }
+
+ ComponentIndex index;
+};
+
+BinaryFormatEngineHandler::BinaryFormatEngineHandler(const ComponentIndex &index)
+ : d(new Private(index))
+{
+ s_instance = this;
+}
+
+BinaryFormatEngineHandler::BinaryFormatEngineHandler(const BinaryFormatEngineHandler &other)
+ : QAbstractFileEngineHandler(),
+ d(new Private(other.d->index))
+{
+ s_instance = this;
+}
+
+BinaryFormatEngineHandler::~BinaryFormatEngineHandler()
+{
+ if (s_instance == this)
+ s_instance = 0;
+ delete d;
+}
+
+void BinaryFormatEngineHandler::setComponentIndex(const ComponentIndex &index)
+{
+ d->index = index;
+}
+
+QAbstractFileEngine *BinaryFormatEngineHandler::create(const QString &fileName) const
+{
+ return fileName.startsWith(QLatin1String("installer://"), Qt::CaseInsensitive ) ? new BinaryFormatEngine(d->index, fileName) : 0;
+}
+
+BinaryFormatEngineHandler *BinaryFormatEngineHandler::instance()
+{
+ return s_instance;
+}
+
+void BinaryFormatEngineHandler::registerArchive(const QString &pathName, const QString &archive)
+{
+ static const QChar sep = QChar::fromLatin1('/');
+ static const QString prefix = QString::fromLatin1("installer://");
+ Q_ASSERT(pathName.toLower().startsWith(prefix));
+
+ // cut the prefix
+ QString path = pathName.mid(prefix.length());
+ while (path.endsWith(sep))
+ path.chop(1);
+
+ const QString comp = path.section(sep, 0, 0);
+ const QString archiveName = path.section(sep, 1, 1);
+
+ Component c = d->index.componentByName(comp.toUtf8());
+ if (c.name().isEmpty())
+ c.setName(comp.toUtf8());
+
+ QList< QSharedPointer<Archive> > registered;
+ QSharedPointer<Archive> newArchive(new Archive(archive));
+ newArchive->setName(archiveName.toUtf8());
+ registered.push_back(newArchive);
+ c.appendArchive(newArchive);
+ d->index.insertComponent(c);
+}
diff --git a/installerbuilder/libinstaller/binaryformatenginehandler.h b/installerbuilder/libinstaller/binaryformatenginehandler.h
new file mode 100644
index 000000000..82269eda9
--- /dev/null
+++ b/installerbuilder/libinstaller/binaryformatenginehandler.h
@@ -0,0 +1,66 @@
+/**************************************************************************
+**
+** This file is part of Installer Framework
+**
+** Copyright (c) 2010-2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef BINARYFORMATENGINEHANDLER_H
+#define BINARYFORMATENGINEHANDLER_H
+
+#include "installer_global.h"
+
+#include <QtCore/QAbstractFileEngineHandler>
+
+
+namespace QInstallerCreator {
+
+class ComponentIndex;
+
+class INSTALLER_EXPORT BinaryFormatEngineHandler : public QAbstractFileEngineHandler
+{
+public:
+ explicit BinaryFormatEngineHandler(const ComponentIndex &index);
+ BinaryFormatEngineHandler(const BinaryFormatEngineHandler &other);
+ ~BinaryFormatEngineHandler();
+ QAbstractFileEngine *create(const QString &fileName) const;
+
+ void setComponentIndex(const ComponentIndex &index);
+
+ static BinaryFormatEngineHandler *instance();
+
+ void registerArchive(const QString &fileName, const QString &path);
+
+private:
+ class Private;
+ Private *const d;
+};
+
+}
+
+#endif
diff --git a/installerbuilder/libinstaller/component.cpp b/installerbuilder/libinstaller/component.cpp
index 39021fab0..4c57e981b 100644
--- a/installerbuilder/libinstaller/component.cpp
+++ b/installerbuilder/libinstaller/component.cpp
@@ -29,11 +29,10 @@
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
-
#include "component.h"
-#include "common/errors.h"
-#include "common/fileutils.h"
+#include "errors.h"
+#include "fileutils.h"
#include "fsengineclient.h"
#include "lib7z_facade.h"
#include "packagemanagercore.h"
diff --git a/installerbuilder/libinstaller/createdesktopentryoperation.cpp b/installerbuilder/libinstaller/createdesktopentryoperation.cpp
index da2a253c2..feda777cc 100644
--- a/installerbuilder/libinstaller/createdesktopentryoperation.cpp
+++ b/installerbuilder/libinstaller/createdesktopentryoperation.cpp
@@ -29,18 +29,18 @@
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
-
#include "createdesktopentryoperation.h"
-#include "common/errors.h"
-#include "common/fileutils.h"
-
-#include <QDir>
-#include <QFile>
-#include <QFileInfo>
-#include <QTextStream>
-#include <QProcess>
+
+#include "errors.h"
+#include "fileutils.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QTextStream>
+#include <QtCore/QProcess>
#if QT_VERSION >= 0x040600
-#include <QProcessEnvironment>
+# include <QtCore/QProcessEnvironment>
#endif
using namespace QInstaller;
diff --git a/installerbuilder/libinstaller/createlocalrepositoryoperation.cpp b/installerbuilder/libinstaller/createlocalrepositoryoperation.cpp
index 5e4af2fb1..a0527f432 100644
--- a/installerbuilder/libinstaller/createlocalrepositoryoperation.cpp
+++ b/installerbuilder/libinstaller/createlocalrepositoryoperation.cpp
@@ -31,14 +31,15 @@
**************************************************************************/
#include "createlocalrepositoryoperation.h"
-#include "common/binaryformat.h"
-#include "common/errors.h"
-#include "common/fileutils.h"
+#include "binaryformat.h"
+#include "errors.h"
+#include "fileutils.h"
#include "copydirectoryoperation.h"
-#include "kdupdaterupdateoperations.h"
#include "lib7z_facade.h"
#include "packagemanagercore.h"
+#include "kdupdaterupdateoperations.h"
+
#include <QtCore/QDir>
#include <QtCore/QDirIterator>
diff --git a/installerbuilder/libinstaller/createshortcutoperation.cpp b/installerbuilder/libinstaller/createshortcutoperation.cpp
index 7d553792f..bd0608233 100644
--- a/installerbuilder/libinstaller/createshortcutoperation.cpp
+++ b/installerbuilder/libinstaller/createshortcutoperation.cpp
@@ -29,24 +29,24 @@
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
+#include "createshortcutoperation.h"
-#include <kdupdaterapplication.h>
-#include <kdupdaterpackagesinfo.h>
+#include "errors.h"
+#include "fileutils.h"
-#include "createshortcutoperation.h"
-#include "common/errors.h"
-#include "common/fileutils.h"
+#include "kdupdaterapplication.h"
+#include "kdupdaterpackagesinfo.h"
-#include <QDir>
-#include <QFileInfo>
-#include <QTemporaryFile>
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+#include <QtCore/QTemporaryFile>
#include <algorithm>
#include <cerrno>
#ifdef Q_WS_WIN
-#include <windows.h>
-#include <shlobj.h>
+# include <windows.h>
+# include <shlobj.h>
#endif
using namespace QInstaller;
diff --git a/installerbuilder/libinstaller/downloadarchivesjob.cpp b/installerbuilder/libinstaller/downloadarchivesjob.cpp
index 19417c3e6..f33108442 100644
--- a/installerbuilder/libinstaller/downloadarchivesjob.cpp
+++ b/installerbuilder/libinstaller/downloadarchivesjob.cpp
@@ -29,16 +29,15 @@
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
-
#include "downloadarchivesjob.h"
-#include "common/binaryformatenginehandler.h"
+#include "binaryformatenginehandler.h"
#include "component.h"
#include "messageboxhandler.h"
#include "packagemanagercore.h"
-#include <kdupdaterfiledownloader.h>
-#include <kdupdaterfiledownloaderfactory.h>
+#include "kdupdaterfiledownloader.h"
+#include "kdupdaterfiledownloaderfactory.h"
#include <QtCore/QFile>
#include <QtCore/QTimerEvent>
diff --git a/installerbuilder/libinstaller/errors.h b/installerbuilder/libinstaller/errors.h
new file mode 100644
index 000000000..09ad52b14
--- /dev/null
+++ b/installerbuilder/libinstaller/errors.h
@@ -0,0 +1,59 @@
+/**************************************************************************
+**
+** This file is part of Installer Framework
+**
+** Copyright (c) 2010-2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef ERRORS_H
+#define ERRORS_H
+
+#include <QtCore/QDebug>
+#include <QtCore/QString>
+
+#include <stdexcept>
+
+namespace QInstaller {
+
+class Error : public std::runtime_error
+{
+public:
+ explicit Error(const QString &message)
+ : std::runtime_error(message.toStdString())
+ , m_message (message) { qWarning() << "Error-Exception:" << message; }
+ virtual ~Error() throw() {}
+
+ QString message() const { return m_message; }
+
+private:
+ QString m_message;
+};
+
+}
+
+#endif // ERRORS_H
diff --git a/installerbuilder/libinstaller/extractarchiveoperation_p.h b/installerbuilder/libinstaller/extractarchiveoperation_p.h
index bbb750630..25c38e61e 100644
--- a/installerbuilder/libinstaller/extractarchiveoperation_p.h
+++ b/installerbuilder/libinstaller/extractarchiveoperation_p.h
@@ -29,15 +29,14 @@
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
-
#ifndef EXTRACTARCHIVEOPERATION_P_H
#define EXTRACTARCHIVEOPERATION_P_H
#include "extractarchiveoperation.h"
+#include "fileutils.h"
#include "lib7z_facade.h"
#include "packagemanagercore.h"
-#include "common/fileutils.h"
#include <QtCore/QDir>
#include <QtCore/QFile>
diff --git a/installerbuilder/libinstaller/fileutils.cpp b/installerbuilder/libinstaller/fileutils.cpp
new file mode 100644
index 000000000..b07b5b08f
--- /dev/null
+++ b/installerbuilder/libinstaller/fileutils.cpp
@@ -0,0 +1,507 @@
+/**************************************************************************
+**
+** This file is part of Installer Framework
+**
+** Copyright (c) 2011-2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+#include "fileutils.h"
+
+#include <errors.h>
+
+#include <QtCore/QDateTime>
+#include <QtCore/QDir>
+#include <QtCore/QDirIterator>
+#include <QtCore/QEventLoop>
+#include <QtCore/QTemporaryFile>
+#include <QtCore/QThread>
+#include <QtCore/QUrl>
+
+#include <errno.h>
+
+using namespace QInstaller;
+
+
+// -- TempDirDeleter
+
+TempDirDeleter::TempDirDeleter(const QString &path)
+{
+ m_paths.insert(path);
+}
+
+TempDirDeleter::TempDirDeleter(const QStringList &paths)
+ : m_paths(paths.toSet())
+{
+}
+
+TempDirDeleter::~TempDirDeleter()
+{
+ releaseAndDeleteAll();
+}
+
+QStringList TempDirDeleter::paths() const
+{
+ return m_paths.toList();
+}
+
+void TempDirDeleter::add(const QString &path)
+{
+ m_paths.insert(path);
+}
+
+void TempDirDeleter::add(const QStringList &paths)
+{
+ m_paths += paths.toSet();
+}
+
+void TempDirDeleter::releaseAll()
+{
+ m_paths.clear();
+}
+
+void TempDirDeleter::release(const QString &path)
+{
+ m_paths.remove(path);
+}
+
+void TempDirDeleter::passAndReleaseAll(TempDirDeleter &tdd)
+{
+ tdd.m_paths = m_paths;
+ releaseAll();
+}
+
+void TempDirDeleter::passAndRelease(TempDirDeleter &tdd, const QString &path)
+{
+ tdd.add(path);
+ release(path);
+}
+
+void TempDirDeleter::releaseAndDeleteAll()
+{
+ foreach (const QString &path, m_paths)
+ releaseAndDelete(path);
+}
+
+void TempDirDeleter::releaseAndDelete(const QString &path)
+{
+ if (m_paths.contains(path)) {
+ try {
+ m_paths.remove(path);
+ removeDirectory(path);
+ } catch (const Error &e) {
+ qCritical() << Q_FUNC_INFO << "Exception caught:" << e.message();
+ } catch (...) {
+ qCritical() << Q_FUNC_INFO << "Unknown exception caught.";
+ }
+ }
+}
+
+
+// -- read, write operations
+
+bool QInstaller::isLocalUrl(const QUrl &url)
+{
+ return url.scheme().isEmpty() || url.scheme().toLower() == QLatin1String("file");
+}
+
+QString QInstaller::pathFromUrl(const QUrl &url)
+{
+ if (isLocalUrl(url))
+ return url.toLocalFile();
+ const QString str = url.toString();
+ if (url.scheme() == QLatin1String("resource"))
+ return str.mid(QString::fromLatin1("resource").length());
+ return str;
+}
+
+void QInstaller::openForRead(QIODevice *dev, const QString &name)
+{
+ Q_ASSERT(dev);
+ if (!dev->open(QIODevice::ReadOnly))
+ throw Error(QObject::tr("Cannot open file %1 for reading: %2").arg(name, dev->errorString()));
+}
+
+void QInstaller::openForWrite(QIODevice *dev, const QString &name)
+{
+ Q_ASSERT(dev);
+ if (!dev->open(QIODevice::WriteOnly))
+ throw Error(QObject::tr("Cannot open file %1 for writing: %2").arg(name, dev->errorString()));
+}
+
+void QInstaller::openForAppend(QIODevice *dev, const QString &name)
+{
+ Q_ASSERT(dev);
+ if (!dev->open(QIODevice::ReadWrite | QIODevice::Append))
+ throw Error(QObject::tr("Cannot open file %1 for writing: %2").arg(name, dev->errorString()));
+}
+
+qint64 QInstaller::blockingWrite(QIODevice *out, const char *buffer, qint64 size)
+{
+ qint64 left = size;
+ while (left > 0) {
+ const qint64 n = out->write(buffer, left);
+ if (n < 0) {
+ throw Error(QObject::tr("Write failed after %1 bytes: %2").arg(QString::number(size-left),
+ out->errorString()));
+ }
+ left -= n;
+ }
+ return size;
+}
+
+qint64 QInstaller::blockingWrite(QIODevice *out, const QByteArray &ba)
+{
+ return blockingWrite(out, ba.constData(), ba.size());
+}
+
+qint64 QInstaller::blockingRead(QIODevice *in, char *buffer, qint64 size)
+{
+ if (in->atEnd())
+ return 0;
+ qint64 left = size;
+ while (left > 0) {
+ const qint64 n = in->read(buffer, left);
+ if (n < 0) {
+ throw Error(QObject::tr("Read failed after %1 bytes: %2").arg(QString::number(size-left),
+ in->errorString()));
+ }
+ left -= n;
+ buffer += n;
+ }
+ return size;
+}
+
+void QInstaller::blockingCopy(QIODevice *in, QIODevice *out, qint64 size)
+{
+ static const qint64 blockSize = 4096;
+ QByteArray ba(blockSize, '\0');
+ qint64 actual = qMin(blockSize, size);
+ while (actual > 0) {
+ blockingRead(in, ba.data(), actual);
+ blockingWrite(out, ba.constData(), actual);
+ size -= actual;
+ actual = qMin(blockSize, size);
+ }
+}
+
+void QInstaller::removeFiles(const QString &path, bool ignoreErrors)
+{
+ const QFileInfoList entries = QDir(path).entryInfoList(QDir::AllEntries | QDir::Hidden);
+ foreach (const QFileInfo &fi, entries) {
+ if (fi.isSymLink() || fi.isFile()) {
+ QFile f(fi.filePath());
+ if (!f.remove() && !ignoreErrors)
+ throw Error(QObject::tr("Could not remove file %1: %2").arg(f.fileName(), f.errorString()));
+ }
+ }
+}
+
+void QInstaller::removeDirectory(const QString &path, bool ignoreErrors)
+{
+ if (path.isEmpty()) // QDir("") points to the working directory! We never want to remove that one.
+ return;
+
+ QStringList dirs;
+ QDirIterator it(path, QDir::NoDotAndDotDot | QDir::Dirs | QDir::NoSymLinks | QDir::Hidden,
+ QDirIterator::Subdirectories);
+ while (it.hasNext()) {
+ it.next();
+ dirs.prepend(it.filePath());
+ removeFiles(dirs.at(0), ignoreErrors);
+ }
+
+ QDir d;
+ dirs.append(path);
+ removeFiles(path, ignoreErrors);
+ foreach (const QString &dir, dirs) {
+ errno = 0;
+ if (d.exists(path) && !d.rmdir(dir) && !ignoreErrors)
+ throw Error(QObject::tr("Could not remove folder %1: %2").arg(dir, QLatin1String(strerror(errno))));
+ }
+}
+
+/*!
+ \internal
+ */
+class RemoveDirectoryThread : public QThread
+{
+public:
+ explicit RemoveDirectoryThread(const QString &path, bool ignoreErrors = false, QObject *parent = 0)
+ : QThread(parent),
+ p(path),
+ ignore(ignoreErrors)
+ {
+ }
+
+ const QString &error() const
+ {
+ return err;
+ }
+
+protected:
+ /*!
+ \reimp
+ */
+ void run()
+ {
+ try {
+ removeDirectory(p, ignore);
+ } catch (const Error &e) {
+ err = e.message();
+ }
+ }
+
+private:
+ QString err;
+ const QString p;
+ const bool ignore;
+};
+
+void QInstaller::removeDirectoryThreaded(const QString &path, bool ignoreErrors)
+{
+ RemoveDirectoryThread thread(path, ignoreErrors);
+ QEventLoop loop;
+ QObject::connect(&thread, SIGNAL(finished()), &loop, SLOT(quit()));
+ thread.start();
+ loop.exec();
+ if (!thread.error().isEmpty())
+ throw Error(thread.error());
+}
+
+void QInstaller::removeSystemGeneratedFiles(const QString &path)
+{
+ if (path.isEmpty())
+ return;
+#if defined Q_WS_MAC
+ QFile::remove(path + QLatin1String("/.DS_Store"));
+#elif defined Q_WS_WIN
+ QFile::remove(path + QLatin1String("/Thumbs.db"));
+#endif
+}
+
+void QInstaller::copyDirectoryContents(const QString &sourceDir, const QString &targetDir)
+{
+ qDebug() << "Copying" << sourceDir << "to" << targetDir;
+ Q_ASSERT(QFileInfo(sourceDir).isDir());
+ Q_ASSERT(!QFileInfo(targetDir).exists() || QFileInfo(targetDir).isDir());
+ if (!QDir().mkpath(targetDir))
+ throw Error(QObject::tr("Could not create folder %1").arg(targetDir));
+
+ QDirIterator it(sourceDir, QDir::NoDotAndDotDot | QDir::AllEntries);
+ while (it.hasNext()) {
+ const QFileInfo i(it.next());
+ if (i.isDir()) {
+ copyDirectoryContents(QDir(sourceDir).absoluteFilePath(i.fileName()),
+ QDir(targetDir).absoluteFilePath(i.fileName()));
+ } else {
+ QFile f(i.filePath());
+ const QString target = QDir(targetDir).absoluteFilePath(i.fileName());
+ if (!f.copy(target)) {
+ throw Error(QObject::tr("Could not copy file from %1 to %2: %3").arg(f.fileName(), target,
+ f.errorString()));
+ }
+ }
+ }
+}
+
+void QInstaller::moveDirectoryContents(const QString &sourceDir, const QString &targetDir)
+{
+ qDebug() << "Moving" << sourceDir << "to" << targetDir;
+ Q_ASSERT(QFileInfo(sourceDir).isDir());
+ Q_ASSERT(!QFileInfo(targetDir).exists() || QFileInfo(targetDir).isDir());
+ if (!QDir().mkpath(targetDir))
+ throw Error(QObject::tr("Could not create folder %1").arg(targetDir));
+
+ QDirIterator it(sourceDir, QDir::NoDotAndDotDot | QDir::AllEntries);
+ while (it.hasNext()) {
+ const QFileInfo i(it.next());
+ if (i.isDir()) {
+ moveDirectoryContents(QDir(sourceDir).absoluteFilePath(i.fileName()),
+ QDir(targetDir).absoluteFilePath(i.fileName()));
+ } else {
+ QFile f(i.filePath());
+ const QString target = QDir(targetDir).absoluteFilePath(i.fileName());
+ if (!f.rename(target)) {
+ throw Error(QObject::tr("Could not move file from %1 to %2: %3").arg(f.fileName(), target,
+ f.errorString()));
+ }
+ }
+ }
+}
+
+void QInstaller::mkdir(const QString &path)
+{
+ errno = 0;
+ if (!QDir().mkdir(QFileInfo(path).absoluteFilePath())) {
+ throw Error(QObject::tr("Could not create folder %1: %2").arg(path,
+ QString::fromLocal8Bit(strerror(errno))));
+ }
+}
+
+void QInstaller::mkpath(const QString &path)
+{
+ errno = 0;
+ if (!QDir().mkpath(QFileInfo(path).absoluteFilePath())) {
+ throw Error(QObject::tr("Could not create folder %1: %2").arg(path,
+ QString::fromLocal8Bit(strerror(errno))));
+ }
+}
+
+QString QInstaller::generateTemporaryFileName(const QString &templ)
+{
+ if (templ.isEmpty()) {
+ QTemporaryFile f;
+ if (!f.open())
+ throw Error(QObject::tr("Could not open temporary file: %1").arg(f.errorString()));
+ return f.fileName();
+ }
+
+ static const QString characters = QLatin1String("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890");
+ QString suffix;
+ qsrand(qrand() * QDateTime::currentDateTime().toTime_t());
+ for (int i = 0; i < 5; ++i)
+ suffix += characters[qrand() % characters.length()];
+
+ const QString tmp = QLatin1String("%1.tmp.%2.%3");
+ int count = 1;
+ while (QFile::exists(tmp.arg(templ, suffix).arg(count)))
+ ++count;
+
+ QFile f(tmp.arg(templ, suffix).arg(count));
+ if (!f.open(QIODevice::WriteOnly))
+ throw Error(QObject::tr("Could not open temporary file for template %1: %2").arg(templ, f.errorString()));
+ f.remove();
+ return f.fileName();
+}
+
+QString QInstaller::createTemporaryDirectory(const QString &templ)
+{
+ const QString t = QDir::tempPath() + QLatin1String("/") + templ + QLatin1String("XXXXXX");
+ QTemporaryFile f(t);
+ if (!f.open())
+ throw Error(QObject::tr("Could not create temporary folder for template %1: %2").arg(t, f.errorString()));
+ const QString path = f.fileName() + QLatin1String("meta");
+ qDebug() << "Creating meta data directory at" << path;
+
+ QInstaller::mkpath(path);
+ return path;
+}
+
+#ifdef Q_WS_WIN
+#include <windows.h>
+
+#pragma pack(push)
+#pragma pack(2)
+
+typedef struct {
+ BYTE bWidth; // Width, in pixels, of the image
+ BYTE bHeight; // Height, in pixels, of the image
+ BYTE bColorCount; // Number of colors in image (0 if >=8bpp)
+ BYTE bReserved; // Reserved
+ WORD wPlanes; // Color Planes
+ WORD wBitCount; // Bits per pixel
+ DWORD dwBytesInRes; // how many bytes in this resource?
+ DWORD dwImageOffset; // the ID
+} ICONDIRENTRY;
+
+typedef struct {
+ WORD idReserved; // Reserved (must be 0)
+ WORD idType; // Resource type (1 for icons)
+ WORD idCount; // How many images?
+ ICONDIRENTRY idEntries[1]; // The entries for each image
+} ICONDIR;
+
+typedef struct {
+ BYTE bWidth; // Width, in pixels, of the image
+ BYTE bHeight; // Height, in pixels, of the image
+ BYTE bColorCount; // Number of colors in image (0 if >=8bpp)
+ BYTE bReserved; // Reserved
+ WORD wPlanes; // Color Planes
+ WORD wBitCount; // Bits per pixel
+ DWORD dwBytesInRes; // how many bytes in this resource?
+ WORD nID; // the ID
+} GRPICONDIRENTRY, *LPGRPICONDIRENTRY;
+
+typedef struct {
+ WORD idReserved; // Reserved (must be 0)
+ WORD idType; // Resource type (1 for icons)
+ WORD idCount; // How many images?
+ GRPICONDIRENTRY idEntries[1]; // The entries for each image
+} GRPICONDIR, *LPGRPICONDIR;
+
+
+#pragma pack(pop)
+
+void QInstaller::setApplicationIcon(const QString &application, const QString &icon)
+{
+ wchar_t* const path = new wchar_t[application.length() + 1];
+ QDir::toNativeSeparators(application).toWCharArray(path);
+ path[application.length()] = 0;
+
+ HANDLE updateRes = BeginUpdateResource(path, false);
+ delete[] path;
+
+ QFile iconFile(icon);
+ if (!iconFile.open(QIODevice::ReadOnly))
+ return;
+
+ QByteArray temp = iconFile.readAll();
+
+ ICONDIR* ig = reinterpret_cast< ICONDIR* >(temp.data());
+
+ DWORD newSize = sizeof(GRPICONDIR) + sizeof(GRPICONDIRENTRY) * (ig->idCount - 1);
+ GRPICONDIR* newDir = reinterpret_cast< GRPICONDIR* >(new char[newSize]);
+ newDir->idReserved = ig->idReserved;
+ newDir->idType = ig->idType;
+ newDir->idCount = ig->idCount;
+
+ for (int i = 0; i < ig->idCount; ++i) {
+ char* temp1 = temp.data() + ig->idEntries[i].dwImageOffset;
+ DWORD size1 = ig->idEntries[i].dwBytesInRes;
+
+ newDir->idEntries[i].bWidth = ig->idEntries[i].bWidth;
+ newDir->idEntries[i].bHeight = ig->idEntries[i].bHeight;
+ newDir->idEntries[i].bColorCount = ig->idEntries[i].bColorCount;
+ newDir->idEntries[i].bReserved = ig->idEntries[i].bReserved;
+ newDir->idEntries[i].wPlanes = ig->idEntries[i].wPlanes;
+ newDir->idEntries[i].wBitCount = ig->idEntries[i].wBitCount;
+ newDir->idEntries[i].dwBytesInRes = ig->idEntries[i].dwBytesInRes;
+ newDir->idEntries[i].nID = i + 1;
+
+ UpdateResource(updateRes, RT_ICON, MAKEINTRESOURCE(i + 1),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), temp1, size1);
+ }
+
+ UpdateResource(updateRes, RT_GROUP_ICON, L"IDI_ICON1", MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), newDir
+ , newSize);
+
+ delete [] newDir;
+
+ EndUpdateResource(updateRes, false);
+}
+
+#endif
diff --git a/installerbuilder/libinstaller/fileutils.h b/installerbuilder/libinstaller/fileutils.h
new file mode 100644
index 000000000..4e634a210
--- /dev/null
+++ b/installerbuilder/libinstaller/fileutils.h
@@ -0,0 +1,114 @@
+/**************************************************************************
+**
+** This file is part of Installer Framework**
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).*
+**
+** Contact: Nokia Corporation qt-info@nokia.com**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception version
+** 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you are unsure which license is appropriate for your use, please contact
+** (qt-info@nokia.com).
+**
+**************************************************************************/
+#ifndef QINSTALLER_FILEUTILS_H
+#define QINSTALLER_FILEUTILS_H
+
+#include "installer_global.h"
+
+#include <QtCore/QSet>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+
+QT_BEGIN_NAMESPACE
+class QByteArray;
+class QIODevice;
+class QUrl;
+QT_END_NAMESPACE
+
+namespace QInstaller {
+class INSTALLER_EXPORT TempDirDeleter
+{
+public:
+ explicit TempDirDeleter(const QString &path);
+ explicit TempDirDeleter(const QStringList &paths = QStringList());
+ ~TempDirDeleter();
+
+ QStringList paths() const;
+
+ void add(const QString &path);
+ void add(const QStringList &paths);
+
+ void releaseAll();
+ void release(const QString &path);
+ void passAndReleaseAll(TempDirDeleter &tdd);
+ void passAndRelease(TempDirDeleter &tdd, const QString &path);
+
+ void releaseAndDeleteAll();
+ void releaseAndDelete(const QString &path);
+
+private:
+ Q_DISABLE_COPY(TempDirDeleter)
+ QSet<QString> m_paths;
+};
+
+ void INSTALLER_EXPORT openForRead(QIODevice *dev, const QString &name);
+ void INSTALLER_EXPORT openForWrite(QIODevice *dev, const QString &name);
+ void INSTALLER_EXPORT openForAppend(QIODevice *dev, const QString &name);
+
+ qint64 INSTALLER_EXPORT blockingRead(QIODevice *in, char *buffer, qint64 size);
+ void INSTALLER_EXPORT blockingCopy(QIODevice *in, QIODevice *out, qint64 size);
+ qint64 INSTALLER_EXPORT blockingWrite(QIODevice *out, const char *buffer, qint64 size);
+ qint64 INSTALLER_EXPORT blockingWrite(QIODevice *out, const QByteArray& ba);
+
+ /*!
+ Removes the directory at \a path recursively.
+ @param path The directory to remove
+ @param ignoreErrors if @p true, errors will be silently ignored. Otherwise an exception will be thrown
+ if removing fails.
+
+ @throws QInstaller::Error if the directory cannot be removed and ignoreErrors is @p false
+ */
+ void INSTALLER_EXPORT removeFiles(const QString &path, bool ignoreErrors = false);
+ void INSTALLER_EXPORT removeDirectory(const QString &path, bool ignoreErrors = false);
+ void INSTALLER_EXPORT removeDirectoryThreaded(const QString &path, bool ignoreErrors = false);
+ void INSTALLER_EXPORT removeSystemGeneratedFiles(const QString &path);
+
+ /*!
+ Creates a temporary directory
+ @throws QInstaller::Error if creating the temporary directory fails
+ */
+ QString INSTALLER_EXPORT createTemporaryDirectory(const QString &templ=QString());
+
+ QString INSTALLER_EXPORT generateTemporaryFileName(const QString &templ=QString());
+
+ void INSTALLER_EXPORT moveDirectoryContents(const QString &sourceDir, const QString &targetDir);
+ void INSTALLER_EXPORT copyDirectoryContents(const QString &sourceDir, const QString &targetDir);
+
+ bool INSTALLER_EXPORT isLocalUrl(const QUrl &url);
+ QString INSTALLER_EXPORT pathFromUrl(const QUrl &url);
+
+ void INSTALLER_EXPORT mkdir(const QString &path);
+ void INSTALLER_EXPORT mkpath(const QString &path);
+
+#ifdef Q_WS_WIN
+ /*!
+ Sets the .ico file at \a icon as application icon for \a application.
+ */
+ void INSTALLER_EXPORT setApplicationIcon(const QString &application, const QString &icon);
+#endif
+}
+
+#endif // QINSTALLER_FILEUTILS_H
diff --git a/installerbuilder/libinstaller/fsengineserver.cpp b/installerbuilder/libinstaller/fsengineserver.cpp
index 06c63b283..19539334c 100644
--- a/installerbuilder/libinstaller/fsengineserver.cpp
+++ b/installerbuilder/libinstaller/fsengineserver.cpp
@@ -29,10 +29,9 @@
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
-
#include "fsengineserver.h"
-#include <common/utils.h>
+#include "utils.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QFSFileEngine>
diff --git a/installerbuilder/libinstaller/getrepositoriesmetainfojob.h b/installerbuilder/libinstaller/getrepositoriesmetainfojob.h
index 968e0f129..e44032b48 100644
--- a/installerbuilder/libinstaller/getrepositoriesmetainfojob.h
+++ b/installerbuilder/libinstaller/getrepositoriesmetainfojob.h
@@ -29,22 +29,20 @@
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
-
#ifndef GETREPOSITORIESMETAINFOJOB_H
#define GETREPOSITORIESMETAINFOJOB_H
-#include <kdjob.h>
+#include "fileutils.h"
+#include "installer_global.h"
+#include "repository.h"
+
+#include "kdjob.h"
#include <QtCore/QList>
#include <QtCore/QPointer>
#include <QtCore/QString>
#include <QtCore/QStringList>
-#include <common/fileutils.h>
-#include <common/repository.h>
-
-#include "installer_global.h"
-
namespace KDUpdater {
class FileDownloader;
}
diff --git a/installerbuilder/libinstaller/getrepositorymetainfojob.cpp b/installerbuilder/libinstaller/getrepositorymetainfojob.cpp
index 421db52b8..a72a861a0 100644
--- a/installerbuilder/libinstaller/getrepositorymetainfojob.cpp
+++ b/installerbuilder/libinstaller/getrepositorymetainfojob.cpp
@@ -29,18 +29,17 @@
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
-
#include "getrepositorymetainfojob.h"
#include "constants.h"
-#include "common/errors.h"
+#include "errors.h"
#include "lib7z_facade.h"
#include "messageboxhandler.h"
#include "packagemanagercore_p.h"
#include "qinstallerglobal.h"
-#include <kdupdaterfiledownloader.h>
-#include <kdupdaterfiledownloaderfactory.h>
+#include "kdupdaterfiledownloader.h"
+#include "kdupdaterfiledownloaderfactory.h"
#include <QtCore/QFile>
#include <QtCore/QTimer>
diff --git a/installerbuilder/libinstaller/getrepositorymetainfojob.h b/installerbuilder/libinstaller/getrepositorymetainfojob.h
index c30de9828..aec94603d 100644
--- a/installerbuilder/libinstaller/getrepositorymetainfojob.h
+++ b/installerbuilder/libinstaller/getrepositorymetainfojob.h
@@ -29,22 +29,20 @@
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
-
#ifndef GETREPOSITORYMETAINFOJOB_H
#define GETREPOSITORYMETAINFOJOB_H
-#include <kdjob.h>
+#include "fileutils.h"
+#include "installer_global.h"
+#include "repository.h"
+
+#include "kdjob.h"
#include <QtCore/QPointer>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QThreadPool>
-#include <common/fileutils.h>
-#include <common/repository.h>
-
-#include "installer_global.h"
-
namespace KDUpdater {
class FileDownloader;
}
diff --git a/installerbuilder/libinstaller/init.cpp b/installerbuilder/libinstaller/init.cpp
index f71facf5b..5a464684a 100644
--- a/installerbuilder/libinstaller/init.cpp
+++ b/installerbuilder/libinstaller/init.cpp
@@ -29,7 +29,6 @@
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
-
#include "init.h"
#include "createshortcutoperation.h"
@@ -69,15 +68,15 @@
#include "minimumprogressoperation.h"
#ifdef Q_OS_MAC
- #include "macreplaceinstallnamesoperation.h"
+# include "macreplaceinstallnamesoperation.h"
#endif // Q_OS_MAC
-#include "common/utils.h"
+#include "utils.h"
-#include <kdupdaterupdateoperation.h>
-#include <kdupdaterupdateoperationfactory.h>
-#include <kdupdaterfiledownloader.h>
-#include <kdupdaterfiledownloaderfactory.h>
+#include "kdupdaterupdateoperation.h"
+#include "kdupdaterupdateoperationfactory.h"
+#include "kdupdaterfiledownloader.h"
+#include "kdupdaterfiledownloaderfactory.h"
#include <QtPlugin>
#include <QNetworkProxyFactory>
diff --git a/installerbuilder/libinstaller/installiconsoperation.cpp b/installerbuilder/libinstaller/installiconsoperation.cpp
index 50c8454ba..c2fee33eb 100644
--- a/installerbuilder/libinstaller/installiconsoperation.cpp
+++ b/installerbuilder/libinstaller/installiconsoperation.cpp
@@ -29,19 +29,18 @@
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
-
#include "installiconsoperation.h"
-#include "common/fileutils.h"
+#include "fileutils.h"
#include "packagemanagercore.h"
#include <QtCore/QDir>
#include <QtCore/QDirIterator>
#if QT_VERSION >= 0x040600
-#include <QProcessEnvironment>
+# include <QProcessEnvironment>
#else
-#include <QProcess>
+# include <QProcess>
#endif
using namespace QInstaller;
diff --git a/installerbuilder/libinstaller/libinstaller.pro b/installerbuilder/libinstaller/libinstaller.pro
index 10f58d409..7a01e0a5f 100644
--- a/installerbuilder/libinstaller/libinstaller.pro
+++ b/installerbuilder/libinstaller/libinstaller.pro
@@ -1,11 +1,9 @@
TEMPLATE = lib
TARGET = installer
-DEPENDPATH += . \
- .. \
- ../common
-INCLUDEPATH += . \
- ..
+INCLUDEPATH += . ..
+DEPENDPATH += . .. 3rdparty/kdtools
+
DESTDIR = $$OUT_PWD/../lib
DLLDESTDIR = $$OUT_PWD/../bin
@@ -29,16 +27,16 @@ contains(CONFIG, static): {
include(3rdparty/7zip/7zip.pri)
include(3rdparty/kdtools/kdtools.pri)
-HEADERS += $$PWD/packagemanagercore.h \
- $$PWD/packagemanagercore_p.h \
- $$PWD/packagemanagergui.h \
- ../common/binaryformat.h \
- ../common/binaryformatengine.h \
- ../common/binaryformatenginehandler.h \
- ../common/repository.h \
- ../common/zipjob.h \
- ../common/utils.h \
- ../common/errors.h \
+HEADERS += packagemanagercore.h \
+ packagemanagercore_p.h \
+ packagemanagergui.h \
+ binaryformat.h \
+ binaryformatengine.h \
+ binaryformatenginehandler.h \
+ repository.h \
+ zipjob.h \
+ utils.h \
+ errors.h \
component.h \
componentmodel.h \
qinstallerglobal.h \
@@ -101,16 +99,16 @@ HEADERS += $$PWD/packagemanagercore.h \
packagemanagerproxyfactory.h \
createlocalrepositoryoperation.h
-SOURCES += $$PWD/packagemanagercore.cpp \
- $$PWD/packagemanagercore_p.cpp \
- $$PWD/packagemanagergui.cpp \
- ../common/binaryformat.cpp \
- ../common/binaryformatengine.cpp \
- ../common/binaryformatenginehandler.cpp \
- ../common/repository.cpp \
- ../common/zipjob.cpp \
- ../common/fileutils.cpp \
- ../common/utils.cpp \
+SOURCES += packagemanagercore.cpp \
+ packagemanagercore_p.cpp \
+ packagemanagergui.cpp \
+ binaryformat.cpp \
+ binaryformatengine.cpp \
+ binaryformatenginehandler.cpp \
+ repository.cpp \
+ zipjob.cpp \
+ fileutils.cpp \
+ utils.cpp \
component.cpp \
componentmodel.cpp \
qtpatch.cpp \
diff --git a/installerbuilder/libinstaller/operationrunner.cpp b/installerbuilder/libinstaller/operationrunner.cpp
index b9dd3cea0..26e7e6b02 100644
--- a/installerbuilder/libinstaller/operationrunner.cpp
+++ b/installerbuilder/libinstaller/operationrunner.cpp
@@ -29,18 +29,17 @@
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
-
#include "operationrunner.h"
-#include "common/errors.h"
-#include "common/binaryformat.h"
-#include "common/utils.h"
+#include "binaryformat.h"
#include "component.h"
+#include "errors.h"
#include "init.h"
#include "packagemanagercore.h"
+#include "utils.h"
-#include <kdupdaterupdateoperation.h>
-#include <kdupdaterupdateoperationfactory.h>
+#include "kdupdaterupdateoperation.h"
+#include "kdupdaterupdateoperationfactory.h"
#include <iostream>
diff --git a/installerbuilder/libinstaller/packagemanagercore.cpp b/installerbuilder/libinstaller/packagemanagercore.cpp
index b47708c7a..8b871c61e 100644
--- a/installerbuilder/libinstaller/packagemanagercore.cpp
+++ b/installerbuilder/libinstaller/packagemanagercore.cpp
@@ -29,15 +29,13 @@
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
-
#include "packagemanagercore.h"
#include "adminauthorization.h"
-#include "common/binaryformat.h"
-#include "common/errors.h"
-#include "common/utils.h"
+#include "binaryformat.h"
#include "component.h"
#include "downloadarchivesjob.h"
+#include "errors.h"
#include "fsengineclient.h"
#include "getrepositoriesmetainfojob.h"
#include "messageboxhandler.h"
@@ -48,6 +46,7 @@
#include "qprocesswrapper.h"
#include "qsettingswrapper.h"
#include "settings.h"
+#include "utils.h"
#include <QtCore/QTemporaryFile>
@@ -56,11 +55,11 @@
#include <QtScript/QScriptEngine>
#include <QtScript/QScriptContext>
-#include <kdsysinfo.h>
-#include <kdupdaterupdateoperationfactory.h>
+#include "kdsysinfo.h"
+#include "kdupdaterupdateoperationfactory.h"
#ifdef Q_OS_WIN
-#include "qt_windows.h"
+# include "qt_windows.h"
#endif
using namespace QInstaller;
diff --git a/installerbuilder/libinstaller/packagemanagercore.h b/installerbuilder/libinstaller/packagemanagercore.h
index 13509b6b1..4e02b3ba3 100644
--- a/installerbuilder/libinstaller/packagemanagercore.h
+++ b/installerbuilder/libinstaller/packagemanagercore.h
@@ -29,11 +29,10 @@
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
-
#ifndef PACKAGEMANAGERCORE_H
#define PACKAGEMANAGERCORE_H
-#include "common/repository.h"
+#include "repository.h"
#include "qinstallerglobal.h"
#include <QtCore/QHash>
diff --git a/installerbuilder/libinstaller/packagemanagercore_p.cpp b/installerbuilder/libinstaller/packagemanagercore_p.cpp
index abb1523a9..765db4e4e 100644
--- a/installerbuilder/libinstaller/packagemanagercore_p.cpp
+++ b/installerbuilder/libinstaller/packagemanagercore_p.cpp
@@ -29,14 +29,13 @@
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
-
#include "packagemanagercore_p.h"
#include "adminauthorization.h"
-#include "common/binaryformat.h"
-#include "common/errors.h"
-#include "common/fileutils.h"
+#include "binaryformat.h"
#include "component.h"
+#include "errors.h"
+#include "fileutils.h"
#include "fsengineclient.h"
#include "messageboxhandler.h"
#include "packagemanagercore.h"
@@ -44,12 +43,12 @@
#include "qprocesswrapper.h"
#include "qsettingswrapper.h"
-#include <kdsavefile.h>
-#include <kdselfrestarter.h>
+#include "kdsavefile.h"
+#include "kdselfrestarter.h"
#include "kdupdaterfiledownloaderfactory.h"
-#include <kdupdaterupdatesourcesinfo.h>
-#include <kdupdaterupdateoperationfactory.h>
-#include <kdupdaterupdatefinder.h>
+#include "kdupdaterupdatesourcesinfo.h"
+#include "kdupdaterupdateoperationfactory.h"
+#include "kdupdaterupdatefinder.h"
#include <QtCore/QtConcurrentRun>
#include <QtCore/QCoreApplication>
diff --git a/installerbuilder/libinstaller/packagemanagergui.cpp b/installerbuilder/libinstaller/packagemanagergui.cpp
index 3fb88bee8..a041c9838 100644
--- a/installerbuilder/libinstaller/packagemanagergui.cpp
+++ b/installerbuilder/libinstaller/packagemanagergui.cpp
@@ -29,23 +29,21 @@
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
-
#include "packagemanagergui.h"
#include "component.h"
#include "componentmodel.h"
+#include "errors.h"
+#include "fileutils.h"
#include "messageboxhandler.h"
#include "packagemanagercore.h"
#include "qinstallerglobal.h"
#include "progresscoordinator.h"
#include "performinstallationform.h"
#include "settings.h"
+#include "utils.h"
-#include "common/errors.h"
-#include "common/utils.h"
-#include "common/fileutils.h"
-
-#include <kdsysinfo.h>
+#include "kdsysinfo.h"
#include <QtCore/QDir>
#include <QtCore/QDynamicPropertyChangeEvent>
diff --git a/installerbuilder/libinstaller/range.h b/installerbuilder/libinstaller/range.h
new file mode 100644
index 000000000..f97aa0317
--- /dev/null
+++ b/installerbuilder/libinstaller/range.h
@@ -0,0 +1,88 @@
+/**************************************************************************
+**
+** This file is part of Installer Framework**
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).*
+**
+** Contact: Nokia Corporation qt-info@nokia.com**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception version
+** 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you are unsure which license is appropriate for your use, please contact
+** (qt-info@nokia.com).
+**
+**************************************************************************/
+#ifndef RANGE_H
+#define RANGE_H
+
+#include <algorithm>
+
+template <typename T>
+class Range {
+public:
+ static Range<T> fromStartAndEnd( const T& start, const T& end ) {
+ Range<T> r;
+ r.m_start = start;
+ r.m_end = end;
+ return r;
+ }
+
+ static Range<T> fromStartAndLength( const T& start, const T& length ) {
+ Range<T> r;
+ r.m_start = start;
+ r.m_end = start + length;
+ return r;
+ }
+
+ Range() : m_start( 0 ), m_end( 0 ) {}
+
+ T start() const { return m_start; }
+
+ T end() const { return m_end; }
+
+ void move( const T& by ) {
+ m_start += by;
+ m_end += by;
+ }
+
+ Range<T> moved( const T& by ) const {
+ Range<T> b = *this;
+ b.move( by );
+ return b;
+ }
+
+ T length() const { return m_end - m_start; }
+
+ Range<T> normalized() const {
+ Range<T> r2( *this );
+ if ( r2.m_start > r2.m_end )
+ std::swap( r2.m_start, r2.m_end );
+ return r2;
+ }
+
+ bool operator==( const Range<T>& other ) const {
+ return m_start == other.m_start && m_end && other.m_end;
+ }
+ bool operator<( const Range<T>& other ) const {
+ if ( m_start != other.m_start )
+ return m_start < other.m_start;
+ return m_end < other.m_end;
+ }
+
+private:
+ T m_start;
+ T m_end;
+};
+
+#endif /* RANGE_H_ */
diff --git a/installerbuilder/libinstaller/repository.cpp b/installerbuilder/libinstaller/repository.cpp
new file mode 100644
index 000000000..cc80a20d9
--- /dev/null
+++ b/installerbuilder/libinstaller/repository.cpp
@@ -0,0 +1,213 @@
+/**************************************************************************
+**
+** This file is part of Installer Framework
+**
+** Copyright (c) 2011-2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "repository.h"
+
+namespace QInstaller {
+
+/*
+ Constructs an invalid Repository object.
+*/
+Repository::Repository()
+ : m_default(false)
+ , m_enabled(false)
+{
+ registerMetaType();
+}
+
+/*!
+ Constructs a new repository by using all fields of the given repository \a other.
+*/
+Repository::Repository(const Repository &other)
+ : m_url(other.m_url)
+ , m_default(other.m_default)
+ , m_enabled(other.m_enabled)
+ , m_username(other.m_username)
+ , m_password(other.m_password)
+{
+ registerMetaType();
+}
+
+/*!
+ Constructs a new repository by setting it's address to \a url and it's default state.
+*/
+Repository::Repository(const QUrl &url, bool isDefault)
+ : m_url(url)
+ , m_default(isDefault)
+ , m_enabled(true)
+{
+ registerMetaType();
+}
+
+/*!
+ Returns true if the repository URL is valid; otherwise returns false.
+
+ Note: The URL is simply run through a conformance test. It is not checked that the repository
+ actually exists.
+*/
+bool Repository::isValid() const
+{
+ return m_url.isValid();
+}
+
+/*!
+ Returns true if the repository was set using the package manager configuration file; otherwise returns
+ false.
+*/
+bool Repository::isDefault() const
+{
+ return m_default;
+}
+
+/*!
+ Returns the URL of the repository. By default an invalid \sa QUrl is returned.
+*/
+QUrl Repository::url() const
+{
+ return m_url;
+}
+
+/*!
+ Sets the repository URL to the one specified at \a url.
+*/
+void Repository::setUrl(const QUrl &url)
+{
+ m_url = url;
+}
+
+/*!
+ Returns whether the repository is enabled and used during information retrieval.
+*/
+bool Repository::isEnabled() const
+{
+ return m_enabled;
+}
+
+/*!
+ Sets this repository to \n enabled state and thus to use this repository for information retrieval or not.
+*/
+void Repository::setEnabled(bool enabled)
+{
+ m_enabled = enabled;
+}
+
+/*!
+ Returns the user name used for authentication.
+*/
+QString Repository::username() const
+{
+ return m_username;
+}
+
+/*!
+ Sets the user name for authentication to be \a username.
+*/
+void Repository::setUsername(const QString &username)
+{
+ m_username = username;
+}
+
+/*!
+ Returns the password used for authentication.
+*/
+QString Repository::password() const
+{
+ return m_password;
+}
+
+/*!
+ Sets the password for authentication to be \a password.
+*/
+void Repository::setPassword(const QString &password)
+{
+ m_password = password;
+}
+
+/*!
+ Compares the values of this repository to \a other and returns true if they are equal (same server,
+ default state, enabled state as well as username and password). \sa operator!=()
+*/
+bool Repository::operator==(const Repository &other) const
+{
+ return m_url == other.m_url && m_default == other.m_default && m_enabled == other.m_enabled
+ && m_username == other.m_username && m_password == other.m_password;
+}
+
+/*!
+ Returns true if the \a other repository is not equal to this repository; otherwise returns false. Two
+ repositories are considered equal if they contain the same elements. \sa operator==()
+*/
+bool Repository::operator!=(const Repository &other) const
+{
+ return !(*this == other);
+}
+
+/*!
+ Assigns the values of repository \a other to this repository.
+*/
+const Repository &Repository::operator=(const Repository &other)
+{
+ if (this == &other)
+ return *this;
+
+ m_url = other.m_url;
+ m_default = other.m_default;
+ m_enabled = other.m_enabled;
+ m_username = other.m_username;
+ m_password = other.m_password;
+
+ return *this;
+}
+
+void Repository::registerMetaType()
+{
+ qRegisterMetaType<Repository>("Repository");
+ qRegisterMetaTypeStreamOperators<Repository>("Repository");
+}
+
+QDataStream &operator>>(QDataStream &istream, Repository &repository)
+{
+ QByteArray url, username, password;
+ istream >> url >> repository.m_default >> repository.m_enabled >> username >> password;
+ repository.setUrl(QUrl::fromEncoded(QByteArray::fromBase64(url)));
+ repository.setUsername(QString::fromUtf8(QByteArray::fromBase64(username)));
+ repository.setPassword(QString::fromUtf8(QByteArray::fromBase64(password)));
+ return istream;
+}
+
+QDataStream &operator<<(QDataStream &ostream, const Repository &repository)
+{
+ return ostream << repository.m_url.toEncoded().toBase64() << repository.m_default << repository.m_enabled
+ << repository.m_username.toUtf8().toBase64() << repository.m_password.toUtf8().toBase64();
+}
+
+}
diff --git a/installerbuilder/libinstaller/repository.h b/installerbuilder/libinstaller/repository.h
new file mode 100644
index 000000000..432a851c4
--- /dev/null
+++ b/installerbuilder/libinstaller/repository.h
@@ -0,0 +1,97 @@
+/**************************************************************************
+**
+** This file is part of Installer Framework
+**
+** Copyright (c) 2011-2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef REPOSITORY_H
+#define REPOSITORY_H
+
+#include "installer_global.h"
+
+#include <QtCore/QMetaType>
+#include <QtCore/QUrl>
+
+namespace QInstaller {
+
+class INSTALLER_EXPORT Repository
+{
+public:
+ explicit Repository();
+ Repository(const Repository &other);
+ explicit Repository(const QUrl &url, bool isDefault);
+
+ bool isValid() const;
+ bool isDefault() const;
+
+ QUrl url() const;
+ void setUrl(const QUrl &url);
+
+ bool isEnabled() const;
+ void setEnabled(bool enabled);
+
+ QString username() const;
+ void setUsername(const QString &username);
+
+ QString password() const;
+ void setPassword(const QString &password);
+
+ bool operator==(const Repository &other) const;
+ bool operator!=(const Repository &other) const;
+
+ uint qHash(const Repository &repository);
+ const Repository &operator=(const Repository &other);
+
+ friend QDataStream &operator>>(QDataStream &istream, Repository &repository);
+ friend QDataStream &operator<<(QDataStream &ostream, const Repository &repository);
+
+private:
+ void registerMetaType();
+
+private:
+ QUrl m_url;
+ bool m_default;
+ bool m_enabled;
+ QString m_username;
+ QString m_password;
+};
+
+inline uint qHash(const Repository &repository)
+{
+ return qHash(repository.url().toString());
+}
+
+QDataStream &operator>>(QDataStream &istream, Repository &repository);
+QDataStream &operator<<(QDataStream &ostream, const Repository &repository);
+
+} // namespace QInstaller
+
+Q_DECLARE_METATYPE(QInstaller::Repository)
+
+#endif // REPOSITORY_H
diff --git a/installerbuilder/libinstaller/settings.cpp b/installerbuilder/libinstaller/settings.cpp
index 6507c0e7d..ace61761e 100644
--- a/installerbuilder/libinstaller/settings.cpp
+++ b/installerbuilder/libinstaller/settings.cpp
@@ -29,12 +29,11 @@
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
-
#include "settings.h"
-#include "common/errors.h"
-#include "common/repository.h"
+#include "errors.h"
#include "qinstallerglobal.h"
+#include "repository.h"
#include <QtCore/QFileInfo>
#include <QtCore/QStringList>
diff --git a/installerbuilder/libinstaller/updater.cpp b/installerbuilder/libinstaller/updater.cpp
index 519c6d18f..ec0564a8f 100644
--- a/installerbuilder/libinstaller/updater.cpp
+++ b/installerbuilder/libinstaller/updater.cpp
@@ -29,16 +29,16 @@
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
-
#include "updater.h"
-#include "common/binaryformat.h"
-#include "common/utils.h"
+#include "binaryformat.h"
#include "component.h"
#include "init.h"
#include "packagemanagercore.h"
+#include "utils.h"
#include <QtCore/QDebug>
+
#include <QtXml/QDomDocument>
#include <iostream>
diff --git a/installerbuilder/libinstaller/updatesettings.cpp b/installerbuilder/libinstaller/updatesettings.cpp
index 078db3adb..f06a1fa87 100644
--- a/installerbuilder/libinstaller/updatesettings.cpp
+++ b/installerbuilder/libinstaller/updatesettings.cpp
@@ -29,11 +29,10 @@
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
-
#include "updatesettings.h"
-#include "common/errors.h"
-#include "common/repository.h"
+#include "errors.h"
+#include "repository.h"
#include "settings.h"
#include <QtCore/QDateTime>
diff --git a/installerbuilder/libinstaller/utils.cpp b/installerbuilder/libinstaller/utils.cpp
new file mode 100644
index 000000000..4bd93430f
--- /dev/null
+++ b/installerbuilder/libinstaller/utils.cpp
@@ -0,0 +1,341 @@
+/**************************************************************************
+**
+** This file is part of Installer Framework
+**
+** Copyright (c) 2011-2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "utils.h"
+
+#include <QtCore/QDateTime>
+#include <QtCore/QDir>
+#include <QtCore/QProcessEnvironment>
+#include <QtCore/QVector>
+
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
+# include "qt_windows.h"
+#endif
+
+#include <fstream>
+#include <iostream>
+#include <sstream>
+
+static bool verb = false;
+
+void QInstaller::setVerbose(bool v)
+{
+ verb = v;
+}
+
+bool QInstaller::isVerbose()
+{
+ return verb;
+}
+
+#ifdef Q_WS_WIN
+void qWinMsgHandler(QtMsgType t, const char *str);
+
+class debugstream : public std::ostream
+{
+ class buf : public std::stringbuf
+ {
+ public:
+ buf() {}
+
+ int sync()
+ {
+ std::string s = str();
+ if (s[s.length() - 1] == '\n' )
+ s[s.length() - 1] = '\0'; // remove \n
+ qWinMsgHandler(QtDebugMsg, s.c_str());
+ std::cout << s << std::endl;
+ str(std::string());
+ return 0;
+ }
+ };
+public:
+ debugstream() : std::ostream(&b) {}
+private:
+ buf b;
+};
+#endif
+
+std::ostream &QInstaller::stdverbose()
+{
+ static std::fstream null;
+#ifdef Q_WS_WIN
+ static debugstream stream;
+#else
+ static std::ostream& stream = std::cout;
+#endif
+ if (verb)
+ return stream;
+ return null;
+}
+
+std::ostream &QInstaller::operator<<(std::ostream &os, const QString &string)
+{
+ return os << qPrintable(string);
+}
+
+//TODO from kdupdaterfiledownloader.cpp, use that one once merged
+QByteArray QInstaller::calculateHash(QIODevice *device, QCryptographicHash::Algorithm algo)
+{
+ Q_ASSERT(device);
+ QCryptographicHash hash(algo);
+ QByteArray buffer;
+ buffer.resize(512 * 1024);
+ while (true) {
+ const qint64 numRead = device->read(buffer.data(), buffer.size());
+ if (numRead <= 0)
+ return hash.result();
+ hash.addData(buffer.constData(), numRead);
+ }
+ return QByteArray(); // never reached
+}
+
+
+QString QInstaller::replaceVariables(const QHash<QString, QString> &vars, const QString &str)
+{
+ QString res;
+ int pos = 0;
+ while (true) {
+ int pos1 = str.indexOf(QLatin1Char('@'), pos);
+ if (pos1 == -1)
+ break;
+ int pos2 = str.indexOf(QLatin1Char('@'), pos1 + 1);
+ if (pos2 == -1)
+ break;
+ res += str.mid(pos, pos1 - pos);
+ QString name = str.mid(pos1 + 1, pos2 - pos1 - 1);
+ res += vars.value(name);
+ pos = pos2 + 1;
+ }
+ res += str.mid(pos);
+ return res;
+}
+
+QString QInstaller::replaceWindowsEnvironmentVariables(const QString &str)
+{
+ const QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
+ QString res;
+ int pos = 0;
+ while (true) {
+ int pos1 = str.indexOf(QLatin1Char( '%'), pos);
+ if (pos1 == -1)
+ break;
+ int pos2 = str.indexOf(QLatin1Char( '%'), pos1 + 1);
+ if (pos2 == -1)
+ break;
+ res += str.mid(pos, pos1 - pos);
+ QString name = str.mid(pos1 + 1, pos2 - pos1 - 1);
+ res += env.value(name);
+ pos = pos2 + 1;
+ }
+ res += str.mid(pos);
+ return res;
+}
+
+QInstaller::VerboseWriter::VerboseWriter(QObject *parent) : QObject(parent)
+{
+ preFileBuffer.open(QIODevice::ReadWrite);
+ stream.setDevice(&preFileBuffer);
+}
+
+QInstaller::VerboseWriter::~VerboseWriter()
+{
+ stream.flush();
+ if (logFileName.isEmpty()) // binarycreator
+ return;
+ //if the installer installed nothing - there is no target directory - where the logfile can be saved
+ if (!QFileInfo(logFileName).absoluteDir().exists())
+ return;
+
+ QFile output(logFileName);
+ if (output.open(QIODevice::ReadWrite | QIODevice::Append)) {
+ QString logInfo;
+ logInfo += QLatin1String("*************************************");
+ logInfo += QLatin1String("Invoked:") + QDateTime::currentDateTime().toString();
+ output.write(logInfo.toLocal8Bit());
+ output.write(preFileBuffer.data());
+ output.close();
+ }
+ stream.setDevice(0);
+}
+
+void QInstaller::VerboseWriter::setOutputStream(const QString &fileName)
+{
+ logFileName = fileName;
+}
+
+
+Q_GLOBAL_STATIC(QInstaller::VerboseWriter, verboseWriter)
+
+QInstaller::VerboseWriter *QInstaller::VerboseWriter::instance()
+{
+ return verboseWriter();
+}
+
+QInstaller::VerboseWriter &QInstaller::verbose()
+{
+ return *verboseWriter();
+}
+
+#ifdef Q_OS_WIN
+// taken from qcoreapplication_p.h
+template<typename Char>
+static QVector<Char*> qWinCmdLine(Char *cmdParam, int length, int &argc)
+{
+ QVector<Char*> argv(8);
+ Char *p = cmdParam;
+ Char *p_end = p + length;
+
+ argc = 0;
+
+ while (*p && p < p_end) { // parse cmd line arguments
+ while (QChar((short)(*p)).isSpace()) // skip white space
+ p++;
+ if (*p && p < p_end) { // arg starts
+ int quote;
+ Char *start, *r;
+ if (*p == Char('\"') || *p == Char('\'')) { // " or ' quote
+ quote = *p;
+ start = ++p;
+ } else {
+ quote = 0;
+ start = p;
+ }
+ r = start;
+ while (*p && p < p_end) {
+ if (quote) {
+ if (*p == quote) {
+ p++;
+ if (QChar((short)(*p)).isSpace())
+ break;
+ quote = 0;
+ }
+ }
+ if (*p == '\\') { // escape char?
+ p++;
+ if (*p == Char('\"') || *p == Char('\''))
+ ; // yes
+ else
+ p--; // treat \ literally
+ } else {
+ if (!quote && (*p == Char('\"') || *p == Char('\''))) { // " or ' quote
+ quote = *p++;
+ continue;
+ } else if (QChar((short)(*p)).isSpace() && !quote)
+ break;
+ }
+ if (*p)
+ *r++ = *p++;
+ }
+ if (*p && p < p_end)
+ p++;
+ *r = Char('\0');
+
+ if (argc >= (int)argv.size()-1) // expand array
+ argv.resize(argv.size()*2);
+ argv[argc++] = start;
+ }
+ }
+ argv[argc] = 0;
+
+ return argv;
+}
+
+QStringList QInstaller::parseCommandLineArgs(int argc, char **argv)
+{
+ Q_UNUSED(argc)
+ Q_UNUSED(argv)
+
+ QStringList arguments;
+ QString cmdLine = QString::fromWCharArray(GetCommandLine());
+
+ QVector<wchar_t*> args = qWinCmdLine<wchar_t>((wchar_t *)cmdLine.utf16(), cmdLine.length(), argc);
+ for (int a = 0; a < argc; ++a)
+ arguments << QString::fromWCharArray(args[a]);
+ return arguments;
+}
+#else
+QStringList QInstaller::parseCommandLineArgs(int argc, char **argv)
+{
+ QStringList arguments;
+ for (int a = 0; a < argc; ++a)
+ arguments << QString::fromLocal8Bit(argv[a]);
+ return arguments;
+}
+#endif
+
+#ifdef Q_OS_WIN
+// taken from qprocess_win.cpp
+static QString qt_create_commandline(const QString &program, const QStringList &arguments)
+{
+ QString args;
+ if (!program.isEmpty()) {
+ QString programName = program;
+ if (!programName.startsWith(QLatin1Char('\"')) && !programName.endsWith(QLatin1Char('\"'))
+ && programName.contains(QLatin1Char(' '))) {
+ programName = QLatin1Char('\"') + programName + QLatin1Char('\"');
+ }
+ programName.replace(QLatin1Char('/'), QLatin1Char('\\'));
+
+ // add the prgram as the first arg ... it works better
+ args = programName + QLatin1Char(' ');
+ }
+
+ for (int i = 0; i < arguments.size(); ++i) {
+ QString tmp = arguments.at(i);
+ // in the case of \" already being in the string the \ must also be escaped
+ tmp.replace(QLatin1String("\\\""), QLatin1String("\\\\\""));
+ // escape a single " because the arguments will be parsed
+ tmp.replace(QLatin1Char('\"'), QLatin1String("\\\""));
+ if (tmp.isEmpty() || tmp.contains(QLatin1Char(' ')) || tmp.contains(QLatin1Char('\t'))) {
+ // The argument must not end with a \ since this would be interpreted
+ // as escaping the quote -- rather put the \ behind the quote: e.g.
+ // rather use "foo"\ than "foo\"
+ QString endQuote(QLatin1Char('\"'));
+ int i = tmp.length();
+ while (i > 0 && tmp.at(i - 1) == QLatin1Char('\\')) {
+ --i;
+ endQuote += QLatin1Char('\\');
+ }
+ args += QLatin1String(" \"") + tmp.left(i) + endQuote;
+ } else {
+ args += QLatin1Char(' ') + tmp;
+ }
+ }
+ return args;
+}
+
+QString QInstaller::createCommandline(const QString &program, const QStringList &arguments)
+{
+ return qt_create_commandline(program, arguments);
+}
+#endif
diff --git a/installerbuilder/libinstaller/utils.h b/installerbuilder/libinstaller/utils.h
new file mode 100644
index 000000000..cbf2e95e7
--- /dev/null
+++ b/installerbuilder/libinstaller/utils.h
@@ -0,0 +1,92 @@
+/**************************************************************************
+**
+** This file is part of Installer Framework
+**
+** Copyright (c) 2010-2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef QINSTALLER_UTILS_H
+#define QINSTALLER_UTILS_H
+
+#include "installer_global.h"
+
+#include <QtCore/QBuffer>
+#include <QtCore/QCryptographicHash>
+#include <QtCore/QHash>
+#include <QtCore/QUrl>
+#include <QtCore/QTextStream>
+
+#include <ostream>
+
+QT_BEGIN_NAMESPACE
+class QIODevice;
+QT_END_NAMESPACE
+
+namespace QInstaller {
+
+ QByteArray INSTALLER_EXPORT calculateHash(QIODevice *device, QCryptographicHash::Algorithm algo);
+
+ QString INSTALLER_EXPORT replaceVariables(const QHash<QString,QString> &vars, const QString &str);
+ QString INSTALLER_EXPORT replaceWindowsEnvironmentVariables(const QString &str);
+ QStringList INSTALLER_EXPORT parseCommandLineArgs(int argc, char **argv);
+#ifdef Q_OS_WIN
+ QString createCommandline(const QString &program, const QStringList &arguments);
+#endif
+
+ void INSTALLER_EXPORT setVerbose(bool v);
+ bool INSTALLER_EXPORT isVerbose();
+
+ INSTALLER_EXPORT std::ostream& stdverbose();
+ INSTALLER_EXPORT std::ostream& operator<<(std::ostream &os, const QString &string);
+
+ class VerboseWriter;
+ INSTALLER_EXPORT VerboseWriter &verbose();
+
+ class INSTALLER_EXPORT VerboseWriter : public QObject
+ {
+ Q_OBJECT
+ public:
+ VerboseWriter(QObject *parent = 0);
+ ~VerboseWriter();
+
+ static VerboseWriter *instance();
+
+ inline VerboseWriter &operator<<(const char *t) { stdverbose() << t; stream << t; return *this; }
+ inline VerboseWriter &operator<<(std::ostream& (*f)(std::ostream &s)) { stdverbose() << *f; stream << "\n"; return *this; }
+ public slots:
+ void setOutputStream(const QString &fileName);
+
+ private:
+ QTextStream stream;
+ QBuffer preFileBuffer;
+ QString logFileName;
+ };
+
+}
+
+#endif // QINSTALLER_UTILS_H
diff --git a/installerbuilder/libinstaller/zipjob.cpp b/installerbuilder/libinstaller/zipjob.cpp
new file mode 100644
index 000000000..bcc617d31
--- /dev/null
+++ b/installerbuilder/libinstaller/zipjob.cpp
@@ -0,0 +1,206 @@
+/**************************************************************************
+**
+** This file is part of Installer Framework
+**
+** Copyright (c) 2011-2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+#include <zipjob.h>
+
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QMetaType>
+#include <QtCore/QStringList>
+
+#include <cassert>
+#include <climits>
+
+class ZipJob::Private
+{
+public:
+ Private() : outputDevice(0), process(0) {}
+
+ QIODevice *outputDevice;
+ QDir workingDir;
+ QProcess *process;
+ QStringList filesToArchive;
+};
+
+Q_DECLARE_METATYPE(QProcess::ExitStatus)
+
+ZipJob::ZipJob()
+ : d(new Private())
+{
+ qRegisterMetaType<QProcess::ExitStatus>();
+}
+
+ZipJob::~ZipJob()
+{
+ delete d;
+}
+
+void ZipJob::run()
+{
+ assert(!d->process);
+ d->process = new QProcess;
+ d->process->setWorkingDirectory(d->workingDir.absolutePath());
+ QStringList args;
+ args << QLatin1String( "-" ) << QLatin1String( "-r" ) << d->filesToArchive;
+ connect(d->process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
+ connect(d->process, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(processFinished(int,QProcess::ExitStatus)));
+ connect(d->process, SIGNAL(readyReadStandardOutput()), this, SLOT(processReadyReadStandardOutput()));
+
+ d->process->start(QLatin1String("zip"), args);
+ if (!d->process->waitForStarted()) {
+ //TODO handle
+ }
+
+ if (!d->process->waitForFinished(INT_MAX)) {
+ //TODO handle
+ }
+
+ delete d->process;
+ d->process = 0;
+ // emit result
+}
+
+void ZipJob::processError(QProcess::ProcessError)
+{
+ emit error();
+}
+
+void ZipJob::processFinished(int, QProcess::ExitStatus)
+{
+ emit finished();
+}
+
+void ZipJob::processReadyReadStandardOutput()
+{
+ const QByteArray buf = d->process->readAll();
+ const qint64 toWrite = buf.size();
+ qint64 written = 0;
+ while (written < toWrite) {
+ const qint64 num = d->outputDevice->write(buf.constData() + written, toWrite - written);
+ if (num < 0) {
+ //TODO: handle error
+ return;
+ }
+ written += num;
+ }
+}
+
+void ZipJob::setOutputDevice(QIODevice *device)
+{
+ d->outputDevice = device;
+}
+
+void ZipJob::setWorkingDirectory(const QDir &dir)
+{
+ d->workingDir = dir;
+}
+
+void ZipJob::setFilesToArchive(const QStringList &files)
+{
+ d->filesToArchive = files;
+}
+
+class UnzipJob::Private
+{
+public:
+ Private() : inputDevice(0) {}
+
+ QIODevice *inputDevice;
+ QString outputPath;
+ QStringList filesToExtract;
+};
+
+UnzipJob::UnzipJob()
+ : d(new Private())
+{
+ qRegisterMetaType<QProcess::ExitStatus>();
+}
+
+UnzipJob::~UnzipJob()
+{
+ delete d;
+}
+
+void UnzipJob::setInputDevice(QIODevice *device)
+{
+ d->inputDevice = device;
+}
+
+void UnzipJob::setOutputPath(const QString &path)
+{
+ d->outputPath = path;
+}
+
+void UnzipJob::processError(QProcess::ProcessError)
+{
+ emit error();
+}
+
+void UnzipJob::run()
+{
+ QProcess process;
+ // TODO: this won't work on Windows... grmpfl, but on Mac and Linux, at least...
+ QStringList args;
+ args << QLatin1String( "/dev/stdin" );
+ if (!d->filesToExtract.isEmpty())
+ args << QLatin1String("-x") << d->filesToExtract;
+ process.setWorkingDirectory(d->outputPath);
+ process.start(QLatin1String("unzip"), args);
+ connect(&process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
+ connect(&process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processFinished(int, QProcess::ExitStatus )));
+ if (!process.waitForStarted()) {
+ // TODO handle
+ return;
+ }
+
+ const int bufferSize = 4096;
+ QByteArray buffer;
+ while (d->inputDevice->bytesAvailable() > 0 || d->inputDevice->waitForReadyRead(INT_MAX)) {
+ buffer = d->inputDevice->read(bufferSize);
+ process.write(buffer);
+ process.waitForBytesWritten(INT_MAX);
+ }
+ process.closeWriteChannel();
+
+ if (!process.waitForFinished(INT_MAX)) {
+ // TODO handle
+ }
+}
+
+void UnzipJob::processFinished(int, QProcess::ExitStatus)
+{
+ emit finished();
+}
+
+void UnzipJob::setFilesToExtract(const QStringList &files)
+{
+ d->filesToExtract = files;
+}
diff --git a/installerbuilder/libinstaller/zipjob.h b/installerbuilder/libinstaller/zipjob.h
new file mode 100644
index 000000000..72ab40796
--- /dev/null
+++ b/installerbuilder/libinstaller/zipjob.h
@@ -0,0 +1,100 @@
+/**************************************************************************
+**
+** This file is part of Installer Framework
+**
+** Copyright (c) 2010-2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef ZIPJOB_H
+#define ZIPJOB_H
+
+#include <QProcess>
+#include <QRunnable>
+
+QT_BEGIN_NAMESPACE
+class QDir;
+class QIODevice;
+class QStringList;
+QT_END_NAMESPACE
+
+class ZipJob : public QObject, public QRunnable
+{
+ Q_OBJECT
+
+public:
+ ZipJob();
+ ~ZipJob();
+
+ void setOutputDevice(QIODevice *device);
+ void setWorkingDirectory(const QDir &dir);
+ void setFilesToArchive(const QStringList &files);
+
+ void run();
+
+Q_SIGNALS:
+ void finished();
+ void error();
+
+private Q_SLOTS:
+ void processError(QProcess::ProcessError);
+ void processFinished(int, QProcess::ExitStatus);
+ void processReadyReadStandardOutput();
+
+private:
+ class Private;
+ Private *const d;
+};
+
+class UnzipJob : public QObject, public QRunnable
+{
+ Q_OBJECT
+
+public:
+ UnzipJob();
+ ~UnzipJob();
+
+ void setInputDevice(QIODevice *device);
+ void setOutputPath(const QString &path);
+ void setFilesToExtract(const QStringList &files);
+
+ void run();
+
+Q_SIGNALS:
+ void finished();
+ void error();
+
+private Q_SLOTS:
+ void processError(QProcess::ProcessError);
+ void processFinished(int, QProcess::ExitStatus);
+
+private:
+ class Private;
+ Private *const d;
+};
+
+#endif // ZIPJOB_H