summaryrefslogtreecommitdiffstats
path: root/installerbuilder/libinstaller/kdtools
diff options
context:
space:
mode:
Diffstat (limited to 'installerbuilder/libinstaller/kdtools')
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/KDAutoPointer1
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/KDByteSize1
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/KDGenericFactory1
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/KDJob1
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/KDLockfile1
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/KDMetaMethodIterator1
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/KDRunOnceChecker1
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/KDSaveFile1
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/KDSelfRestarter1
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/KDSysInfo1
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/KDToolsCore.pri42
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/KDWatchdog1
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdautopointer.cpp577
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdautopointer.h147
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdbytesize.cpp90
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdbytesize.h51
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdgenericfactory.cpp250
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdgenericfactory.h90
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdjob.cpp148
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdjob.h104
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdlockfile.cpp90
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdlockfile.h47
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdlockfile_p.h52
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdlockfile_unix.cpp77
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdlockfile_win.cpp69
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdmetamethoditerator.cpp493
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdmetamethoditerator.h85
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdrunoncechecker.cpp133
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdrunoncechecker.h46
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdsavefile.cpp476
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdsavefile.h83
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdselfrestarter.cpp78
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdselfrestarter.h42
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdsysinfo.cpp191
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdsysinfo.h116
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdsysinfo_mac.cpp119
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdsysinfo_win.cpp323
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdsysinfo_x11.cpp163
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdtoolsglobal.cpp54
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdtoolsglobal.h135
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdversion.cpp89
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdversion.h52
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdwatchdog.cpp115
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/kdwatchdog.h60
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/pimpl_ptr1
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/pimpl_ptr.cpp225
-rw-r--r--installerbuilder/libinstaller/kdtools/KDToolsCore/pimpl_ptr.h66
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/Application1
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/FileDownloader1
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/FileDownloaderFactory1
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/KDUpdater20
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/KDUpdater.pri73
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/PackagesInfo1
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/SignatureVerificationResult1
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/SignatureVerifier1
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/Update1
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/UpdateFinder1
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/UpdateOperation1
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/UpdateOperationFactory1
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/UpdateSourcesInfo1
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/UpdatesDialog1
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/addupdatesourcedialog.ui193
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/environment.cpp55
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/environment.h36
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdater.h62
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterapplication.cpp324
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterapplication.h93
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatercrypto.cpp743
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatercrypto.h99
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterfiledownloader.cpp1165
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterfiledownloader.h105
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterfiledownloader_p.h243
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterfiledownloaderfactory.cpp129
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterfiledownloaderfactory.h71
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterpackagesinfo.cpp566
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterpackagesinfo.h117
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterpackagesview.cpp134
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterpackagesview.h53
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatersignatureverificationresult.cpp88
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatersignatureverificationresult.h65
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatersignatureverificationrunnable.cpp135
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatersignatureverificationrunnable.h85
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatersignatureverifier.cpp46
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatersignatureverifier.h46
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatertask.cpp440
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatertask.h99
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterufcompresscommon.cpp131
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterufcompresscommon_p.h71
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterufuncompressor.cpp220
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterufuncompressor_p.h58
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdate.cpp313
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdate.h86
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatefinder.cpp892
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatefinder.h70
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateinstaller.cpp481
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateinstaller.h64
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateoperation.cpp417
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateoperation.h91
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateoperationfactory.cpp116
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateoperationfactory.h65
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateoperations.cpp1120
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateoperations.h184
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesdialog.cpp305
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesdialog.h57
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesinfo.cpp372
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesinfo_p.h99
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesourcesinfo.cpp511
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesourcesinfo.h112
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesourcesview.cpp375
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesourcesview.h68
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/updatesdialog.ui245
-rw-r--r--installerbuilder/libinstaller/kdtools/LICENSE.LGPL488
112 files changed, 17298 insertions, 0 deletions
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/KDAutoPointer b/installerbuilder/libinstaller/kdtools/KDToolsCore/KDAutoPointer
new file mode 100644
index 000000000..5203ea2db
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/KDAutoPointer
@@ -0,0 +1 @@
+#include "kdautopointer.h"
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/KDByteSize b/installerbuilder/libinstaller/kdtools/KDToolsCore/KDByteSize
new file mode 100644
index 000000000..e0ee65f30
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/KDByteSize
@@ -0,0 +1 @@
+#include "kdbytesize.h"
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/KDGenericFactory b/installerbuilder/libinstaller/kdtools/KDToolsCore/KDGenericFactory
new file mode 100644
index 000000000..42f06640a
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/KDGenericFactory
@@ -0,0 +1 @@
+#include "kdgenericfactory.h"
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/KDJob b/installerbuilder/libinstaller/kdtools/KDToolsCore/KDJob
new file mode 100644
index 000000000..79fd1dde9
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/KDJob
@@ -0,0 +1 @@
+#include "kdjob.h"
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/KDLockfile b/installerbuilder/libinstaller/kdtools/KDToolsCore/KDLockfile
new file mode 100644
index 000000000..afd9f7ad1
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/KDLockfile
@@ -0,0 +1 @@
+#include "kdlockfile.h"
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/KDMetaMethodIterator b/installerbuilder/libinstaller/kdtools/KDToolsCore/KDMetaMethodIterator
new file mode 100644
index 000000000..cfb58d054
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/KDMetaMethodIterator
@@ -0,0 +1 @@
+#include "kdmetamethoditerator.h"
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/KDRunOnceChecker b/installerbuilder/libinstaller/kdtools/KDToolsCore/KDRunOnceChecker
new file mode 100644
index 000000000..d5ccad881
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/KDRunOnceChecker
@@ -0,0 +1 @@
+#include "kdrunoncechecker.h"
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/KDSaveFile b/installerbuilder/libinstaller/kdtools/KDToolsCore/KDSaveFile
new file mode 100644
index 000000000..f7df3f1b5
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/KDSaveFile
@@ -0,0 +1 @@
+#include "kdsavefile.h"
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/KDSelfRestarter b/installerbuilder/libinstaller/kdtools/KDToolsCore/KDSelfRestarter
new file mode 100644
index 000000000..7de1c2779
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/KDSelfRestarter
@@ -0,0 +1 @@
+#include "kdselfrestarter.h"
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/KDSysInfo b/installerbuilder/libinstaller/kdtools/KDToolsCore/KDSysInfo
new file mode 100644
index 000000000..7d5cec1e4
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/KDSysInfo
@@ -0,0 +1 @@
+#include "kdsysinfo.h"
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/KDToolsCore.pri b/installerbuilder/libinstaller/kdtools/KDToolsCore/KDToolsCore.pri
new file mode 100644
index 000000000..213c8343d
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/KDToolsCore.pri
@@ -0,0 +1,42 @@
+DEPENDPATH += $$PWD
+INCLUDEPATH += $$PWD
+
+CONFIG( shared, static|shared) {
+ DEFINES += BUILD_SHARED_KDTOOLSCORE
+}
+
+HEADERS += $$PWD/pimpl_ptr.h \
+ $$PWD/kdtoolsglobal.h \
+ $$PWD/kdbytesize.h \
+ $$PWD/kdjob.h \
+ $$PWD/kdwatchdog.h \
+ $$PWD/kdgenericfactory.h \
+ $$PWD/kdautopointer.h \
+ $$PWD/kdselfrestarter.h \
+ $$PWD/kdsavefile.h \
+ $$PWD/kdmetamethoditerator.h \
+ $$PWD/kdrunoncechecker.h \
+ $$PWD/kdlockfile.h \
+ $$PWD/kdsysinfo.h \
+ $$PWD/kdversion.h
+
+SOURCES += $$PWD/pimpl_ptr.cpp \
+ $$PWD/kdtoolsglobal.cpp \
+ $$PWD/kdbytesize.cpp \
+ $$PWD/kdjob.cpp \
+ $$PWD/kdwatchdog.cpp \
+ $$PWD/kdgenericfactory.cpp \
+ $$PWD/kdautopointer.cpp \
+ $$PWD/kdselfrestarter.cpp \
+ $$PWD/kdsavefile.cpp \
+ $$PWD/kdmetamethoditerator.cpp \
+ $$PWD/kdrunoncechecker.cpp \
+ $$PWD/kdlockfile.cpp \
+ $$PWD/kdsysinfo.cpp \
+ $$PWD/kdversion.cpp
+
+unix:SOURCES += $$PWD/kdlockfile_unix.cpp
+win32:SOURCES += $$PWD/kdlockfile_win.cpp
+win32:SOURCES += $$PWD/kdsysinfo_win.cpp
+macx:SOURCES += $$PWD/kdsysinfo_mac.cpp
+unix:!macx:SOURCES += $$PWD/kdsysinfo_x11.cpp
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/KDWatchdog b/installerbuilder/libinstaller/kdtools/KDToolsCore/KDWatchdog
new file mode 100644
index 000000000..3032c2a37
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/KDWatchdog
@@ -0,0 +1 @@
+#include "kdwatchdog.h"
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdautopointer.cpp b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdautopointer.cpp
new file mode 100644
index 000000000..3398ac8b8
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdautopointer.cpp
@@ -0,0 +1,577 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdautopointer.h"
+
+/*!
+ \class KDAutoPointer
+ \ingroup core smartptr
+ \brief Owning version of QPointer
+ \since_c 2.1
+
+ (The exception safety of this class has not been evaluated yet.)
+
+ KDAutoPointer is a fusion of std::auto_ptr and QPointer, ie. it owns the
+ contained object, but if that object is otherwise deleted, it sets
+ itself to null, just like QPointer does.
+
+ Like std::auto_ptr, ownership is never shared between instances of
+ KDAutoPointer. Copying and copy assignment \em transfer ownership,
+ ie. in the following code
+
+ \code
+ KDAutoPointer<MyDialog> myDialog( new MyDialog );
+ KDAutoPointer<QObject> monitor( myDialog ); // Probably WRONG!
+ \endcode
+
+ \c monitor will end up owning the \c MyDialog instance, and \c
+ myDialog will be NULL, which is probably not what the programmer
+ intended.
+
+ Like QPointer, KDAutoPointer can only hold objects of a class derived
+ from QObject. If you need this functionality for arbitrary types,
+ consider using std::tr1::shared_ptr together with
+ std::tr1::weak_ptr.
+
+ \section overview Overview
+
+ You construct a KDAutoPointer by passing a pointer to the object to be
+ owned in \link KDAutoPointer(T*) the constructor\endlink, or, after the
+ fact, by calling reset(). Neither of these operations happen
+ implicitly, since they entail a change of ownership that should be
+ visible in code.
+
+ For the same reason, if you need to get a pointer to the contained
+ (owned) object, the conversion is not implicit, either. You have to
+ explicitly call get() (if you want to leave ownership to the
+ KDAutoPointer) or release() (if you want to transfer ownership out of
+ KDAutoPointer).
+
+ Use \link swap(KDAutoPointer&,KDAutoPointer&) swap()\endlink to quickly
+ exchange the contents of two \link KDAutoPointer KDAutoPointers\endlink, and
+ operator unspecified_bool_type() to test whether KDAutoPointer (still)
+ contains an object:
+
+ \code
+ KDAutoPointer w1( new QWidget ), w2();
+ assert( w1 ); assert( !w2 );
+ swap( w1, s2 );
+ assert( !w1 ); assert( w2 );
+ \endcode
+
+ \section general-use General Use
+
+ The general use case of KDAutoPointer is that of holding objects that
+ have unclear ownership semantics. E.g. classes that implement the
+ Command Pattern are sometimes implemented as deleting themselves
+ after the command finished. By holding instances of such classes in
+ KDAutoPointers, you do not have to care about whether or now the object
+ deletes itself. If it deletes itself, then KDAutoPointer will set itself
+ to NULL, if not, KDAutoPointer will delete the object when it goes out
+ of scope.
+
+ \section child-creation Esp.: Child Creation
+
+ You can also use KDAutoPointer for temporarily storing \link QObject
+ QObjects\endlink for exception safety. This is esp. useful when
+ following the Trolltech-recommended style of dialog creation (create
+ parent-less children up-front, add to layouts later):
+
+ \code
+ QLabel * lb = new QLabel( tr("Name:" );
+ QLineEdit * le = new QLineEdit;
+
+ QHBoxLayout * hbox = new QHBoxLayout;
+ hbox->addWidget( lb );
+ hbox->addWidget( le );
+ // if somethings throws an exception here,
+ // all of the above will be leaked
+ setLayout( hbox );
+ \endcode
+
+ Rewriting this as (granted, cumbersome):
+ \code
+ KDAutoPointer<QLabel> lb( new QLabel( tr("Name:" );
+ KDAutoPointer<QLineEdit> le( new QLineEdit );
+
+ KDAutoPointer<QHBoxLayout> hbox( new QHBoxLayout );
+ hbox->addWidget( lb.get() );
+ hbox->addWidget( le.get() );
+ // if somethings throws an exception here,
+ // all of the above will be properly cleaned up
+ setLayout( hbox.release() );
+ lb.release();
+ le.release();
+ \endcode
+ takes care of the leak.
+
+ Since this is so cumbersome, you should instead always pass parents
+ to children as part of construction.
+
+ \section model-dialogs Esp.: Modal Dialogs
+
+ A more specific use case is (modal) dialogs.
+
+ Traditionally, most programmers allocate these on the stack:
+
+ \code
+ MyDialog dialog( parent );
+ // set up 'dialog'...
+ if ( !dialog.exec() )
+ return;
+ // extract information from 'dialog'...
+ return;
+ \endcode
+
+ This is usually ok. Even though \c dialog has a parent, the parent
+ will usually live longer than the dialog. The dialog is modal, after
+ all, so the user is not supposed to be able to quit the application
+ while that dialog is on screen.
+
+ There are some applications, however, that have other ways to
+ terminate than explicit user request. Whether the application exits
+ timer-driven, or by an IPC call, what will happen is that \c dialog
+ is deleted as a child of \c parent \em and \em then \em again by the
+ compiler as part of cleaning up the stack once \c exec() returns.
+
+ This is where KDAutoPointer comes in. Instead of allocating modal
+ dialogs on the stack, allocate them into a KDAutoPointer:
+
+ \code
+ const KDAutoPointer<MyDialog> dialog( new MyDialog( parent ) );
+ // set up 'dialog'...
+ if ( !dialog->exec() || !dialog )
+ return;
+ // extract information from 'dialog'...
+ return;
+ \endcode
+
+ Note the use of \c const to prevent accidental copying of \c dialog,
+ and the additional check for \c dialog to catch the case where after
+ exec() returns, the dialog has been deleted.
+*/
+
+/*!
+ \typedef KDAutoPointer::element_type
+
+ A typedef for \c T. For STL compatibility.
+*/
+
+/*!
+ \typedef KDAutoPointer::value_type
+
+ A typedef for \c T. For STL compatibility.
+*/
+
+/*!
+ \typedef KDAutoPointer<T>::pointer
+
+ A typedef for \c T*. For STL compatibility.
+*/
+
+/*!
+ \fn KDAutoPointer::KDAutoPointer()
+
+ Default constructor. Constructs a NULL KDAutoPointer.
+
+ \post get() == 0
+*/
+
+/*!
+ \fn KDAutoPointer::KDAutoPointer( T * obj )
+
+ Constructor. Constructs a KDAutoPointer that contains (owns) \a obj.
+
+ \post get() == obj
+*/
+
+/*!
+ \fn KDAutoPointer::KDAutoPointer( KDAutoPointer & other )
+
+ Move constructor. Constructs a KDAutoPointer that takes over ownership
+ of the object contained (owned) by \a other.
+
+ \post this->get() == (the object previously owned by 'other')
+ \post other.get() == 0
+*/
+
+/*!
+ \fn KDAutoPointer::KDAutoPointer( KDAutoPointer<U> & other )
+
+ \overload
+*/
+
+/*!
+ \fn KDAutoPointer & KDAutoPointer::operator=( KDAutoPointer & other )
+
+ Copy assignment operator. Equivalent to
+ \code
+ reset( other.release() );
+ \endcode
+
+ \post this->get() == (the object previously owned by 'other')
+ \post other.get() == 0
+ \post The object previously owned by \c *this has been deleted.
+*/
+
+/*!
+ \fn KDAutoPointer & KDAutoPointer::operator=( KDAutoPointer<U> & other )
+
+ \overload
+*/
+
+/*!
+ \fn KDAutoPointer::~KDAutoPointer()
+
+ Destructor.
+
+ \post The object previously owned by \c *this has been deleted.
+*/
+
+/*!
+ \fn void KDAutoPointer::swap( KDAutoPointer & other )
+
+ Swaps the contents of \a *this and \a other. You probably want to
+ use the free function swap(KDAutoPointer&,KDAutoPointer&) instead. Also
+ qSwap() has been specialized to use this function internally.
+
+ \post get() == (previous value of other.get())
+ \post other.get() == (previous value of this->get())
+*/
+
+/*!
+ \fn T * KDAutoPointer::get() const
+
+ \returns a pointer to the contained (owned) object.
+*/
+
+/*!
+ \fn T * KDAutoPointer::release()
+
+ Yields ownership of the contained object and returns a pointer to it.
+
+ \post get() == 0
+ \post The object previously owned by \c *this had \em not been deleted.
+*/
+
+/*!
+ \fn T * KDAutoPointer::data() const
+
+ Equivalent to get(). Provided for consistency with Qt naming
+ conventions.
+*/
+
+/*!
+ \fn T * KDAutoPointer::take()
+
+ Equivalent to release(). Provided for consistency with Qt naming
+ conventions.
+*/
+
+/*!
+ \fn void KDAutoPointer::reset( T * other )
+
+ Yields ownership of the contained object (if any) and and takes over
+ ownership of \a other.
+
+ \post get() == other
+ \post The object previously owned by \c *this has been deleted.
+*/
+
+/*!
+ \fn T & KDAutoPointer::operator*() const
+
+ Dereference operator. Returns \link get() *get()\endlink.
+*/
+
+/*!
+ \fn T * KDAutoPointer::operator->() const
+
+ Member-by-pointer operator. Returns get().
+*/
+
+/*!
+ \fn bool KDAutoPointer::operator==( const KDAutoPointer<S> & other ) const
+
+ Equal-to operator. Returns get() == other.get().
+
+ \note Due to the fact that two \link KDAutoPointer KDAutoPointers\endlink
+ cannot contain the same object, the relational operators are not
+ very useful.
+*/
+
+/*!
+ \fn bool KDAutoPointer::operator!=( const KDAutoPointer<S> & other ) const
+
+ Not-Equal-to operator. Returns get() != other.get().
+
+ \note Due to the fact that two \link KDAutoPointer KDAutoPointers\endlink
+ cannot contain the same object, the relational operators are not
+ very useful.
+*/
+
+/*!
+ \fn KDAutoPointer::operator unspecified_bool_type() const
+
+ \returns \c true if \c *this contains an object, otherwise \c false.
+*/
+
+/*!
+ \fn void swap( KDAutoPointer<T> & lhs, KDAutoPointer<T> & rhs )
+ \relates KDAutoPointer
+
+ Equivalent to
+ \code
+ lhs.swap( rhs );
+ \endcode
+
+ Provided for generic code that uses the standard swap idiom:
+ \code
+ using std::swap;
+ swap( a, b );
+ \endcode
+ to find through <a href="http://en.wikipedia.org/wiki/Argument_dependent_name_lookup">ADL</a>,
+ enabling such code to automatically use the more efficient
+ \link KDAutoPointer::swap() member swap\endlink instead of the default
+ implementation (which uses a temporary).
+*/
+
+/*!
+ \fn void qSwap( KDAutoPointer<T> & lhs, KDAutoPointer<S> & rhs )
+ \relates KDAutoPointer
+
+ Equivalent to
+ \code
+ swap( lhs, rhs );
+ \endcode
+ except for code using %qSwap() instead of (std::)swap.
+*/
+
+/*!
+ \fn bool operator==( const KDAutoPointer<S> & lhs, const T * rhs )
+ \relates KDAutoPointer
+
+ Equal-to operator. Equivalent to
+ \code
+ lhs.get() == rhs
+ \endcode
+*/
+
+/*!
+ \fn bool operator==( const S * lhs, const KDAutoPointer<T> & rhs )
+ \relates KDAutoPointer
+ \overload
+*/
+
+/*!
+ \fn bool operator==( const KDAutoPointer<S> & lhs, const QPointer<T> & rhs )
+ \relates KDAutoPointer
+ \overload
+*/
+
+/*!
+ \fn bool operator==( const QPointer<S> & lhs, const KDAutoPointer<T> & rhs )
+ \relates KDAutoPointer
+ \overload
+*/
+
+
+/*!
+ \fn bool operator!=( const KDAutoPointer<S> & lhs, const T * rhs )
+ \relates KDAutoPointer
+
+ Not-equal-to operator. Equivalent to
+ \code
+ lhs.get() != rhs
+ \endcode
+*/
+
+/*!
+ \fn bool operator!=( const S * lhs, const KDAutoPointer<T> & rhs )
+ \relates KDAutoPointer
+ \overload
+*/
+
+/*!
+ \fn bool operator!=( const KDAutoPointer<S> & lhs, const QPointer<T> & rhs )
+ \relates KDAutoPointer
+ \overload
+*/
+
+/*!
+ \fn bool operator!=( const QPointer<S> & lhs, const KDAutoPointer<T> & rhs )
+ \relates KDAutoPointer
+ \overload
+*/
+
+#ifdef KDTOOLSCORE_UNITTESTS
+
+#include <KDUnitTest/Test>
+
+namespace {
+
+ struct A : QObject {};
+ struct B : QObject {};
+
+}
+
+KDAB_UNITTEST_SIMPLE( KDAutoPointer, "kdcoretools" ) {
+
+ {
+ QPointer<QObject> o;
+ {
+ const KDAutoPointer<QObject> qobject( new QObject );
+ o = qobject.get();
+ }
+ assertNull( o );
+ }
+
+ {
+ // check that conversion to bool works
+ KDAutoPointer<A> a( new A );
+ const bool b1 = a;
+ assertTrue( b1 );
+ const bool b2 = !a;
+ assertFalse( b2 );
+ a.reset();
+ const bool b3 = a;
+ assertFalse( b3 );
+ const bool b4 = !a;
+ assertTrue( b4 );
+ }
+
+ {
+ KDAutoPointer<QObject> o;
+ assertNull( o.get() );
+ assertFalse( o );
+ QObject * obj;
+ o.reset( obj = new QObject );
+ assertNotNull( o.get() );
+ assertTrue( o );
+ assertEqual( o.get(), obj );
+
+ KDAutoPointer<QObject> o2 = o;
+ assertNull( o.get() );
+ assertNotNull( o2.get() );
+ assertEqual( o2.get(), obj );
+
+ delete obj;
+ assertNull( o2.get() );
+ }
+
+ {
+ QPointer<QObject> obj = new QObject;
+ KDAutoPointer<QObject> o( obj );
+ o = o; // self-assignment
+ assertNotNull( obj );
+ o.reset( o.get() ); // self-assignment-ish
+ assertNotNull( obj );
+
+ o.reset( new QObject );
+ assertNull( obj );
+ assertNotNull( o.get() );
+ }
+
+ {
+ QPointer<A> ap;
+ {
+ KDAutoPointer<A> a( new A );
+ ap = a.get();
+ KDAutoPointer<QObject> o1( a );
+ assertNull( a.get() );
+ assertNotNull( o1.get() );
+ KDAutoPointer<QObject> o2;
+ o2 = a;
+ // doesn't compile (but doesn't compile for std::auto_ptr,
+ // either, so it's ok, I think
+ //KDAutoPointer<QObject> o3 = a
+ }
+ assertNull( ap );
+ }
+
+ {
+ // test swapping
+ KDAutoPointer<A> a1( new A ), a2( new A );
+
+ A * A1 = a1.get();
+ A * A2 = a2.get();
+
+ using std::swap;
+ swap( a1, a2 );
+
+ assertNotNull( a1.get() );
+ assertNotNull( a2.get() );
+
+ assertEqual( a1.get(), A2 );
+ assertEqual( a2.get(), A1 );
+
+ qSwap( a1, a2 );
+ assertEqual( a1.get(), A1 );
+ assertEqual( a2.get(), A2 );
+
+ }
+
+ {
+ KDAutoPointer<A> apa( new A );
+ QPointer<A> qpa( apa.get() );
+ A * pa = apa.get();
+ const A * cpa = pa;
+
+ assertEqual( apa.get(), apa.get() );
+ assertEqual( apa.get(), qpa );
+ assertEqual( apa.get(), pa );
+ assertEqual( apa.get(), cpa );
+ assertEqual( qpa, apa.get() );
+ assertEqual( pa, apa.get() );
+ assertEqual( cpa, apa.get() );
+
+ KDAutoPointer<QObject> apq; cpa = pa = qpa = 0;
+
+ assertNotEqual( apa.get(), qpa );
+ assertNotEqual( apa.get(), pa );
+ assertNotEqual( apa.get(), cpa );
+ assertNotEqual( qpa, apa.get() );
+ assertNotEqual( pa, apa.get() );
+ assertNotEqual( cpa, apa.get() );
+
+ assertNotEqual( apq.get(), apa.get() );
+ assertNotEqual( apa.get(), apq.get() );
+
+ assertNotNull( apa.get() );
+
+ apq.reset( new QObject );
+
+ assertNotEqual( apa.get(), qpa );
+ assertNotEqual( apa.get(), pa );
+ assertNotEqual( apa.get(), cpa );
+ assertNotEqual( qpa, apa.get() );
+ assertNotEqual( pa, apa.get() );
+ assertNotEqual( cpa, apa.get() );
+
+ assertNotEqual( apq.get(), apa.get() );
+ assertNotEqual( apa.get(), apq.get() );
+
+ assertNotNull( apa.get() );
+ }
+}
+
+#endif // KDTOOLSCORE_UNITTESTS
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdautopointer.h b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdautopointer.h
new file mode 100644
index 000000000..7a0558db0
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdautopointer.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef __KDTOOLS_CORE_KDAUTOPOINTER_H__
+#define __KDTOOLS_CORE_KDAUTOPOINTER_H__
+
+#include <KDToolsCore/kdtoolsglobal.h>
+
+#include <QtCore/QPointer>
+#include <QtCore/QObject>
+
+class KDAutoPointerBase {
+protected:
+ QPointer<QObject> o;
+
+ KDAutoPointerBase() : o() {}
+ explicit KDAutoPointerBase( QObject * obj ) : o( obj ) {}
+ KDAutoPointerBase( KDAutoPointerBase & other ) : o( other.release() ) {}
+ ~KDAutoPointerBase() { delete o; }
+
+ void swap( KDAutoPointerBase & other ) {
+ const QPointer<QObject> copy( o );
+ o = other.o;
+ other.o = copy;
+ }
+
+ QObject * release() { QObject * copy = o; o = 0 ; return copy; }
+ void reset( QObject * other ) { if ( o != other ) { delete o; o = other; } }
+
+ KDAB_IMPLEMENT_SAFE_BOOL_OPERATOR( o );
+};
+
+template <typename T>
+class MAKEINCLUDES_EXPORT KDAutoPointer : KDAutoPointerBase {
+public:
+ friend inline void swap( KDAutoPointer & lhs, KDAutoPointer & rhs ) { lhs.swap( rhs ); }
+
+ typedef T element_type;
+ typedef T value_type;
+ typedef T * pointer;
+
+ KDAutoPointer() : KDAutoPointerBase() {}
+ explicit KDAutoPointer( T * obj ) : KDAutoPointerBase( obj ) {}
+ KDAutoPointer( KDAutoPointer & other ) : KDAutoPointerBase( other.release() ) {}
+ template <typename U>
+ KDAutoPointer( KDAutoPointer<U> & other ) : KDAutoPointerBase( other.release() ) { T * t = other.get(); ( void )t; }
+
+ KDAutoPointer & operator=( KDAutoPointer & other ) {
+ this->reset( other.release() );
+ return *this;
+ }
+
+ template <typename U>
+ KDAutoPointer & operator=( KDAutoPointer<U> & other ) {
+ this->reset( other.release() );
+ return *this;
+ }
+
+ ~KDAutoPointer() {}
+
+ void swap( KDAutoPointer & other ) {
+ KDAutoPointerBase::swap( other );
+ }
+
+ T * get() const { QObject * obj = o; return static_cast<T*>( obj ); }
+ T * release() { return static_cast<T*>( KDAutoPointerBase::release() ); }
+
+ T * data() const { return get(); }
+ T * take() { return release(); }
+
+ void reset( T * other=0 ) { KDAutoPointerBase::reset( other ); }
+
+ T & operator*() const { return *get(); }
+ T * operator->() const { return get(); }
+
+ template <typename S>
+ bool operator==( const KDAutoPointer<S> & other ) const {
+ return get() == other.get();
+ }
+ template <typename S>
+ bool operator!=( const KDAutoPointer<S> & other ) const {
+ return get() != other.get();
+ }
+
+ KDAB_USING_SAFE_BOOL_OPERATOR( KDAutoPointerBase )
+};
+
+template <typename T>
+inline void swap( KDAutoPointer<T> & lhs, KDAutoPointer<T> & rhs ) { lhs.swap( rhs ); }
+template <typename T>
+inline void qSwap( KDAutoPointer<T> & lhs, KDAutoPointer<T> & rhs ) { lhs.swap( rhs ); }
+
+template <typename S, typename T>
+inline bool operator==( const KDAutoPointer<S> & lhs, const T * rhs ) {
+ return lhs.get() == rhs;
+}
+template <typename S, typename T>
+inline bool operator==( const S * lhs, const KDAutoPointer<T> & rhs ) {
+ return lhs == rhs.get();
+}
+template <typename S, typename T>
+inline bool operator==( const KDAutoPointer<S> & lhs, const QPointer<T> & rhs ) {
+ return lhs.get() == rhs;
+}
+template <typename S, typename T>
+inline bool operator==( const QPointer<S> & lhs, const KDAutoPointer<T> & rhs ) {
+ return lhs == rhs.get();
+}
+
+template <typename S, typename T>
+inline bool operator!=( const KDAutoPointer<S> & lhs, const T * rhs ) {
+ return !operator==( lhs, rhs );
+}
+template <typename S, typename T>
+inline bool operator!=( const S * lhs, const KDAutoPointer<T> & rhs ) {
+ return !operator==( lhs, rhs );
+}
+template <typename S, typename T>
+inline bool operator!=( const KDAutoPointer<S> & lhs, const QPointer<T> & rhs ) {
+ return !operator==( lhs, rhs );
+}
+template <typename S, typename T>
+inline bool operator!=( const QPointer<S> & lhs, const KDAutoPointer<T> & rhs ) {
+ return !operator==( lhs, rhs );
+}
+
+
+#endif /* __KDTOOLS_CORE_KDAUTOPOINTER_H__ */
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdbytesize.cpp b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdbytesize.cpp
new file mode 100644
index 000000000..0cf06f233
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdbytesize.cpp
@@ -0,0 +1,90 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+#include "kdbytesize.h"
+
+#include <QStringList>
+#include <QTextStream>
+
+KDByteSize::KDByteSize( quint64 size )
+ : m_size( size )
+{
+}
+
+KDByteSize::~KDByteSize()
+{
+}
+
+KDByteSize::operator quint64() const
+{
+ return m_size;
+}
+
+quint64 KDByteSize::size() const
+{
+ return m_size;
+}
+
+QString KDByteSize::toString() const
+{
+ static const QStringList units = QStringList() << QObject::tr( "B" )
+ << QObject::tr( "kB" )
+ << QObject::tr( "MB" )
+ << QObject::tr( "GB" )
+ << QObject::tr( "TB" );
+
+ double s = m_size;
+ quint64 factor = 1;
+ int unit = 0;
+ while( s >= 1024.0 && unit + 1 < units.count() )
+ {
+ ++unit;
+ factor *= 1024;
+ s = 1.0 * m_size / factor;
+ }
+
+ // only one digit after the decimal point is wanted
+ s = qRound( s * 10 ) / 10.0;
+
+ return QString::fromLatin1( "%L1 %2" ).arg( s, 0, 'g', 4 ).arg( units[ unit ] );
+}
+
+bool operator==( const KDByteSize& lhs, const KDByteSize& rhs )
+{
+ return lhs.size() == rhs.size();
+}
+
+bool operator<( const KDByteSize& lhs, const KDByteSize& rhs )
+{
+ return lhs.size() < rhs.size();
+}
+
+KDByteSize operator*( const KDByteSize& lhs, int rhs )
+{
+ return KDByteSize( lhs.size() * rhs );
+}
+
+#include <QDebug>
+
+QDebug operator<<( QDebug dbg, const KDByteSize& size )
+{
+ return dbg << "KDByteSize(" << size.size() << ")";
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdbytesize.h b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdbytesize.h
new file mode 100644
index 000000000..cc8f5a770
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdbytesize.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+#ifndef KDBYTESIZE_H
+#define KDBYTESIZE_H
+
+#include <KDToolsCore/kdtoolsglobal.h>
+
+class KDTOOLSCORE_EXPORT KDByteSize
+{
+public:
+ explicit KDByteSize( quint64 size = 0 );
+ virtual ~KDByteSize();
+
+ operator quint64() const;
+ quint64 size() const;
+
+ QString toString() const;
+
+private:
+ quint64 m_size;
+};
+
+KDTOOLSCORE_EXPORT bool operator==( const KDByteSize& lhs, const KDByteSize& rhs );
+KDTOOLSCORE_EXPORT bool operator<( const KDByteSize& lhs, const KDByteSize& rhs );
+KDTOOLSCORE_EXPORT KDByteSize operator*( const KDByteSize& lhs, int rhs );
+
+KDTOOLS_MAKE_RELATION_OPERATORS( KDByteSize, static inline )
+
+class QDebug;
+KDTOOLSCORE_EXPORT QDebug operator<<( QDebug dbg, const KDByteSize& size );
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdgenericfactory.cpp b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdgenericfactory.cpp
new file mode 100644
index 000000000..9352f83cd
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdgenericfactory.cpp
@@ -0,0 +1,250 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdgenericfactory.h"
+
+/*!
+ \class KDGenericFactory
+ \ingroup core
+ \brief Template based generic factory implementation
+ \since_c 2.1
+
+ (The exception safety of this class has not been evaluated yet.)
+
+ KDGenericFactory is an implemention of of the factory pattern. It can be used to
+ "produce" instances of different classes having a common superclass
+ T_Product. The user of the
+ factory registers those producable classes in the factory by using an identifier
+ (T_Identifier, defaulting to QString). That identifer can then be used to
+ produce as many instances of the registered product as he wants.
+
+ The advanced user can even choose the type of the map the factory is using to store its
+ FactoryFunctions by passing a T_Map template parameter. It defaults to QHash. KDGenericFactory
+ expects it to be a template class accepting T_Identifier and FactoryFunction as parameters.
+ Additionally it needs to provide:
+
+ \li\link QHash::const_iterator a nested %const_iterator \endlink typedef for an iterator type that when dereferenced has type ((const) reference to) FactoryFunction (Qt convention),
+ \li\link QHash::insert %insert( T_Identifier, FactoryFunction ) \endlink, which must overwrite any existing entries with the same identifier.
+ \li\link QHash::find %find( T_Identifier ) \endlink,
+ \li\link QHash::end %end() \endlink,
+ \li\link QHash::size %size() \endlink,
+ \li\link QHash::remove %remove( T_Identifier ) \endlink, and
+ \li\link QHash::keys %keys ) \endlink, returning a QList<T_Identifier>.
+
+ The only two class templates that currently match this concept are
+ QHash and QMap. QMultiHash and QMulitMap do not work, since they
+ violate the requirement on insert() above, and std::map and
+ std::unordered_map do not match because they don't have keys() and
+ because a dereferenced iterator has type
+ std::pair<const T_Identifier,FactoryFunction>
+ instead of just FactoryFunction.
+
+ \section general-use General Use
+
+ The following example shows how the general use case of KDGenericFactory looks like:
+
+ \code
+
+ class Fruit
+ {
+ };
+
+ class Apple : public Fruit
+ {
+ };
+
+ class Pear : public Fruit
+ {
+ };
+
+ int main()
+ {
+ // creates a common fruit "factory"
+ KDGenericFactory< Fruit > fruitPlantation;
+ // registers the product "Apple"
+ fruitPlantation.registerProduct< Apple >( "Apple" );
+ // registers the product "Pear"
+ fruitPlantation.registerProduct< Pear >( "Pear" );
+
+ // lets create some stuff - here comes our tasty apple:
+ Fruit* myApple = fruitPlantation.create( "Apple" );
+
+ // and a pear, please:
+ Fruit* myPear = fruitPlantation.create( "Pear" );
+
+ // ohh - that doesn't work, returns a null pointer:
+ Fruit* myCherry = fruitPlantation.create( "Cherry" );
+ }
+
+ \endcode
+*/
+
+/*!
+ \fn KDGenericFactory::~KDGenericFactory
+
+ Destructor.
+*/
+
+/*!
+ \typedef KDGenericFactory::FactoryFunction
+
+ This typedef defines a factory function producing an object of type T_Product.
+*/
+
+/*!
+ \fn KDGenericFactory::registerProduct( const T_Identifier& name )
+
+ Registers a product of type T, identified by \a name in the factory.
+ Any type with the same name gets unregistered.
+
+ If a product was registered via this method, it will be created using its
+ default constructor.
+*/
+
+/*!
+ \fn KDGenericFactory::unregisterProduct( const T_Identifier& name )
+
+ Unregisters the previously registered product identified by \a name from the factory.
+ If no such product is known, nothing is done.
+*/
+
+/*!
+ \fn KDGenericFactory::productCount() const
+
+ Returns the number of different products known to the factory.
+*/
+
+/*!
+ \fn KDGenericFactory::availableProducts() const
+
+ Returns the list of products known to the factory.
+*/
+
+/*!
+ \fn KDGenericFactory::create( const T_Identifier& name ) const
+
+ Creates and returns a product of the type identified by \a name.
+ Ownership of the product is transferred to the caller.
+*/
+
+/*!
+ \fn KDGenericFactory::registerProductionFunction( const T_Identifier& name, FactoryFunction create )
+
+ Subclasses can use this method to register their own FactoryFunction \a create to create products of
+ type T, identified by \a name. When a product is registered via this method, it will be created
+ by calling create().
+*/
+
+#ifdef KDTOOLSCORE_UNITTESTS
+
+#include <KDUnitTest/test.h>
+
+#include <QStringList>
+#include <QMap>
+
+class Fruit
+{
+public:
+ virtual ~Fruit() {}
+};
+
+class Apple : public Fruit
+{
+};
+
+class Pear : public Fruit
+{
+};
+
+std::ostream& operator<<( std::ostream& stream, const QStringList& list )
+{
+ stream << "QStringList(";
+ for( QStringList::const_iterator it = list.begin(); it != list.end(); ++it )
+ {
+ stream << " " << it->toLocal8Bit().data();
+ if( it + 1 != list.end() )
+ stream << ",";
+ }
+ stream << " )";
+ return stream;
+}
+
+class KDGenericFactoryTest : public KDUnitTest::Test {
+public:
+ KDGenericFactoryTest() : Test( "KDGenericFactory" ) {}
+ void run() {
+ doRun<QHash>();
+ doRun<QMap>();
+ }
+
+ template <template <typename U, typename V> class T_Map>
+ void doRun();
+};
+
+KDAB_EXPORT_UNITTEST( KDGenericFactoryTest, "kdcoretools" )
+
+template <template <typename U, typename V> class T_Map>
+void KDGenericFactoryTest::doRun() {
+
+ {
+ KDGenericFactory< Fruit, QString, T_Map > fruitPlantation;
+ assertEqual( fruitPlantation.productCount(), 0U );
+ assertEqual( fruitPlantation.availableProducts(), QStringList() );
+
+ fruitPlantation.template registerProduct< Apple >( QLatin1String( "Apple" ) );
+ assertEqual( fruitPlantation.productCount(), 1U );
+ assertEqual( fruitPlantation.availableProducts(), QStringList( QLatin1String( "Apple" ) ) );
+
+ fruitPlantation.template registerProduct< Pear >( QLatin1String( "Pear" ) );
+ assertEqual( fruitPlantation.productCount(), 2U );
+
+ Fruit* fruit = 0;
+ fruit = fruitPlantation.create( QLatin1String( "Apple" ) );
+ assertNotNull( fruit );
+ assertNotNull( dynamic_cast< Apple* >( fruit ) );
+
+ fruit = fruitPlantation.create( QLatin1String( "Pear" ) );
+ assertNotNull( fruit );
+ assertNotNull( dynamic_cast< Pear* >( fruit ) );
+
+ fruit = fruitPlantation.create( QLatin1String( "Cherry" ) );
+ assertNull( fruit );
+
+ fruitPlantation.unregisterProduct( QLatin1String( "Apple" ) );
+ assertEqual( fruitPlantation.productCount(), 1U );
+ assertEqual( fruitPlantation.availableProducts(), QStringList( QLatin1String( "Pear" ) ) );
+ fruit = fruitPlantation.create( QLatin1String( "Apple" ) );
+ assertNull( fruit );
+
+ fruit = fruitPlantation.create( QLatin1String( "Pear" ) );
+ assertNotNull( fruit );
+ assertNotNull( dynamic_cast< Pear* >( fruit ) );
+
+
+ fruitPlantation.unregisterProduct( QLatin1String( "Pear" ) );
+ assertEqual( fruitPlantation.productCount(), 0U );
+ fruit = fruitPlantation.create( QLatin1String( "Pear" ) );
+ assertNull( fruit );
+ }
+
+}
+#endif // KDTOOLSCORE_UNITTESTS
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdgenericfactory.h b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdgenericfactory.h
new file mode 100644
index 000000000..1a0d7f854
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdgenericfactory.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef __KDTOOLSCORE__KDGENERICFACTORY_H__
+#define __KDTOOLSCORE__KDGENERICFACTORY_H__
+
+#include <KDToolsCore/kdtoolsglobal.h>
+
+#include <QtCore/QHash>
+
+template< typename T_Product, typename T_Identifier = QString, template< typename U, typename V > class T_Map = QHash >
+class MAKEINCLUDES_EXPORT KDGenericFactory
+{
+public:
+ virtual ~KDGenericFactory()
+ {
+ }
+
+ typedef T_Product* (*FactoryFunction)();
+
+ template< typename T >
+ void registerProduct( const T_Identifier& name )
+ {
+#ifdef Q_CC_MSVC
+ FactoryFunction function = &KDGenericFactory::create<T>;
+ registerProductionFunction( name, function );
+#else
+ registerProductionFunction( name, &create<T> );
+#endif
+ }
+
+ void unregisterProduct( const T_Identifier& name )
+ {
+ map.remove( name );
+ }
+
+ unsigned int productCount() const
+ {
+ return map.size();
+ }
+
+ QList< T_Identifier > availableProducts() const
+ {
+ return map.keys();
+ }
+
+ T_Product* create( const T_Identifier& name ) const
+ {
+ const typename T_Map< T_Identifier, FactoryFunction >::const_iterator it = map.find( name );
+ if( it == map.end() )
+ return 0;
+ return (*it)();
+ }
+
+protected:
+ void registerProductionFunction( const T_Identifier& name, FactoryFunction create )
+ {
+ map.insert( name, create );
+ }
+
+private:
+ template< typename T >
+ static T_Product* create()
+ {
+ return new T;
+ }
+
+ T_Map< T_Identifier, FactoryFunction > map;
+};
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdjob.cpp b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdjob.cpp
new file mode 100644
index 000000000..d88380ffb
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdjob.cpp
@@ -0,0 +1,148 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdjob.h"
+
+#include <QEventLoop>
+
+class KDJob::Private {
+ KDJob* const q;
+public:
+ explicit Private( KDJob* qq ) : q( qq ), error( KDJob::NoError ), errorString(), caps( KDJob::NoCapabilities ), autoDelete( true ), totalAmount( 100 ), processedAmount( 0 ) {}
+
+ void delayedStart() {
+ q->doStart();
+ emit q->started( q );
+ }
+
+ void waitForSignal( const char* sig ) {
+ QEventLoop loop;
+ q->connect( q, sig, &loop, SLOT(quit()) );
+ loop.exec();
+ }
+
+ int error;
+ QString errorString;
+ KDJob::Capabilities caps;
+ bool autoDelete : 1;
+ quint64 totalAmount;
+ quint64 processedAmount;
+};
+
+KDJob::KDJob( QObject* parent ) : QObject( parent ), d( new Private( this ) ) {
+}
+
+KDJob::~KDJob() {
+ //delete d;
+}
+
+bool KDJob::autoDelete() const {
+ return d->autoDelete;
+}
+
+void KDJob::setAutoDelete( bool autoDelete ) {
+ d->autoDelete = autoDelete;
+}
+
+int KDJob::error() const {
+ return d->error;
+}
+
+QString KDJob::errorString() const {
+ return d->errorString;
+}
+
+void KDJob::emitFinished() {
+ emit finished( this );
+ if ( d->autoDelete )
+ deleteLater();
+}
+
+void KDJob::emitFinishedWithError( int error, const QString& errorString ) {
+ d->error = error;
+ d->errorString = errorString;
+ emitFinished();
+}
+
+void KDJob::setError( int error ) {
+ d->error = error;
+}
+
+void KDJob::setErrorString( const QString& errorString ) {
+ d->errorString = errorString;
+}
+
+void KDJob::waitForStarted() {
+ d->waitForSignal( SIGNAL(started(KDJob*)) );
+}
+
+void KDJob::waitForFinished() {
+ d->waitForSignal( SIGNAL(finished(KDJob*)) );
+}
+
+KDJob::Capabilities KDJob::capabilities() const {
+ return d->caps;
+}
+
+bool KDJob::hasCapability( Capability c ) const {
+ return d->caps.testFlag( c );
+}
+
+void KDJob::setCapabilities( Capabilities c ) {
+ d->caps = c;
+}
+
+void KDJob::start() {
+ QMetaObject::invokeMethod( this, "delayedStart", Qt::QueuedConnection );
+}
+
+void KDJob::doCancel() {
+}
+
+void KDJob::cancel() {
+ doCancel();
+ setError( Canceled );
+}
+
+quint64 KDJob::totalAmount() const {
+ return d->totalAmount;
+}
+
+quint64 KDJob::processedAmount() const {
+ return d->processedAmount;
+}
+
+void KDJob::setTotalAmount( quint64 amount ) {
+ if ( d->totalAmount == amount )
+ return;
+ d->totalAmount = amount;
+ emit progress( this, d->processedAmount, d->totalAmount );
+}
+
+void KDJob::setProcessedAmount( quint64 amount ) {
+ if ( d->processedAmount == amount )
+ return;
+ d->processedAmount = amount;
+ emit progress( this, d->processedAmount, d->totalAmount );
+}
+
+#include "moc_kdjob.cpp"
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdjob.h b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdjob.h
new file mode 100644
index 000000000..10cdd6899
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdjob.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef __KDTOOLS_CORE_KDJOB_H__
+#define __KDTOOLS_CORE_KDJOB_H__
+
+#include <QObject>
+
+#include <KDToolsCore/pimpl_ptr.h>
+
+class KDTOOLSCORE_EXPORT KDJob : public QObject {
+ Q_OBJECT
+ Q_PROPERTY( bool autoDelete READ autoDelete WRITE setAutoDelete )
+
+public:
+ explicit KDJob( QObject* parent=0 );
+ ~KDJob();
+
+ enum Error {
+ NoError=0,
+ Canceled=1,
+ UserDefinedError=128
+ };
+
+ enum Capability {
+ NoCapabilities=0x0,
+ Cancelable=0x1
+ };
+
+ Q_DECLARE_FLAGS(Capabilities, Capability)
+
+ int error() const;
+ QString errorString() const;
+
+ bool autoDelete() const;
+ void setAutoDelete( bool autoDelete );
+
+ Capabilities capabilities() const;
+ bool hasCapability( Capability c ) const;
+
+ void waitForStarted();
+ void waitForFinished();
+
+ quint64 totalAmount() const;
+ quint64 processedAmount() const;
+
+public Q_SLOTS:
+ void start();
+ void cancel();
+
+Q_SIGNALS:
+ void infoMessage( KDJob*, const QString& );
+
+Q_SIGNALS:
+#ifndef Q_MOC_RUN
+private: // make signals private unless moc runs
+#endif
+ void started( KDJob* );
+ void finished( KDJob* );
+ void progress( KDJob* job, quint64 processed, quint64 total );
+
+protected:
+ virtual void doStart() = 0;
+ virtual void doCancel();
+
+ void setCapabilities( Capabilities c );
+ void setTotalAmount( quint64 amount );
+ void setProcessedAmount( quint64 amount );
+
+ void setError( int error );
+ void setErrorString( const QString& errorString );
+
+ void emitFinished();
+ void emitFinishedWithError( int error, const QString& errorString );
+
+private:
+ class Private;
+ friend class ::KDJob::Private;
+ kdtools::pimpl_ptr<Private> d;
+ Q_PRIVATE_SLOT( d, void delayedStart() )
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(KDJob::Capabilities)
+
+#endif // __KDTOOLS_CORE_KDJOB_H__
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdlockfile.cpp b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdlockfile.cpp
new file mode 100644
index 000000000..234bc448e
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdlockfile.cpp
@@ -0,0 +1,90 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdlockfile.h"
+
+#include "kdlockfile_p.h"
+
+KDLockFile::Private::Private( const QString& filename_ )
+ : filename( filename_ )
+ , handle( 0 )
+ , locked( false )
+{
+}
+
+KDLockFile::KDLockFile( const QString& name )
+ : d( new Private( name ) )
+{
+}
+
+KDLockFile::~KDLockFile()
+{
+}
+
+bool KDLockFile::lock()
+{
+ return d->lock();
+}
+
+QString KDLockFile::errorString() const
+{
+ return d->errorString;
+}
+
+bool KDLockFile::unlock()
+{
+ return d->unlock();
+}
+
+
+#ifdef KDTOOLSCORE_UNITTESTS
+
+#include <KDUnitTest/Test>
+#include <QDebug>
+#include <QDir>
+
+KDAB_UNITTEST_SIMPLE( KDLockFile, "kdcoretools" ) {
+ {
+ KDLockFile f( QLatin1String("/jlksdfdsfjkldsf-doesnotexist/file") );
+ const bool locked = f.lock();
+ assertFalse( locked );
+ qDebug() << f.errorString();
+ assertTrue( !f.errorString().isEmpty() );
+ if ( !locked )
+ assertTrue( f.unlock() );
+ }
+ {
+ KDLockFile f( QDir::currentPath() + QLatin1String("/kdlockfile-test") );
+ const bool locked = f.lock();
+ assertTrue( locked );
+ if ( !locked )
+ qDebug() << f.errorString();
+ assertEqual( locked, f.errorString().isEmpty() );
+ const bool unlocked = f.unlock();
+ assertTrue( unlocked );
+ if ( !unlocked )
+ qDebug() << f.errorString();
+ assertEqual( unlocked, f.errorString().isEmpty() );
+ }
+}
+
+#endif // KDTOOLSCORE_UNITTESTS
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdlockfile.h b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdlockfile.h
new file mode 100644
index 000000000..cecbc5cbd
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdlockfile.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef __KDTOOLSCORE_KDLOCKFILE_H__
+#define __KDTOOLSCORE_KDLOCKFILE_H__
+
+#include <pimpl_ptr.h>
+
+class QString;
+
+class KDTOOLSCORE_EXPORT KDLockFile
+{
+public:
+ explicit KDLockFile( const QString & name );
+ ~KDLockFile();
+
+ QString errorString() const;
+
+ bool lock();
+ bool unlock();
+
+private:
+ Q_DISABLE_COPY(KDLockFile)
+ class Private;
+ kdtools::pimpl_ptr< Private > d;
+};
+
+#endif // __KDTOOLSCORE_KDLOCKFILE_H__
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdlockfile_p.h b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdlockfile_p.h
new file mode 100644
index 000000000..da4c4dc4c
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdlockfile_p.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef __KDTOOLSCORE_KDLOCKFILE_P_H__
+#define __KDTOOLSCORE_KDLOCKFILE_P_H__
+
+#include "kdlockfile.h"
+#include <QtCore/QString>
+#ifdef Q_OS_WIN
+#include <windows.h>
+#endif
+
+class KDLockFile::Private
+{
+public:
+ explicit Private( const QString& filename );
+ ~Private();
+ bool lock();
+ bool unlock();
+
+ QString errorString;
+
+private:
+ QString filename;
+#ifdef Q_OS_WIN
+ HANDLE handle;
+#else
+ int handle;
+#endif
+ bool locked;
+};
+
+#endif // LOCKFILE_P_H
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdlockfile_unix.cpp b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdlockfile_unix.cpp
new file mode 100644
index 000000000..e3d187cbf
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdlockfile_unix.cpp
@@ -0,0 +1,77 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdlockfile_p.h"
+
+#include <QtCore/QCoreApplication>
+
+#include <cerrno>
+
+#include <sys/file.h>
+
+KDLockFile::Private::~Private()
+{
+ unlock();
+}
+
+bool KDLockFile::Private::lock()
+{
+ if ( locked )
+ return true;
+
+ errorString.clear();
+ errno = 0;
+ handle = open( filename.toLatin1().constData(), O_CREAT | O_RDWR | O_NONBLOCK );
+ if ( handle == -1 ) {
+ errorString = QObject::tr("Could not create lock file %1: %2").arg( filename, QLatin1String( strerror( errno ) ) );
+ return false;
+ }
+ const QString pid = QString::number( qApp->applicationPid() );
+ const QByteArray data = pid.toLatin1();
+ errno = 0;
+ qint64 written = 0;
+ while ( written < data.size() ) {
+ const qint64 n = write( handle, data.constData() + written, data.size() - written );
+ if ( n < 0 ) {
+ errorString = QObject::tr("Could not write PID to lock file %1: %2").arg( filename, QLatin1String( strerror( errno ) ) );
+ return false;
+ }
+ written += n;
+ }
+ errno = 0;
+ locked = flock( handle, LOCK_NB | LOCK_EX ) != -1;
+ if ( !locked )
+ errorString = QObject::tr("Could not lock lock file %1: %2").arg( filename, QLatin1String( strerror( errno ) ) );
+ return locked;
+}
+
+bool KDLockFile::Private::unlock()
+{
+ errorString.clear();
+ if ( !locked )
+ return true;
+ errno = 0;
+ locked = flock( handle, LOCK_UN | LOCK_NB ) == -1;
+ if ( locked )
+ errorString = QObject::tr("Could not unlock lock file %1: %2").arg( filename, QLatin1String( strerror( errno ) ) );
+ return !locked;
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdlockfile_win.cpp b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdlockfile_win.cpp
new file mode 100644
index 000000000..f7fed60ab
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdlockfile_win.cpp
@@ -0,0 +1,69 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdlockfile.h"
+#include "kdlockfile_p.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QFileInfo>
+
+KDLockFile::Private::~Private()
+{
+ unlock();
+}
+
+bool KDLockFile::Private::lock()
+{
+ const QFileInfo fi( filename );
+ handle = CreateFile( filename.toStdWString().data(),
+ GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,
+ NULL, fi.exists() ? OPEN_EXISTING : CREATE_NEW,
+ FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, NULL );
+
+ if ( !handle )
+ return false;
+ QString pid = QString::number( qApp->applicationPid() );
+ QByteArray data = pid.toLatin1();
+ DWORD bytesWritten;
+ const bool wrotePid = WriteFile( handle, data.data(), data.size(), &bytesWritten, NULL );
+ if ( !wrotePid )
+ return false;
+ FlushFileBuffers( handle );
+
+ const bool locked = LockFile( handle, 0, 0, fi.size(), 0 );
+
+ this->locked = locked;
+ return locked;
+}
+
+bool KDLockFile::Private::unlock()
+{
+ const QFileInfo fi( filename );
+ if ( locked )
+ {
+ const bool success = UnlockFile( handle, 0, 0, 0, fi.size() );
+ this->locked = !success;
+ CloseHandle( handle );
+ return success;
+ }
+ return true;
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdmetamethoditerator.cpp b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdmetamethoditerator.cpp
new file mode 100644
index 000000000..1a0b863c7
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdmetamethoditerator.cpp
@@ -0,0 +1,493 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdmetamethoditerator.h"
+
+/*!
+ \class KDMetaMethodIterator
+ \ingroup core
+ \brief Iterator over methods of QObjects
+ \since_c 2.3
+
+ KDMetaMethodIterator provides a way over all methods of a QObject which can be accessed via Qt's meta
+ object system. It is possible to filter on types of methods (Q_INVOKABLE methods, signals, slots,
+ constructors) and on access types (public, protected, private). Furthermore, KDMetaMethodIterator can
+ be configured to filter methods of the given object's base class or all methods provided by QObject.
+
+ \section general-use General Use
+
+ The following example shows a general use case of KDMetaMethodIterator:
+
+ \code
+
+ class QIODeviceWrapper : public QIODevice
+ {
+ Q_OBJECT
+ public:
+ QIODeviceWrapper( QIODevice* nestedDevice )
+ : nested( nestedDevice )
+ {
+ // make sure all signals of the nested QIODevice are forwarded,
+ // but make sure not to connect QObject's own destroyed() signal,
+ // therefore use KDMetaMethodIterator::IgnoreQObjectMethods
+ KDMetaMethodIterator it( QIODevice::staticMetaObject, KDMetaMethodIterator::Signal, KDMetaMethodIterator::IgnoreQObjectMethods );
+ while( it.hasNext() )
+ {
+ it.next();
+ connect( nested, it.connectableSignature(), this, it.connectableSignature() );
+ }
+ }
+
+ protected:
+ // virtual methods needed to access the contents...
+
+ private:
+ QIODevice* const nested;
+ };
+
+ \endcode
+*/
+
+/*!
+ \enum KDMetaMethodIterator::AccessType
+ This enum describes the access type of methods to iterate:
+*/
+
+/*!
+ \var KDMetaMethodIterator::Private
+ Iterate over private methods.
+*/
+
+/*!
+ \var KDMetaMethodIterator::Protected
+ Iterate over protected methods.
+*/
+
+/*!
+ \var KDMetaMethodIterator::Public
+ Iterate over public methods.
+*/
+
+/*!
+ \var KDMetaMethodIterator::AllAccessTypes
+ Iterate over methods of all access types.
+*/
+
+/*!
+ \enum KDMetaMethodIterator::MethodType
+ This enum describes the type of methods to iterate:
+*/
+
+/*!
+ \var KDMetaMethodIterator::Method
+ Iterate over methods marked with Q_INVOKABLE
+*/
+
+/*!
+ \var KDMetaMethodIterator::Signal
+ Iterate over signals.
+*/
+
+/*!
+ \var KDMetaMethodIterator::Slot
+ Iterate over slots.
+*/
+
+/*!
+ \var KDMetaMethodIterator::Constructor
+ Iterate over constructors marked with Q_INVOKABLE.
+*/
+
+/*!
+ \var KDMetaMethodIterator::AllMethodTypes
+ Iterate over all supported method types.
+*/
+
+/*!
+ \enum KDMetaMethodIterator::IteratorFlag
+ This enum describes flags which can be passed to KDMetaMethodIterator:
+*/
+
+/*!
+ \var KDMetaMethodIterator::NoFlags
+ No flags set, only type filtering takes place.
+*/
+
+/*!
+ \var KDMetaMethodIterator::IgnoreQObjectMethods
+ KDMetaMethodIterator will not iterate over methods provided by QObject itself.
+*/
+
+/*!
+ \var KDMetaMethodIterator::IgnoreSuperClassMethods
+ KDMetaMethodIterator will only iterate over methods provided by the passed class instance itself, ignoring any base classes.
+*/
+
+/*!
+ \internal
+ */
+class KDMetaMethodIterator::Priv
+{
+public:
+ Priv( const QMetaObject* object, MethodTypes types, AccessTypes access, IteratorFlags flags )
+ : index( -1 ),
+ m( types ),
+ a( access ),
+ f( flags ),
+ metaObject( object )
+ {
+ }
+
+ Priv( const QMetaObject* object, MethodTypes types, IteratorFlags flags )
+ : index( -1 ),
+ m( types ),
+ a( ( types & Signal ) ? ( Protected | Public ) : Public ),
+ f( flags ),
+ metaObject( object )
+ {
+ }
+
+ bool filterMatches( const QMetaMethod& method, int index ) const;
+
+ int index;
+ const MethodTypes m;
+ const AccessTypes a;
+ const IteratorFlags f;
+ const QMetaObject* const metaObject;
+
+ mutable QByteArray connectableSignature;
+};
+
+/*!
+ Creates a new KDMetaMethodIterator iterating over \a metaObject. The iterator will only return methods of the given \a types.
+ By default, only public methods will be returned. If \a types contains Signal, the access type filter will automatically set
+ to return protected and public.
+
+ By default, \a flags is NoFlags, which lists all methods.
+ */
+KDMetaMethodIterator::KDMetaMethodIterator( const QMetaObject& metaObject, MethodTypes types, IteratorFlags flags )
+ : d( new Priv( &metaObject, types, flags ) )
+{
+}
+
+/*!
+ Creates a new KDMetaMethodIterator iterating over \a metaObject. The iterator will only return methods of the given \a types,
+ matching the \a access mode.
+
+ By default, \a flags is NoFlags, which lists all methods.
+
+ \overload
+ */
+KDMetaMethodIterator::KDMetaMethodIterator( const QMetaObject& metaObject, MethodTypes types, AccessType access, IteratorFlags flags )
+ : d( new Priv( &metaObject, types, access, flags ) )
+{
+}
+
+/*!
+ Creates a new KDMetaMethodIterator iterating over \a metaObject. The iterator will only return methods matching the \a access mode.
+
+ By default, \a flags is NoFlags, which lists all methods.
+
+ \overload
+ */
+KDMetaMethodIterator::KDMetaMethodIterator( const QMetaObject& metaObject, AccessType access, IteratorFlags flags )
+ : d( new Priv( &metaObject, AllMethodTypes, access, flags ) )
+{
+}
+
+/*!
+ Creates a new KDMetaMethodIterator iterating over \a metaObject. The iterator will only return methods of the given \a types.
+ By default, only public methods will be returned. If \a types contains Signal, the access type filter will automatically set
+ to return protected and public.
+
+ By default, \a flags is NoFlags, which lists all methods.
+
+ \overload
+ */
+KDMetaMethodIterator::KDMetaMethodIterator( const QMetaObject* metaObject, MethodTypes types, IteratorFlags flags )
+ : d( new Priv( metaObject, types, flags ) )
+{
+}
+
+/*!
+ Creates a new KDMetaMethodIterator iterating over \a metaObject. The iterator will only return methods of the given \a types,
+ matching the \a access mode.
+
+ By default, \a flags is NoFlags, which lists all methods.
+
+ \overload
+ */
+KDMetaMethodIterator::KDMetaMethodIterator( const QMetaObject* metaObject, MethodTypes types, AccessType access, IteratorFlags flags )
+ : d( new Priv( metaObject, types, access, flags ) )
+{
+}
+
+/*!
+ Creates a new KDMetaMethodIterator iterating over \a metaObject. The iterator will only return methods matching the \a access mode.
+
+ By default, \a flags is NoFlags, which lists all methods.
+
+ \overload
+ */
+KDMetaMethodIterator::KDMetaMethodIterator( const QMetaObject* metaObject, AccessType access, IteratorFlags flags )
+ : d( new Priv( metaObject, AllMethodTypes, access, flags ) )
+{
+}
+
+/*!
+ Creates a new KDMetaMethodIterator iterating over \a object. The iterator will only return methods of the given \a types.
+ By default, only public methods will be returned. If \a types contains Signal, the access type filter will automatically set
+ to return protected and public.
+
+ By default, \a flags is NoFlags, which lists all methods.
+
+ \overload
+ */
+KDMetaMethodIterator::KDMetaMethodIterator( const QObject* object, MethodTypes types, IteratorFlags flags )
+ : d( new Priv( object->metaObject(), types, flags ) )
+{
+}
+
+/*!
+ Creates a new KDMetaMethodIterator iterating over \a object. The iterator will only return methods of the given \a types,
+ matching the \a access mode.
+
+ By default, \a flags is NoFlags, which lists all methods.
+
+ \overload
+ */
+KDMetaMethodIterator::KDMetaMethodIterator( const QObject* object, MethodTypes types, AccessType access, IteratorFlags flags )
+ : d( new Priv( object->metaObject(), types, access, flags ) )
+{
+}
+
+/*!
+ Creates a new KDMetaMethodIterator iterating over \a object. The iterator will only return methods matching the \a access mode.
+
+ By default, \a flags is NoFlags, which lists all methods.
+
+ \overload
+ */
+KDMetaMethodIterator::KDMetaMethodIterator( const QObject* object, AccessType access, IteratorFlags flags )
+ : d( new Priv( object->metaObject(), AllMethodTypes, access, flags ) )
+{
+}
+
+/*!
+ Destroys the KDMetaMethodIterator.
+ */
+KDMetaMethodIterator::~KDMetaMethodIterator()
+{
+}
+
+/*!
+ Returns true if there is at least one item ahead of the iterator, i.e. the iterator is not at the back of the method list; otherwise returns false.
+ */
+bool KDMetaMethodIterator::hasNext() const
+{
+ for( int i = d->index + 1; i < d->metaObject->methodCount(); ++i )
+ {
+ const QMetaMethod method = d->metaObject->method( i );
+ if( d->filterMatches( method, i ) )
+ return true;
+ }
+ return false;
+}
+
+/*!
+ Returns the next method and advances the iterator by one position.
+ */
+QMetaMethod KDMetaMethodIterator::next()
+{
+ Q_ASSERT( hasNext() );
+ d->connectableSignature.clear();
+ for( ++d->index; d->index < d->metaObject->methodCount(); ++d->index )
+ {
+ const QMetaMethod method = d->metaObject->method( d->index );
+ if( d->filterMatches( method, d->index ) )
+ return method;
+ }
+ return QMetaMethod();
+}
+
+/*!
+ Returns the current method's signature ready to be passed to QObject::connect, i.e. already passed through the SIGNAL or SLOT macro.
+ The return value stays valid up to the following next() call. This is only valid for signals and slots.
+ */
+const char* KDMetaMethodIterator::connectableSignature() const
+{
+ if( d->connectableSignature.isEmpty() )
+ {
+ const QMetaMethod method = d->metaObject->method( d->index );
+ d->connectableSignature = method.signature();
+ d->connectableSignature.push_front( QString::number( ( static_cast< int >( method.methodType() ) - 3 ) * -1 ).toLocal8Bit() );
+ }
+ return d->connectableSignature.constData();
+}
+
+/*!
+ Returns true if \a method matches the filters set on the iterator, currently pointing to \a index.
+ \internal
+ */
+bool KDMetaMethodIterator::Priv::filterMatches( const QMetaMethod& method, int index ) const
+{
+ // filter QObject's own methods
+ if( ( f & IgnoreQObjectMethods ) && index < QObject::staticMetaObject.methodCount() )
+ return false;
+
+ // filter any super classes methods
+ if( ( f & IgnoreSuperClassMethods ) && index < metaObject->methodOffset() )
+ return false;
+
+ // filter any methods with unwanted access types
+ if( ( ( 1 << method.access() ) & a ) == 0 )
+ return false;
+
+ // filter any methods with unwanted method types
+ return ( ( 1 << method.methodType() ) & m ) != 0;
+}
+
+#ifdef KDTOOLSCORE_UNITTESTS
+
+#include <KDUnitTest/Test>
+
+class TestClass : public QObject
+{
+ Q_OBJECT
+public:
+ TestClass(){}
+
+public Q_SLOTS:
+ void publicSlot( int ) {}
+
+protected Q_SLOTS:
+ void protectedSlot( int ) {}
+
+private Q_SLOTS:
+ void privateSlot( int ) {}
+
+private:
+ Q_PRIVATE_SLOT( d, void veryPrivateSlot() )
+
+ class Private;
+ kdtools::pimpl_ptr< Private > d;
+};
+
+class TestClassDerived : public TestClass
+{
+ Q_OBJECT
+public:
+ TestClassDerived(){}
+};
+
+class TestClass::Private
+{
+public:
+ void veryPrivateSlot() {}
+};
+
+KDAB_UNITTEST_SIMPLE( KDMetaMethodIterator, "kdcoretools" ) {
+
+ QObject o;
+ {
+ KDMetaMethodIterator it( &o, KDMetaMethodIterator::Signal );
+ assertTrue( it.hasNext() );
+ assertEqual( std::string( it.next().signature() ), "destroyed(QObject*)" );
+ assertTrue( it.hasNext() );
+ assertEqual( std::string( it.next().signature() ), "destroyed()" );
+ assertFalse( it.hasNext() );
+ }
+ {
+ KDMetaMethodIterator it( QObject::staticMetaObject, KDMetaMethodIterator::Signal );
+ assertTrue( it.hasNext() );
+ assertEqual( std::string( it.next().signature() ), "destroyed(QObject*)" );
+ }
+ {
+ KDMetaMethodIterator it( o.metaObject(), KDMetaMethodIterator::Signal );
+ assertTrue( it.hasNext() );
+ assertEqual( std::string( it.next().signature() ), "destroyed(QObject*)" );
+ }
+
+ {
+ KDMetaMethodIterator it( TestClass::staticMetaObject, KDMetaMethodIterator::Signal );
+ assertTrue( it.hasNext() );
+ assertEqual( std::string( it.next().signature() ), "destroyed(QObject*)" );
+ assertTrue( it.hasNext() );
+ assertEqual( std::string( it.next().signature() ), "destroyed()" );
+ assertEqual( std::string( it.connectableSignature() ), "2destroyed()" );
+ assertFalse( it.hasNext() );
+ }
+
+ {
+ KDMetaMethodIterator it( TestClass::staticMetaObject, KDMetaMethodIterator::Signal, KDMetaMethodIterator::IgnoreQObjectMethods );
+ assertFalse( it.hasNext() );
+ }
+ {
+ KDMetaMethodIterator it( TestClass::staticMetaObject, KDMetaMethodIterator::Signal, KDMetaMethodIterator::IgnoreSuperClassMethods );
+ assertFalse( it.hasNext() );
+ }
+ {
+ KDMetaMethodIterator it( TestClass::staticMetaObject, KDMetaMethodIterator::Slot );
+ assertTrue( it.hasNext() );
+ assertEqual( std::string( it.next().signature() ), "deleteLater()" );
+ assertTrue( it.hasNext() );
+ assertEqual( std::string( it.next().signature() ), "publicSlot(int)" );
+ assertEqual( std::string( it.connectableSignature() ), "1publicSlot(int)" );
+ assertFalse( it.hasNext() );
+ }
+ {
+ KDMetaMethodIterator it( TestClass::staticMetaObject, KDMetaMethodIterator::Slot, KDMetaMethodIterator::IgnoreQObjectMethods );
+ assertTrue( it.hasNext() );
+ assertEqual( std::string( it.next().signature() ), "publicSlot(int)" );
+ assertFalse( it.hasNext() );
+ }
+ {
+ KDMetaMethodIterator it( TestClass::staticMetaObject, KDMetaMethodIterator::Slot, KDMetaMethodIterator::Protected, KDMetaMethodIterator::IgnoreQObjectMethods );
+ assertTrue( it.hasNext() );
+ assertEqual( std::string( it.next().signature() ), "protectedSlot(int)" );
+ assertFalse( it.hasNext() );
+ }
+ {
+ KDMetaMethodIterator it( TestClass::staticMetaObject, KDMetaMethodIterator::Slot, KDMetaMethodIterator::Private, KDMetaMethodIterator::IgnoreQObjectMethods );
+ assertTrue( it.hasNext() );
+ assertEqual( std::string( it.next().signature() ), "privateSlot(int)" );
+ assertEqual( std::string( it.next().signature() ), "veryPrivateSlot()" );
+ assertFalse( it.hasNext() );
+ }
+
+ {
+ KDMetaMethodIterator it( TestClassDerived::staticMetaObject, KDMetaMethodIterator::Slot, KDMetaMethodIterator::Private, KDMetaMethodIterator::IgnoreQObjectMethods );
+ assertTrue( it.hasNext() );
+ assertEqual( std::string( it.next().signature() ), "privateSlot(int)" );
+ assertEqual( std::string( it.next().signature() ), "veryPrivateSlot()" );
+ assertFalse( it.hasNext() );
+ }
+ {
+ KDMetaMethodIterator it( TestClassDerived::staticMetaObject, KDMetaMethodIterator::Slot, KDMetaMethodIterator::Private, KDMetaMethodIterator::IgnoreSuperClassMethods );
+ assertFalse( it.hasNext() );
+ }
+
+}
+
+#include "kdmetamethoditerator.moc"
+
+#endif // KDTOOLSCORE_UNITTESTS
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdmetamethoditerator.h b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdmetamethoditerator.h
new file mode 100644
index 000000000..94bb8f707
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdmetamethoditerator.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef __KDTOOLSCORE_KDMETAMETHODITERATOR_H__
+#define __KDTOOLSCORE_KDMETAMETHODITERATOR_H__
+
+#include <KDToolsCore/pimpl_ptr.h>
+
+#include <QtCore/QMetaMethod>
+
+class KDTOOLSCORE_EXPORT KDMetaMethodIterator
+{
+public:
+ enum AccessType
+ {
+ Private = 1 << QMetaMethod::Private,
+ Protected = 1 << QMetaMethod::Protected,
+ Public = 1 << QMetaMethod::Public,
+ AllAccessTypes = Private | Protected | Public
+ };
+ Q_DECLARE_FLAGS( AccessTypes, AccessType )
+
+ enum MethodType
+ {
+ Method = 0x1,
+ Signal = 0x2,
+ Slot = 0x4,
+ Constructor = 0x8,
+ AllMethodTypes = Method | Signal | Slot | Constructor
+ };
+ Q_DECLARE_FLAGS( MethodTypes, MethodType )
+
+ enum IteratorFlag
+ {
+ NoFlags = 0x00,
+ IgnoreQObjectMethods = 0x01,
+ IgnoreSuperClassMethods = 0x02
+ };
+ Q_DECLARE_FLAGS( IteratorFlags, IteratorFlag )
+
+ explicit KDMetaMethodIterator( const QMetaObject& metaObject, MethodTypes types = AllMethodTypes, IteratorFlags flags = NoFlags );
+ KDMetaMethodIterator( const QMetaObject& metaObject, MethodTypes types, AccessType access, IteratorFlags flags = NoFlags );
+ KDMetaMethodIterator( const QMetaObject& metaObject, AccessType access, IteratorFlags flags = NoFlags );
+
+ explicit KDMetaMethodIterator( const QMetaObject* metaObject, MethodTypes types = AllMethodTypes, IteratorFlags flags = NoFlags );
+ KDMetaMethodIterator( const QMetaObject* metaObject, MethodTypes types, AccessType access, IteratorFlags flags = NoFlags );
+ KDMetaMethodIterator( const QMetaObject* metaObject, AccessType access, IteratorFlags flags = NoFlags );
+
+ explicit KDMetaMethodIterator( const QObject* object, MethodTypes types = AllMethodTypes, IteratorFlags flags = NoFlags );
+ KDMetaMethodIterator( const QObject* object, MethodTypes types, AccessType access, IteratorFlags flags = NoFlags );
+ KDMetaMethodIterator( const QObject* object, AccessType access, IteratorFlags flags = NoFlags );
+
+ ~KDMetaMethodIterator();
+
+ bool hasNext() const;
+ QMetaMethod next();
+
+ const char* connectableSignature() const;
+
+private:
+ class Priv;
+ kdtools::pimpl_ptr< Priv > d;
+};
+
+
+#endif // __KDTOOLSCORE_KDMETAMETHODITERATOR_H__
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdrunoncechecker.cpp b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdrunoncechecker.cpp
new file mode 100644
index 000000000..457a6215a
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdrunoncechecker.cpp
@@ -0,0 +1,133 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdrunoncechecker.h"
+#include "kdlockfile.h"
+#include "kdsysinfo.h"
+
+#include <QtCore/QList>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+
+#include <algorithm>
+
+class KDRunOnceChecker::Private
+{
+public:
+ Private( const QString& filename );
+ ~Private();
+ KDLockFile m_lockfile;
+ bool m_hasLock;
+};
+
+KDRunOnceChecker::Private::Private( const QString& filename )
+ : m_lockfile( filename )
+ , m_hasLock( false )
+{
+
+}
+
+KDRunOnceChecker::Private::~Private()
+{
+
+}
+
+KDRunOnceChecker::KDRunOnceChecker( const QString& filename )
+ :d( new Private( filename ) )
+{
+
+}
+
+KDRunOnceChecker::~KDRunOnceChecker()
+{
+
+}
+
+class ProcessnameEquals
+{
+public:
+ ProcessnameEquals( const QString& name ): m_name( name ){}
+ bool operator()( const KDSysInfo::ProcessInfo& info )
+ {
+#ifndef Q_WS_WIN
+ if( info.name == m_name )
+ return true;
+ const QFileInfo fi( info.name );
+ if( fi.fileName() == m_name || fi.baseName() == m_name )
+ return true;
+ return false;
+#else
+ if( info.name.toLower() == m_name.toLower() )
+ return true;
+ if( info.name.toLower() == QDir::toNativeSeparators(m_name.toLower()) )
+ return true;
+ const QFileInfo fi( info.name );
+ if( fi.fileName().toLower() == m_name.toLower() || fi.baseName().toLower() == m_name.toLower() )
+ return true;
+ return info.name == m_name;
+#endif
+ }
+
+private:
+ QString m_name;
+};
+
+bool KDRunOnceChecker::isRunning( Dependencies depends )
+{
+ bool running = false;
+ switch ( depends )
+ {
+ case( Lockfile ):
+ {
+ const bool locked = d->m_hasLock || d->m_lockfile.lock();
+ if ( locked )
+ d->m_hasLock = true;
+ running = running || ! locked;
+ }
+ break;
+ case( ProcessList ):
+ {
+ const QList< KDSysInfo::ProcessInfo > allProcesses = KDSysInfo::runningProcesses();
+ const QString appName = qApp->applicationFilePath();
+ //QList< KDSysInfo::ProcessInfo >::const_iterator it = std::find_if( allProcesses.constBegin(), allProcesses.constEnd(), ProcessnameEquals( appName ) );
+ const int count = std::count_if( allProcesses.constBegin(), allProcesses.constEnd(), ProcessnameEquals( appName ) );
+ running = running || /*it != allProcesses.constEnd()*/count > 1;
+ }
+ break;
+ case( BOTH ):
+ {
+ const QList< KDSysInfo::ProcessInfo > allProcesses = KDSysInfo::runningProcesses();
+ const QString appName = qApp->applicationFilePath();
+ //QList< KDSysInfo::ProcessInfo >::const_iterator it = std::find_if( allProcesses.constBegin(), allProcesses.constEnd(), ProcessnameEquals( appName ) );
+ const int count = std::count_if( allProcesses.constBegin(), allProcesses.constEnd(), ProcessnameEquals( appName ) );
+ const bool locked = d->m_hasLock || d->m_lockfile.lock();
+ if ( locked )
+ d->m_hasLock = true;
+ running = running || ( /*it != allProcesses.constEnd()*/count > 1 && !locked );
+
+ }
+ break;
+ }
+
+ return running;
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdrunoncechecker.h b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdrunoncechecker.h
new file mode 100644
index 000000000..9e562d3cf
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdrunoncechecker.h
@@ -0,0 +1,46 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef __KDTOOLS_RUNONCECHECKER_H__
+#define __KDTOOLS_RUNONCECHECKER_H__
+
+#include <KDToolsCore/pimpl_ptr>
+
+#include <QtCore/QString>
+
+class KDTOOLSCORE_EXPORT KDRunOnceChecker
+{
+
+public:
+ enum Dependencies{ ProcessList, Lockfile, BOTH };
+ explicit KDRunOnceChecker( const QString& filename = QString() );
+ ~KDRunOnceChecker();
+ bool isRunning( Dependencies depends );
+
+private:
+ Q_DISABLE_COPY(KDRunOnceChecker)
+ class Private;
+ kdtools::pimpl_ptr< Private > d;
+
+};
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdsavefile.cpp b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdsavefile.cpp
new file mode 100644
index 000000000..38a4b87bf
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdsavefile.cpp
@@ -0,0 +1,476 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdsavefile.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QPointer>
+#include <QtCore/QTemporaryFile>
+
+#ifdef Q_OS_WIN
+# include <io.h>
+#endif
+#include <memory>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+static int permissionsToMode( QFile::Permissions p, bool* ok ) {
+ Q_ASSERT( ok );
+ int m = 0;
+#ifdef Q_OS_WIN
+ //following qfsfileengine_win.cpp: QFSFileEngine::setPermissions()
+ if ( p & QFile::ReadOwner || p & QFile::ReadUser || p & QFile::ReadGroup || p & QFile::ReadOther )
+ m |= _S_IREAD;
+ if ( p & QFile::WriteOwner || p & QFile::WriteUser || p & QFile::WriteGroup || p & QFile::WriteOther )
+ m |= _S_IWRITE;
+ *ok = m != 0;
+#else
+ if ( p & QFile::ReadUser )
+ m |= S_IRUSR;
+ if ( p & QFile::WriteUser )
+ m |= S_IWUSR;
+ if ( p & QFile::ExeUser)
+ m |= S_IXUSR;
+ if ( p & QFile::ReadGroup )
+ m |= S_IRGRP;
+ if ( p & QFile::WriteGroup )
+ m |= S_IWGRP;
+ if ( p & QFile::ExeGroup )
+ m |= S_IXGRP;
+ if ( p & QFile::ReadOther )
+ m |= S_IROTH;
+ if ( p & QFile::WriteOther )
+ m |= S_IWOTH;
+ if ( p & QFile::ExeOther )
+ m |= S_IXOTH;
+ *ok = true;
+#endif
+ return m;
+}
+
+static bool sync( int fd ) {
+#ifdef Q_OS_WIN
+ return _commit( fd ) == 0;
+#else
+ return fsync( fd ) == 0;
+#endif
+}
+
+static QString makeAbsolute( const QString& path ) {
+ if ( QDir::isAbsolutePath( path ) )
+ return path;
+ return QDir::currentPath() + QLatin1String("/") + path;
+}
+
+static int myOpen( const QString& path, int flags, int mode ) {
+#ifdef Q_OS_WIN
+ int fd;
+ _wsopen_s( &fd, reinterpret_cast<const wchar_t*>( path.utf16() ), flags, _SH_DENYRW, mode );
+ return fd;
+#else
+ return open( QFile::encodeName( path ).constData(), flags, mode );
+#endif
+}
+
+static void myClose( int fd ) {
+#ifdef Q_OS_WIN
+ _close( fd );
+#else
+ close( fd );
+#endif
+}
+
+static bool touchFile( const QString& path, QFile::Permissions p ) {
+ bool ok;
+ const int mode = permissionsToMode( p, &ok );
+ if ( !ok )
+ return false;
+ const int fd = myOpen( QDir::toNativeSeparators( path ), O_WRONLY|O_CREAT, mode );
+ if ( fd < 0 )
+ {
+ QFile file( path );
+ if( !file.open( QIODevice::WriteOnly ) )
+ return false;
+ if( !file.setPermissions( p ) ) {
+ QFile::remove( path );
+ return false;
+ }
+ return true;
+ }
+ sync( fd );
+ myClose( fd );
+ return true;
+}
+
+static QFile* createFile( const QString& path, QIODevice::OpenMode m, QFile::Permissions p, bool* openOk ) {
+ Q_ASSERT( openOk );
+ if ( !touchFile( path, p ) )
+ return 0;
+ std::auto_ptr<QFile> file( new QFile( path ) );
+ *openOk = file->open( m | QIODevice::Append );
+ if ( !*openOk )
+ QFile::remove( path ); // try to remove empty file
+ return file.release();
+}
+
+/*!
+ Generates a temporary file name based on template \a path
+ \internal
+ */
+static QString generateTempFileName( const QString& path )
+{
+ const QString tmp = path + QLatin1String( "tmp.dsfdf.%1" ); //TODO: use random suffix
+ int count = 1;
+ while ( QFile::exists( tmp.arg( count ) ) )
+ ++count;
+ return tmp.arg( count );
+}
+
+/*!
+ \class KDSaveFile KDSaveFile
+ \ingroup core
+ \brief Secure and robust writing to a file
+
+*/
+
+class KDSaveFile::Private {
+ KDSaveFile* const q;
+public:
+ explicit Private( const QString& fname, KDSaveFile* qq ) : q( qq ),
+#ifdef Q_OS_WIN
+ backupExtension( QLatin1String(".bak") ),
+#else
+ backupExtension( QLatin1String("~") ),
+#endif
+ permissions( QFile::ReadUser|QFile::WriteUser), filename( fname ), tmpFile() {
+ //TODO respect umask instead of hardcoded default permissions
+ }
+
+ ~Private() {
+ deleteTempFile();
+ }
+
+ bool deleteTempFile() {
+ if ( !tmpFile )
+ return true;
+ const QString name = tmpFile->fileName();
+ delete tmpFile;
+ //force a real close by deleting the object, before deleting the actual file. Needed on Windows
+ QFile tmp( name );
+ return tmp.remove();
+ }
+
+ bool recreateTemporaryFile( QIODevice::OpenMode mode ) {
+ deleteTempFile();
+ bool ok;
+ tmpFile = createFile( generateTempFileName( filename ), mode, permissions, &ok );
+ QObject::connect( tmpFile, SIGNAL(aboutToClose()), q, SIGNAL(aboutToClose()) );
+ QObject::connect( tmpFile, SIGNAL(bytesWritten(qint64)), q, SIGNAL(bytesWritten(qint64)) );
+ QObject::connect( tmpFile, SIGNAL(readChannelFinished()), q, SIGNAL(readChannelFinished()) );
+ QObject::connect( tmpFile, SIGNAL(readyRead()), q, SIGNAL(readyRead()) );
+ return ok;
+ }
+
+ QString generateBackupName() const {
+ const QString bf = filename + backupExtension;
+ if ( !QFile::exists( bf ) )
+ return bf;
+ int count = 1;
+ while ( QFile::exists( bf + QString::number( count ) ) )
+ ++count;
+ return bf + QString::number( count );
+ }
+
+ void propagateErrors() {
+ if ( !tmpFile )
+ return;
+ q->setErrorString( tmpFile->errorString() );
+ }
+ QString backupExtension;
+ QFile::Permissions permissions;
+ QString filename;
+ QPointer<QFile> tmpFile;
+};
+
+KDSaveFile::KDSaveFile( const QString& filename, QObject* parent ) : QIODevice( parent ), d( new Private( makeAbsolute( filename ), this ) ) {
+}
+
+KDSaveFile::~KDSaveFile() {
+}
+
+void KDSaveFile::close() {
+ d->deleteTempFile();
+ QIODevice::close();
+}
+
+bool KDSaveFile::open( OpenMode mode ) {
+ setOpenMode( QIODevice::NotOpen );
+ if ( mode & QIODevice::Append ) {
+ setErrorString( tr("Append mode not supported.") );
+ return false;
+ }
+
+ if ( ( mode & QIODevice::WriteOnly ) == 0 ) {
+ setErrorString( tr("Read-only access not supported.") );
+ return false;
+ }
+
+ // for some reason this seems to be problematic... let's remove it for now, will break in commit anyhow, if it's serious
+ //if ( QFile::exists( d->filename ) && !QFileInfo( d->filename ).isWritable() ) {
+ // setErrorString( tr("The target file %1 exists and is not writable").arg( d->filename ) );
+ // return false;
+ //}
+ const bool opened = d->recreateTemporaryFile( mode );
+ if ( opened ) {
+ setOpenMode( mode );
+ }
+
+ //if target file already exists, apply permissions of existing file to temp file
+ return opened;
+}
+
+bool KDSaveFile::atEnd() {
+ return d->tmpFile ? d->tmpFile->atEnd() : QIODevice::atEnd();
+}
+
+qint64 KDSaveFile::bytesAvailable() const {
+ return d->tmpFile ? d->tmpFile->bytesAvailable() : QIODevice::bytesAvailable();
+}
+
+qint64 KDSaveFile::bytesToWrite() const {
+ return d->tmpFile ? d->tmpFile->bytesToWrite() : QIODevice::bytesToWrite();
+}
+
+bool KDSaveFile::canReadLine() const {
+ return d->tmpFile ? d->tmpFile->canReadLine() : QIODevice::canReadLine();
+}
+
+bool KDSaveFile::isSequential() const {
+ return d->tmpFile ? d->tmpFile->isSequential() : QIODevice::isSequential();
+}
+
+qint64 KDSaveFile::pos() const {
+ return d->tmpFile ? d->tmpFile->pos() : QIODevice::pos();
+}
+
+bool KDSaveFile::reset() {
+ return d->tmpFile ? d->tmpFile->reset() : QIODevice::reset();
+}
+
+bool KDSaveFile::seek( qint64 pos ) {
+ const bool ret = d->tmpFile ? d->tmpFile->seek( pos ) : QIODevice::seek( pos );
+ if ( !ret )
+ d->propagateErrors();
+ return ret;
+}
+
+qint64 KDSaveFile::size() const {
+ return d->tmpFile ? d->tmpFile->size() : QIODevice::size();
+}
+
+bool KDSaveFile::waitForBytesWritten( int msecs ) {
+ return d->tmpFile ? d->tmpFile->waitForBytesWritten( msecs ) : QIODevice::waitForBytesWritten( msecs );
+}
+
+bool KDSaveFile::waitForReadyRead( int msecs ) {
+ return d->tmpFile ? d->tmpFile->waitForReadyRead( msecs ) : QIODevice::waitForReadyRead( msecs );
+}
+
+bool KDSaveFile::commit( KDSaveFile::CommitMode mode ) {
+ if ( !d->tmpFile )
+ return false;
+ const QString tmpfname = d->tmpFile->fileName();
+ d->tmpFile->flush();
+ delete d->tmpFile;
+ QFile orig( d->filename );
+ QString backup;
+ if ( orig.exists() ) {
+ backup = d->generateBackupName();
+ if ( !orig.rename( backup ) ) {
+ setErrorString( tr("Could not backup existing file %1: %2").arg( d->filename, orig.errorString() ) );
+ QFile tmp( tmpfname );
+ if ( !tmp.remove() ) // TODO how to report this error?
+ qWarning() << "Could not remove temp file" << tmpfname << tmp.errorString();
+ if ( mode != OverwriteExistingFile )
+ return false;
+ }
+ }
+ QFile target( tmpfname );
+ if ( !target.rename( d->filename ) ) {
+ setErrorString( target.errorString() );
+ return false;
+ }
+ if ( mode == OverwriteExistingFile ) {
+ QFile tmp( backup );
+ const bool removed = !tmp.exists() || tmp.remove( backup );
+ if ( !removed )
+ qWarning() << "Could not remove the backup: " << tmp.errorString();
+ }
+
+ return true;
+}
+
+QString KDSaveFile::fileName() const {
+ return d->filename;
+}
+
+void KDSaveFile::setFileName( const QString& filename ) {
+ const QString fn = makeAbsolute( filename );
+ if ( fn == d->filename )
+ return;
+ close();
+ delete d->tmpFile;
+ d->filename = fn;
+}
+
+qint64 KDSaveFile::readData( char* data, qint64 maxSize ) {
+ if ( !d->tmpFile ) {
+ setErrorString( tr("TODO") );
+ return -1;
+ }
+ const qint64 ret = d->tmpFile->read( data, maxSize );
+ d->propagateErrors();
+ return ret;
+}
+
+qint64 KDSaveFile::readLineData( char* data, qint64 maxSize ) {
+ if ( !d->tmpFile ) {
+ setErrorString( tr("TODO") );
+ return -1;
+ }
+ const qint64 ret = d->tmpFile->readLine( data, maxSize );
+ d->propagateErrors();
+ return ret;
+}
+
+qint64 KDSaveFile::writeData( const char* data, qint64 maxSize ) {
+ if ( !d->tmpFile ) {
+ setErrorString( tr("TODO") );
+ return -1;
+ }
+ const qint64 ret = d->tmpFile->write( data, maxSize );
+ d->propagateErrors();
+ return ret;
+}
+
+bool KDSaveFile::flush() {
+ return d->tmpFile ? d->tmpFile->flush() : false;
+}
+
+bool KDSaveFile::resize( qint64 sz ) {
+ return d->tmpFile ? d->tmpFile->resize( sz ) : false;
+}
+
+int KDSaveFile::handle() const {
+ return d->tmpFile ? d->tmpFile->handle() : -1;
+}
+
+QFile::Permissions KDSaveFile::permissions() const {
+ return d->tmpFile ? d->tmpFile->permissions() : d->permissions;
+}
+
+bool KDSaveFile::setPermissions( QFile::Permissions p ) {
+ d->permissions = p;
+ if ( d->tmpFile )
+ return d->tmpFile->setPermissions( p );
+ return false;
+}
+
+void KDSaveFile::setBackupExtension( const QString& ext ) {
+ d->backupExtension = ext;
+}
+
+QString KDSaveFile::backupExtension() const {
+ return d->backupExtension;
+}
+
+/**
+ * TODO
+ *
+ *
+ */
+
+#ifdef KDTOOLSCORE_UNITTESTS
+
+#include <KDUnitTest/Test>
+
+KDAB_UNITTEST_SIMPLE( KDSaveFile, "kdcoretools" ) {
+ //TODO test contents (needs blocking and checked write() )
+ {
+ const QString testfile1 = QLatin1String("kdsavefile-test1");
+ QByteArray testData("lalalala");
+ KDSaveFile saveFile( testfile1 );
+ assertTrue( saveFile.open( QIODevice::WriteOnly ) );
+ saveFile.write( testData.constData(), testData.size() );
+ assertTrue( saveFile.commit() );
+ assertTrue( QFile::exists( testfile1 ) );
+ assertTrue( QFile::remove( testfile1 ) );
+ }
+ {
+ const QString testfile1 = QLatin1String("kdsavefile-test1");
+ QByteArray testData("lalalala");
+ KDSaveFile saveFile( testfile1 );
+ assertTrue( saveFile.open( QIODevice::WriteOnly ) );
+ saveFile.write( testData.constData(), testData.size() );
+ saveFile.close();
+ assertFalse( QFile::exists( testfile1 ) );
+ }
+ {
+ const QString testfile1 = QLatin1String("kdsavefile-test1");
+ QByteArray testData("lalalala");
+ KDSaveFile saveFile( testfile1 );
+ assertTrue( saveFile.open( QIODevice::WriteOnly ) );
+ saveFile.write( testData.constData(), testData.size() );
+ assertTrue( saveFile.commit() );
+ assertTrue( QFile::exists( testfile1 ) );
+
+ KDSaveFile sf2( testfile1 );
+ sf2.setBackupExtension( QLatin1String(".bak") );
+ assertTrue( sf2.open( QIODevice::WriteOnly ) );
+ sf2.write( testData.constData(), testData.size() );
+ sf2.commit(); //commit in backup mode (default)
+ const QString backup = testfile1 + sf2.backupExtension();
+ assertTrue( QFile::exists( backup ) );
+ assertTrue( QFile::remove( backup ) );
+
+ KDSaveFile sf3( testfile1 );
+ sf3.setBackupExtension( QLatin1String(".bak") );
+ assertTrue( sf3.open( QIODevice::WriteOnly ) );
+ sf3.write( testData.constData(), testData.size() );
+ sf3.commit( KDSaveFile::OverwriteExistingFile );
+ const QString backup2 = testfile1 + sf3.backupExtension();
+ assertFalse( QFile::exists( backup2 ) );
+
+ assertTrue( QFile::remove( testfile1 ) );
+ }
+ {
+ const QString testfile1 = QLatin1String("kdsavefile-test1");
+ KDSaveFile sf( testfile1 );
+ assertFalse( sf.open( QIODevice::ReadOnly ) );
+ assertFalse( sf.open( QIODevice::WriteOnly|QIODevice::Append ) );
+ assertTrue( sf.open( QIODevice::ReadWrite ) );
+ }
+}
+
+#endif // KDTOOLSCORE_UNITTESTS
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdsavefile.h b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdsavefile.h
new file mode 100644
index 000000000..94170608c
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdsavefile.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef __KDTOOLSCORE_KDSAVEFILE_H__
+#define __KDTOOLSCORE_KDSAVEFILE_H__
+
+#include <KDToolsCore/kdtoolsglobal.h>
+#include <KDToolsCore/pimpl_ptr.h>
+
+#include <QtCore/QIODevice>
+#include <QtCore/QFile>
+#include <QtCore/QString>
+
+class KDTOOLSCORE_EXPORT KDSaveFile : public QIODevice {
+ Q_OBJECT
+public:
+ explicit KDSaveFile( const QString& filename=QString(), QObject* parent=0 );
+ ~KDSaveFile();
+
+ enum CommitMode {
+ BackupExistingFile=0x1,
+ OverwriteExistingFile=0x2
+ };
+
+ bool commit( CommitMode=BackupExistingFile );
+
+ QString fileName() const;
+ void setFileName( const QString& filename );
+
+ QFile::Permissions permissions() const;
+ bool setPermissions( QFile::Permissions );
+
+ QString backupExtension() const;
+ void setBackupExtension( const QString& extension );
+
+ bool flush();
+ bool resize( qint64 sz );
+ int handle() const;
+
+ /* reimp */ bool atEnd();
+ /* reimp */ qint64 bytesAvailable() const;
+ /* reimp */ qint64 bytesToWrite() const;
+ /* reimp */ bool canReadLine() const;
+ /* reimp */ void close();
+ /* reimp */ bool isSequential() const;
+ /* reimp */ bool open( OpenMode mode=QIODevice::ReadWrite ); //only valid: WriteOnly, ReadWrite
+ /* reimp */ qint64 pos() const;
+ /* reimp */ bool reset();
+ /* reimp */ bool seek( qint64 pos );
+ /* reimp */ qint64 size() const;
+ /* reimp */ bool waitForBytesWritten( int msecs );
+ /* reimp */ bool waitForReadyRead( int msecs );
+
+private:
+ /* reimp */ qint64 readData( char* data, qint64 maxSize );
+ /* reimp */ qint64 readLineData( char* data, qint64 maxSize );
+ /* reimp */ qint64 writeData( const char* data, qint64 maxSize );
+
+private:
+ class Private;
+ kdtools::pimpl_ptr<Private> d;
+};
+
+#endif // __KDTOOLSCORE_KDSAVEFILE_H__
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdselfrestarter.cpp b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdselfrestarter.cpp
new file mode 100644
index 000000000..fcd66f238
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdselfrestarter.cpp
@@ -0,0 +1,78 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdselfrestarter.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDir>
+#include <QtCore/QProcess>
+
+class KDSelfRestarter::Private {
+public:
+ Private( int argc, char** argv ) : restartOnQuit( false ) {
+ executable = QString::fromLocal8Bit( argv[0] );
+ workingPath = QDir::currentPath();
+ for ( int i = 1; i < argc; ++i )
+ args << QString::fromLocal8Bit( argv[i] );
+ }
+
+ Private()
+ {
+ executable = qApp->applicationFilePath();
+ workingPath = QDir::currentPath();
+ args = qApp->arguments().mid( 1 );
+ }
+
+ ~Private() {
+ if ( restartOnQuit )
+ QProcess::startDetached( executable, args, workingPath );
+ }
+
+ QString executable;
+ QStringList args;
+ bool restartOnQuit;
+ QString workingPath;
+ static KDSelfRestarter* instance;
+};
+
+KDSelfRestarter* KDSelfRestarter::Private::instance = 0;
+
+KDSelfRestarter::KDSelfRestarter( int argc, char** argv ) : d( new Private( argc, argv ) ) {
+ Q_ASSERT_X( !Private::instance, Q_FUNC_INFO, "Cannot create more than one KDSelfRestarter instance" );
+ Private::instance = this;
+}
+
+KDSelfRestarter::~KDSelfRestarter()
+{
+ Q_ASSERT_X( Private::instance == this, Q_FUNC_INFO, "Cannot create more than one KDSelfRestarter instance" );
+ Private::instance = 0;
+}
+
+void KDSelfRestarter::setRestartOnQuit( bool restart ) {
+ Q_ASSERT_X( Private::instance, Q_FUNC_INFO, "KDSelfRestarter instance must be created in main()" );
+ if ( Private::instance )
+ Private::instance->d->restartOnQuit = restart;
+}
+
+bool KDSelfRestarter::restartOnQuit() {
+ return Private::instance ? Private::instance->d->restartOnQuit : false;
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdselfrestarter.h b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdselfrestarter.h
new file mode 100644
index 000000000..0582c778d
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdselfrestarter.h
@@ -0,0 +1,42 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef __KDTOOLSCORE_KDSELFRESTARTER_H__
+#define __KDTOOLSCORE_KDSELFRESTARTER_H__
+
+#include <KDToolsCore/pimpl_ptr.h>
+
+class KDTOOLSCORE_EXPORT KDSelfRestarter {
+public:
+ KDSelfRestarter( int argc, char** argv );
+ ~KDSelfRestarter();
+
+ static bool restartOnQuit();
+ static void setRestartOnQuit( bool restart );
+
+private:
+ Q_DISABLE_COPY(KDSelfRestarter);
+ class Private;
+ kdtools::pimpl_ptr<Private> d;
+};
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdsysinfo.cpp b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdsysinfo.cpp
new file mode 100644
index 000000000..e694d79fa
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdsysinfo.cpp
@@ -0,0 +1,191 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdsysinfo.h"
+
+#include <algorithm>
+
+KDSysInfo::KDSysInfo()
+{
+}
+
+KDSysInfo::~KDSysInfo()
+{
+}
+
+#include <QDir>
+#include <QDebug>
+
+QDebug operator<<( QDebug dbg, KDSysInfo::OperatingSystemType type )
+{
+ switch( type )
+ {
+ case KDSysInfo::Linux:
+ return dbg << "Linux";
+ case KDSysInfo::MacOSX:
+ return dbg << "Mac OS X";
+ case KDSysInfo::Windows:
+ return dbg << "Windows";
+ default:
+ return dbg << "<unknown>";
+ }
+}
+
+QDebug operator<<( QDebug dbg, KDSysInfo::ArchitectureType type )
+{
+ switch( type )
+ {
+ case KDSysInfo::ARM:
+ return dbg << "ARM";
+ case KDSysInfo::Intel:
+ return dbg << "Intel";
+ case KDSysInfo::AMD64:
+ return dbg << "AMD64";
+ case KDSysInfo::IA64:
+ return dbg << "IA64";
+ case KDSysInfo::PowerPC:
+ return dbg << "Power PC";
+ case KDSysInfo::Motorola68k:
+ return dbg << "Motorola 68k";
+ default:
+ return dbg << "<unknown>";
+ }
+}
+
+QDebug operator<<( QDebug dbg, KDSysInfo::Volume volume )
+{
+ return dbg << "KDSysInfo::Volume(" << volume.path() << ")";
+}
+
+QPair< KDByteSize, KDByteSize > volumeSpace( const QString& volume );
+QString volumeName( const QString& volume );
+
+class KDSysInfo::Volume::Private : public QSharedData
+{
+public:
+ QString p;
+ QString name;
+ KDByteSize size;
+ KDByteSize availableSpace;
+};
+
+
+KDSysInfo::Volume::Volume()
+ : d( new Private )
+{
+}
+
+KDSysInfo::Volume::Volume( const Volume& other )
+ : d( other.d )
+{
+}
+
+KDSysInfo::Volume::~Volume()
+{
+}
+
+void KDSysInfo::Volume::swap( KDSysInfo::Volume& other )
+{
+ std::swap( d, other.d );
+}
+
+KDSysInfo::Volume& KDSysInfo::Volume::operator=( const KDSysInfo::Volume& other )
+{
+ KDSysInfo::Volume tmp( other );
+ swap( tmp );
+ return *this;
+}
+
+void KDSysInfo::Volume::setPath( const QString& path )
+{
+ d->p = path;
+}
+
+bool KDSysInfo::Volume::operator == ( const Volume& other ) const
+{
+ return d->name == other.d->name && d->p == other.d->p;
+}
+
+void KDSysInfo::Volume::setName( const QString& name )
+{
+ d->name = name;
+}
+
+QString KDSysInfo::Volume::name() const
+{
+ return d->name;
+}
+
+QString KDSysInfo::Volume::path() const
+{
+ return d->p;
+}
+
+KDByteSize KDSysInfo::Volume::size() const
+{
+ return d->size;
+}
+
+void KDSysInfo::Volume::setSize( const KDByteSize& size )
+{
+ d->size = size;
+}
+
+KDByteSize KDSysInfo::Volume::availableSpace() const
+{
+ return d->availableSpace;
+}
+
+void KDSysInfo::Volume::setAvailableSpace( const KDByteSize& available )
+{
+ d->availableSpace = available;
+}
+
+struct PathLongerThan
+{
+ bool operator()( const KDSysInfo::Volume& lhs, const KDSysInfo::Volume& rhs ) const
+ {
+ return lhs.path().length() > rhs.path().length();
+ }
+};
+
+KDSysInfo::Volume KDSysInfo::Volume::fromPath( const QString& path )
+{
+ QList< KDSysInfo::Volume > volumes = mountedVolumes();
+ // sort by length to get the longest mount point (not just "/") first
+ std::sort( volumes.begin(), volumes.end(), PathLongerThan() );
+ for( QList< KDSysInfo::Volume >::const_iterator it = volumes.constBegin(); it != volumes.constEnd(); ++it )
+ {
+#ifdef Q_WS_WIN
+ if( QDir::toNativeSeparators( path ).toLower().startsWith( it->path().toLower() ) )
+#else
+ if( path.startsWith( it->path() ) )
+#endif
+ return *it;
+ }
+ return KDSysInfo::Volume();
+}
+
+QDebug operator<<( QDebug dbg, KDSysInfo::ProcessInfo process )
+{
+ return dbg << "KDSysInfo::ProcessInfo(" << process.id << ", " << process.name << ")";
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdsysinfo.h b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdsysinfo.h
new file mode 100644
index 000000000..2324ccfc8
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdsysinfo.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef KDSYSINFO_H
+#define KDSYSINFO_H
+
+#include <KDToolsCore/kdtoolsglobal.h>
+
+#include <QtCore/QString>
+#include <QtCore/QSysInfo>
+#include <QtCore/QSharedDataPointer>
+
+#include "kdbytesize.h"
+
+class KDVersion;
+
+class KDTOOLSCORE_EXPORT KDSysInfo : public QSysInfo
+{
+private:
+ KDSysInfo();
+
+public:
+ ~KDSysInfo();
+
+ enum OperatingSystemType
+ {
+ UnknownOperatingSystem = -1,
+ Linux,
+ MacOSX,
+ Windows
+ };
+
+ enum ArchitectureType
+ {
+ UnknownArchitecture = -1,
+ ARM,
+ Intel,
+ AMD64,
+ IA64,
+ PowerPC,
+ Motorola68k
+ };
+
+ class KDTOOLSCORE_EXPORT Volume
+ {
+ friend class ::KDSysInfo;
+ public:
+ static Volume fromPath( const QString& path );
+
+ Volume();
+ Volume( const Volume& other );
+ ~Volume();
+
+ QString name() const;
+ QString path() const;
+ KDByteSize size() const;
+ KDByteSize availableSpace() const;
+
+ void swap( Volume& other );
+ Volume& operator=( const Volume& other );
+ bool operator == ( const Volume& other ) const;
+
+ private:
+ void setPath( const QString& path );
+ void setName( const QString& name );
+ void setSize( const KDByteSize& size );
+ void setAvailableSpace( const KDByteSize& available );
+
+ private:
+ class Private;
+ QSharedDataPointer<Private> d;
+ };
+
+ struct ProcessInfo
+ {
+ quint32 id;
+ QString name;
+ };
+
+ static OperatingSystemType osType();
+ static KDVersion osVersion();
+ static QString osDescription();
+ static ArchitectureType architecture();
+
+ static KDByteSize installedMemory();
+ static QList< Volume > mountedVolumes();
+ static QList< ProcessInfo > runningProcesses();
+};
+
+class QDebug;
+
+QDebug operator<<( QDebug dbg, KDSysInfo::OperatingSystemType type );
+QDebug operator<<( QDebug dbg, KDSysInfo::ArchitectureType type );
+QDebug operator<<( QDebug dbg, KDSysInfo::Volume volume );
+QDebug operator<<( QDebug dbg, KDSysInfo::ProcessInfo process );
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdsysinfo_mac.cpp b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdsysinfo_mac.cpp
new file mode 100644
index 000000000..024d1dd4d
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdsysinfo_mac.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdsysinfo.h"
+
+#include "kdbytesize.h"
+#include "kdversion.h"
+
+#include <Carbon/Carbon.h>
+
+static QString qt_mac_hfsunistr_to_qstring( const HFSUniStr255* hfs )
+{
+ const QChar* const charPointer = reinterpret_cast< const QChar* >( hfs->unicode );
+ return QString( charPointer, hfs->length );
+}
+
+KDSysInfo::OperatingSystemType KDSysInfo::osType()
+{
+ return MacOSX;
+}
+
+KDVersion KDSysInfo::osVersion()
+{
+ SInt32 major = 0;
+ SInt32 minor = 0;
+ SInt32 bugfix = 0;
+ Gestalt( gestaltSystemVersionMajor, &major );
+ Gestalt( gestaltSystemVersionMinor, &minor );
+ Gestalt( gestaltSystemVersionBugFix, &bugfix );
+
+ QStringList result;
+ result << QString::number( major );
+ result << QString::number( minor );
+ result << QString::number( bugfix );
+
+ return KDVersion::fromString( result.join( QChar::fromLatin1( '.' ) ) );
+}
+
+QString KDSysInfo::osDescription()
+{
+ return QObject::tr( "Mac OS X Version %1" ).arg( osVersion().toString() );
+}
+
+KDByteSize KDSysInfo::installedMemory()
+{
+ SInt32 mb = 0;
+ Gestalt( gestaltPhysicalRAMSizeInMegabytes, &mb );
+ return KDByteSize( static_cast< quint64 >( mb ) * 1024LL * 1024LL );
+}
+
+KDSysInfo::ArchitectureType KDSysInfo::architecture()
+{
+ SInt32 arch = 0;
+ Gestalt( gestaltSysArchitecture, &arch );
+ switch( arch )
+ {
+ case gestalt68k:
+ return Motorola68k;
+ case gestaltPowerPC:
+ return PowerPC;
+ case gestaltIntel:
+ return Intel;
+ default:
+ return UnknownArchitecture;
+ }
+}
+
+QList< KDSysInfo::Volume > KDSysInfo::mountedVolumes()
+{
+ QList< KDSysInfo::Volume > result;
+ FSVolumeRefNum volume;
+ FSVolumeInfo info;
+ HFSUniStr255 volName;
+ FSRef ref;
+ int i = 0;
+
+ while( FSGetVolumeInfo( kFSInvalidVolumeRefNum, ++i, &volume, kFSVolInfoFSInfo, &info, &volName, &ref ) == 0 )
+ {
+ UInt8 path[ PATH_MAX + 1 ];
+ if( FSRefMakePath( &ref, path, PATH_MAX ) == 0 )
+ {
+ const QString name = qt_mac_hfsunistr_to_qstring( &volName );
+ const QString mount = QString::fromLocal8Bit( reinterpret_cast< char* >( path ) );
+ FSGetVolumeInfo( volume, 0, 0, kFSVolInfoSizes, &info, 0, 0 );
+ Volume v;
+ v.setName( name );
+ v.setPath( mount );
+ v.setSize( KDByteSize( info.totalBytes ) );
+ v.setAvailableSpace( KDByteSize( info.freeBytes ) );
+ result.push_back( v );
+ }
+ }
+
+ return result;
+}
+
+QList< KDSysInfo::ProcessInfo > KDSysInfo::runningProcesses()
+{
+ return QList< KDSysInfo::ProcessInfo >();
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdsysinfo_win.cpp b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdsysinfo_win.cpp
new file mode 100644
index 000000000..3456b89cb
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdsysinfo_win.cpp
@@ -0,0 +1,323 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdsysinfo.h"
+
+#include "kdbytesize.h"
+#include "kdversion.h"
+
+#include <windows.h>
+#include <Tlhelp32.h>
+#include <Psapi.h>
+
+#include <QDir>
+#include <QPair>
+
+#include <QtCore/QLibrary>
+
+#define KDSYSINFO_PROCESS_QUERY_LIMITED_INFORMATION (0x1000)
+
+KDSysInfo::OperatingSystemType KDSysInfo::osType()
+{
+ return Windows;
+}
+
+KDVersion KDSysInfo::osVersion()
+{
+ OSVERSIONINFO info;
+ memset( &info, 0, sizeof( info ) );
+ info.dwOSVersionInfoSize = sizeof( info );
+ GetVersionEx( &info );
+ return KDVersion::fromString( QString::fromLatin1( "%1.%2" ).arg( info.dwMajorVersion ).arg( info.dwMinorVersion ) );
+}
+
+QString KDSysInfo::osDescription()
+{
+ switch( QSysInfo::windowsVersion() )
+ {
+ case QSysInfo::WV_32s:
+ return QObject::tr( "Windows 3.1" );
+ case QSysInfo::WV_95:
+ return QObject::tr( "Windows 95" );
+ case QSysInfo::WV_98:
+ return QObject::tr( "Windows 98" );
+ case QSysInfo::WV_Me:
+ return QObject::tr( "Windows ME" );
+ case QSysInfo::WV_NT:
+ return QObject::tr( "Windows NT" );
+ case QSysInfo::WV_2000:
+ return QObject::tr( "Windows 2000" );
+ case QSysInfo::WV_XP:
+ return QObject::tr( "Windows XP" );
+ case QSysInfo::WV_2003:
+ return QObject::tr( "Windows 2003" );
+ case QSysInfo::WV_VISTA:
+ return QObject::tr( "Windows Vista" );
+ case QSysInfo::WV_WINDOWS7:
+ return QObject::tr( "Windows 7" );
+ case QSysInfo::WV_CE:
+ return QObject::tr( "Windows CE" );
+ case QSysInfo::WV_CENET:
+ return QObject::tr( "Windows CE .NET" );
+ case QSysInfo::WV_CE_5:
+ return QObject::tr( "Windows CE 5" );
+ case QSysInfo::WV_CE_6:
+ return QObject::tr( "Windows CE 6" );
+ default:
+ return QObject::tr( "Windows" );
+ }
+}
+
+KDByteSize KDSysInfo::installedMemory()
+{
+ MEMORYSTATUSEX status;
+ status.dwLength = sizeof( status );
+ GlobalMemoryStatusEx( &status );
+ return KDByteSize( status.ullTotalPhys );
+}
+
+KDSysInfo::ArchitectureType KDSysInfo::architecture()
+{
+#if defined( _M_X64 )
+ return AMD64;
+#elif defined( _M_IX86 )
+ return Intel;
+#elif defined( _M_IA64 )
+ return IA64;
+#elif defined( _M_PPC )
+ return PowerPC;
+#elif defined( _M_ARM )
+ return ARM;
+#else
+ return UnknownArchitecture;
+#endif
+}
+
+QPair< KDByteSize, KDByteSize > volumeSpace( const QString& volume )
+{
+ QPair< KDByteSize, KDByteSize > result;
+ ULARGE_INTEGER bytes;
+ ULARGE_INTEGER freebytes;
+ if( GetDiskFreeSpaceExA( qPrintable( volume ), 0, &bytes, &freebytes ) != 0 )
+ {
+ result.first = KDByteSize( bytes.QuadPart );
+ result.second = KDByteSize( freebytes.QuadPart );
+ }
+ return result;
+}
+
+QString volumeName( const QString& volume )
+{
+ char name[ MAX_PATH + 1 ] = "";
+ DWORD dummy;
+ char dummy2[ MAX_PATH + 1 ] = "";
+ GetVolumeInformationA( qPrintable( volume ), name, MAX_PATH + 1, &dummy, &dummy, &dummy, dummy2, MAX_PATH + 1 );
+ QString vName = QString::fromLatin1( name );
+ if( vName.isEmpty() )
+ {
+ const uint driveType = GetDriveTypeA( qPrintable( volume ) );
+ switch( driveType )
+ {
+ case DRIVE_REMOVABLE:
+ vName = QObject::tr( "Removable Disk" );
+ break;
+ case DRIVE_CDROM:
+ vName = QObject::tr( "CD Drive" );
+ break;
+ case DRIVE_FIXED:
+ vName = QObject::tr( "Local Disk" );
+ break;
+ default:
+ return volume.left( 2 );
+ }
+ }
+ return QString::fromLatin1( "%2 (%1)" ).arg( volume.left( 2 ), vName );
+}
+
+QList< KDSysInfo::Volume > KDSysInfo::mountedVolumes()
+{
+ QList< Volume > result;
+ const QFileInfoList drives = QDir::drives();
+ for( QFileInfoList::const_iterator it = drives.constBegin(); it != drives.constEnd(); ++it )
+ {
+ Volume volume;
+ const QString path = QDir::toNativeSeparators( it->path() );
+ volume.setPath( path );
+ volume.setName( volumeName( path ) );
+ const QPair< KDByteSize, KDByteSize > sizes = volumeSpace( path );
+ volume.setSize( sizes.first );
+ volume.setAvailableSpace( sizes.second );
+ result.push_back( volume );
+ }
+ return result;
+}
+
+struct EnumWindowsProcParam
+{
+ QList< KDSysInfo::ProcessInfo > processes;
+ QList< quint32 > seenIDs;
+};
+
+//BOOL CALLBACK EnumWindowsProc( HWND hWnd, LPARAM lParam )
+//{
+// EnumWindowsProcParam* const list = reinterpret_cast< EnumWindowsProcParam* >( lParam );
+
+// KDSysInfo::ProcessInfo info;
+
+// // process id
+// DWORD procID = 0;
+// GetWindowThreadProcessId( hWnd, &procID );
+// info.id = procID;
+
+// if( list->seenIDs.contains( info.id ) )
+// return TRUE;
+// list->seenIDs.push_back( info.id );
+
+// HINSTANCE inst = (HINSTANCE)GetWindowLongA( hWnd, GWL_HINSTANCE );
+// // process name
+// HANDLE process = OpenProcess( PROCESS_ALL_ACCESS, FALSE, procID );
+
+// static char buffer[ 1024 ];
+// if( GetModuleFileNameExA( process, inst, buffer, sizeof( buffer ) ) )
+// info.name = QString::fromLocal8Bit( buffer );
+// CloseHandle( process );
+
+// list->processes.push_back( info );
+// return TRUE;
+//}
+
+//QList< KDSysInfo::ProcessInfo > KDSysInfo::runningProcesses()
+//{
+// EnumWindowsProcParam param;
+// HANDLE snapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
+// if ( !snapshot )
+// return param.processes;
+// PROCESSENTRY32 processStruct;
+// processStruct.dwSize = sizeof( PROCESSENTRY32 );
+// bool foundProcess = Process32First( snapshot, &processStruct );
+// while ( foundProcess )
+// {
+// //const QString executableName = QString::fromWCharArray( processStruct.szExeFile );
+// KDSysInfo::ProcessInfo info;
+// HANDLE procHandle = OpenProcess( PROCESS_QUERY_LIMITED_INFORMATION, false, processStruct.th32ProcessID );
+// char buffer[ 1024 ];
+// DWORD bufferSize = 1024;
+// const bool succ = QueryFullProcessImageNameA( procHandle, 0, buffer, &bufferSize );
+// if ( succ )
+// {
+// const QString executablepath = QString::fromLatin1( buffer );
+// const quint32 pid = processStruct.th32ProcessID;
+// param.seenIDs.append( pid );
+
+// info.id = pid;
+// info.name = executablepath;
+// param.processes.append( info );
+// }
+// CloseHandle( procHandle );
+
+// foundProcess = Process32Next( snapshot, &processStruct );
+// }
+// if ( snapshot )
+// CloseHandle( snapshot );
+//// EnumDesktopWindows( 0, &EnumWindowsProc, reinterpret_cast< LPARAM >( &param ) );
+// return param.processes;
+//}
+typedef BOOL ( WINAPI *QueryFullProcessImageNamePtr )( HANDLE, DWORD, char*, PDWORD );
+typedef DWORD ( WINAPI *GetProcessImageFileNamePtr )( HANDLE, char*, DWORD );
+QList< KDSysInfo::ProcessInfo > KDSysInfo::runningProcesses()
+{
+ EnumWindowsProcParam param;
+ HANDLE snapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
+ if ( !snapshot )
+ return param.processes;
+ PROCESSENTRY32 processStruct;
+ processStruct.dwSize = sizeof( PROCESSENTRY32 );
+ bool foundProcess = Process32First( snapshot, &processStruct );
+ const DWORD bufferSize = 1024;
+ char driveBuffer[ bufferSize ];
+ QStringList deviceList;
+ if ( QSysInfo::windowsVersion() <= QSysInfo::WV_5_2 )
+ {
+ DWORD size = GetLogicalDriveStringsA( bufferSize, driveBuffer );
+ deviceList = QString::fromLatin1( driveBuffer, size ).split( QLatin1Char( (char)0 ), QString::SkipEmptyParts );
+ }
+
+ QLibrary kernel32( QLatin1String( "Kernel32.dll" ) );
+ kernel32.load();
+ void* pQueryFullProcessImageNameA = kernel32.resolve( "QueryFullProcessImageNameA" );
+
+ QLibrary psapi( QLatin1String ( "Psapi.dll" ) );
+ psapi.load();
+ void* pGetProcessImageFileNamePtr = psapi.resolve( "GetProcessImageFileNameA" );
+ QueryFullProcessImageNamePtr callPtr = ( QueryFullProcessImageNamePtr ) pQueryFullProcessImageNameA;
+ GetProcessImageFileNamePtr callPtrXp = ( GetProcessImageFileNamePtr ) pGetProcessImageFileNamePtr;
+ while ( foundProcess )
+ {
+ HANDLE procHandle = OpenProcess( QSysInfo::windowsVersion() > QSysInfo::WV_5_2 ?
+ KDSYSINFO_PROCESS_QUERY_LIMITED_INFORMATION :
+ PROCESS_QUERY_INFORMATION
+ , false,
+ processStruct.th32ProcessID );
+
+ char buffer[ 1024 ];
+ DWORD bufferSize = 1024;
+ bool succ = false;
+ QString whichFailed;
+ QString executablePath;
+ KDSysInfo::ProcessInfo info;
+ if ( QSysInfo::windowsVersion() > QSysInfo::WV_5_2 )
+ {
+ succ = callPtr( procHandle, 0, buffer, &bufferSize );
+ executablePath = QString::fromLatin1( buffer );
+ }
+ else
+ {
+ if (pGetProcessImageFileNamePtr) {
+ succ = callPtrXp( procHandle, buffer, bufferSize );
+ executablePath = QString::fromLatin1( buffer );
+ for ( int i = 0; i < deviceList.count(); ++i )
+ {
+ executablePath.replace( QString::fromLatin1( "\\Device\\HarddiskVolume%1\\" ).arg( i + 1 ), deviceList.at( i ) );
+ }
+ }
+
+ }
+ if ( succ )
+ {
+ const quint32 pid = processStruct.th32ProcessID;
+ param.seenIDs.append( pid );
+
+ info.id = pid;
+ info.name = executablePath;
+ param.processes.append( info );
+ }
+
+ CloseHandle( procHandle );
+ foundProcess = Process32Next( snapshot, &processStruct );
+
+ }
+ if ( snapshot )
+ CloseHandle( snapshot );
+
+ kernel32.unload();
+ return param.processes;
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdsysinfo_x11.cpp b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdsysinfo_x11.cpp
new file mode 100644
index 000000000..a9d609d4d
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdsysinfo_x11.cpp
@@ -0,0 +1,163 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdsysinfo.h"
+
+#include "kdbytesize.h"
+#include "kdversion.h"
+
+#include <sys/utsname.h>
+#include <sys/statvfs.h>
+
+#include <QtCore/QFile>
+#include <QtCore/QTextStream>
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+
+KDSysInfo::OperatingSystemType KDSysInfo::osType()
+{
+#if defined( Q_OS_LINUX )
+ return Linux;
+#else
+ UnknownOperatingSystem;
+#endif
+}
+
+KDVersion KDSysInfo::osVersion()
+{
+#if defined( Q_OS_LINUX )
+ struct utsname info;
+ uname( &info );
+ QString v = QString::fromLatin1( info.release );
+ if( v.contains( QString::fromLatin1( "-" ) ) )
+ v = v.mid( 0, v.indexOf( QString::fromLatin1( "-" ) ) );
+
+ return KDVersion::fromString( v );
+#else
+ return KDVersion();
+#endif
+}
+
+QString KDSysInfo::osDescription()
+{
+#if defined( Q_OS_LINUX )
+ return QObject::tr( "Linux %1" ).arg( osVersion().toString() );
+#else
+ return QString();
+#endif
+}
+
+KDByteSize KDSysInfo::installedMemory()
+{
+#ifdef Q_OS_LINUX
+ QFile f( QLatin1String( "/proc/meminfo" ) );
+ f.open( QIODevice::ReadOnly );
+ QTextStream stream( &f );
+ while( true )
+ {
+ const QString s = stream.readLine();
+ if( !s.startsWith( QLatin1String( "MemTotal:" ) ) )
+ continue;
+ else if( s.isEmpty() )
+ return KDByteSize();
+
+ const QStringList parts = s.split( QLatin1Char( ' ' ), QString::SkipEmptyParts );
+ return KDByteSize( parts.at(1).toInt() * 1024LL );
+ }
+#else
+ quint64 physmem;
+ size_t len = sizeof physmem;
+ static int mib[2] = { CTL_HW, HW_MEMSIZE };
+ sysctl( mib, 2, &physmem, &len, 0, 0 );
+ return KDByteSize( physmem );
+#endif
+ return KDByteSize();
+}
+
+KDSysInfo::ArchitectureType KDSysInfo::architecture()
+{
+ return UnknownArchitecture;
+}
+
+QList< KDSysInfo::Volume > KDSysInfo::mountedVolumes()
+{
+ QList< Volume > result;
+
+ QFile f( QLatin1String( "/etc/mtab" ) );
+ if ( !f.open( QIODevice::ReadOnly ) ) {
+ qCritical( "%s: Could not open %s: %s", Q_FUNC_INFO, qPrintable(f.fileName()), qPrintable(f.errorString()) );
+ return QList<KDSysInfo::Volume>(); //better error-handling?
+ }
+
+ QTextStream stream( &f );
+ while( true )
+ {
+ const QString s = stream.readLine();
+ if ( s.isNull() )
+ return result;
+
+ if( !s.startsWith( QLatin1Char( '/' ) ) )
+ continue;
+
+ const QStringList parts = s.split( QLatin1Char( ' ' ), QString::SkipEmptyParts );
+
+ Volume v;
+ v.setName( parts.at( 1 ) );
+ v.setPath( parts.at( 1 ) );
+
+ struct statvfs data;
+ if( statvfs( qPrintable( v.name() ), &data ) == 0 )
+ {
+ v.setSize( KDByteSize( static_cast< quint64 >( data.f_blocks ) * data.f_bsize ) );
+ v.setAvailableSpace( KDByteSize( static_cast< quint64> ( data.f_bfree ) * data.f_bsize ) );
+ }
+
+ result.push_back( v );
+ }
+
+ return result;
+}
+
+QList< KDSysInfo::ProcessInfo > KDSysInfo::runningProcesses()
+{
+ QList< KDSysInfo::ProcessInfo > processes;
+ QDir procDir( QLatin1String( "/proc" ) );
+ const QFileInfoList procCont = procDir.entryInfoList( QDir::Dirs | QDir::NoDotAndDotDot | QDir::Readable );
+ QRegExp validator( QLatin1String( "[0-9]+" ) );
+ Q_FOREACH( const QFileInfo& info, procCont )
+ {
+ if ( validator.exactMatch( info.fileName() ) )
+ {
+ const QString linkPath = QDir( info.absoluteFilePath() ).absoluteFilePath( QLatin1String( "exe" ) );
+ const QFileInfo linkInfo( linkPath );
+ if ( linkInfo.exists() )
+ {
+ KDSysInfo::ProcessInfo processInfo;
+ processInfo.name = linkInfo.symLinkTarget();
+ processInfo.id = info.fileName().toInt();
+ processes.append( processInfo );
+ }
+ }
+ }
+ return processes;
+}
+
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdtoolsglobal.cpp b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdtoolsglobal.cpp
new file mode 100644
index 000000000..f41d7974e
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdtoolsglobal.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdtoolsglobal.h"
+
+#include <QByteArray>
+
+#include <algorithm>
+
+namespace {
+ struct Version {
+ unsigned char v[3];
+ };
+
+ static inline bool operator<( const Version & lhs, const Version & rhs ) {
+ return std::lexicographical_compare( lhs.v, lhs.v + 3, rhs.v, rhs.v + 3 );
+ }
+ static inline bool operator==( const Version & lhs, const Version & rhs ) {
+ return std::equal( lhs.v, lhs.v + 3, rhs.v );
+ }
+ KDTOOLS_MAKE_RELATION_OPERATORS( Version, static inline )
+}
+
+static Version kdParseQtVersion( const char * const version ) {
+ if ( !version || qstrlen( version ) < 5 || version[1] != '.' || version[3] != '.' || ( version[5] != 0 && version[5] != '.' && version[5] != '-' ) )
+ return Version(); // parse error
+ const Version result = { { version[0] - '0', version[2] - '0', version[4] - '0' } };
+ return result;
+}
+
+bool _kdCheckQtVersion_impl( int major, int minor, int patchlevel ) {
+ static const Version actual = kdParseQtVersion( qVersion() ); // do this only once each run...
+ const Version requested = { { major, minor, patchlevel } };
+ return actual >= requested;
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdtoolsglobal.h b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdtoolsglobal.h
new file mode 100644
index 000000000..3d687da39
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdtoolsglobal.h
@@ -0,0 +1,135 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef __KDTOOLS_KDTOOLSGLOBAL_H__
+#define __KDTOOLS_KDTOOLSGLOBAL_H__
+
+#include <QtCore/QtGlobal>
+
+#define KDAB_DISABLE_COPY( x ) private: x( const x & ); x & operator=( const x & )
+
+#ifdef KDTOOLS_SHARED
+# ifdef BUILD_SHARED_KDTOOLSCORE
+# define KDTOOLSCORE_EXPORT Q_DECL_EXPORT
+# else
+# define KDTOOLSCORE_EXPORT Q_DECL_IMPORT
+# endif
+# ifdef BUILD_SHARED_KDTOOLSGUI
+# define KDTOOLSGUI_EXPORT Q_DECL_EXPORT
+# else
+# define KDTOOLSGUI_EXPORT Q_DECL_IMPORT
+# endif
+# ifdef BUILD_SHARED_KDTOOLSXML
+# define KDTOOLSXML_EXPORT Q_DECL_EXPORT
+# else
+# define KDTOOLSXML_EXPORT Q_DECL_IMPORT
+# endif
+# ifdef BUILD_SHARED_KDUPDATER
+# define KDTOOLS_UPDATER_EXPORT Q_DECL_EXPORT
+# else
+# define KDTOOLS_UPDATER_EXPORT Q_DECL_IMPORT
+# endif
+#else // KDTOOLS_SHARED
+# define KDTOOLSCORE_EXPORT
+# define KDTOOLSGUI_EXPORT
+# define KDTOOLSXML_EXPORT
+# define KDTOOLS_UPDATER_EXPORT
+#endif // KDTOOLS_SHARED
+
+#define MAKEINCLUDES_EXPORT
+
+#define DOXYGEN_PROPERTY( x )
+#ifdef DOXYGEN_RUN
+# define KDAB_IMPLEMENT_SAFE_BOOL_OPERATOR( func ) operator unspecified_bool_type() const { return func; }
+# define KDAB_USING_SAFE_BOOL_OPERATOR( Class ) operator unspecified_bool_type() const;
+#else
+# define KDAB_IMPLEMENT_SAFE_BOOL_OPERATOR( func ) \
+ private: struct __safe_bool_dummy__ { void nonnull() {} }; \
+ typedef void ( __safe_bool_dummy__::*unspecified_bool_type )(); \
+ public: \
+ operator unspecified_bool_type() const { \
+ return ( func ) ? &__safe_bool_dummy__::nonnull : 0 ; \
+ }
+#define KDAB_USING_SAFE_BOOL_OPERATOR( Class ) \
+ using Class::operator Class::unspecified_bool_type;
+#endif
+
+#define KDTOOLS_MAKE_RELATION_OPERATORS( Class, linkage ) \
+ linkage bool operator>( const Class & lhs, const Class & rhs ) { \
+ return operator<( rhs, lhs ); \
+ } \
+ linkage bool operator!=( const Class & lhs, const Class & rhs ) { \
+ return !operator==( lhs, rhs ); \
+ } \
+ linkage bool operator<=( const Class & lhs, const Class & rhs ) { \
+ return !operator>( lhs, rhs ); \
+ } \
+ linkage bool operator>=( const Class & lhs, const Class & rhs ) { \
+ return !operator<( lhs, rhs ); \
+ }
+
+template <typename T>
+inline T & __kdtools__dereference_for_methodcall( T & o ) {
+ return o;
+}
+
+template <typename T>
+inline T & __kdtools__dereference_for_methodcall( T * o ) {
+ return *o;
+}
+
+#define KDAB_SET_OBJECT_NAME( x ) __kdtools__dereference_for_methodcall( x ).setObjectName( QLatin1String( #x ) )
+
+KDTOOLSCORE_EXPORT bool _kdCheckQtVersion_impl( int major, int minor=0, int patchlevel=0 );
+static inline bool kdCheckQtVersion( unsigned int major, unsigned int minor=0, unsigned int patchlevel=0 ) {
+ return (major<<16|minor<<8|patchlevel) <= static_cast<unsigned int>(QT_VERSION)
+ || _kdCheckQtVersion_impl( major, minor, patchlevel );
+}
+
+#define KDTOOLS_DECLARE_PRIVATE_BASE( Class ) \
+protected: \
+ class Private; \
+ Private * d_func() { return _d; } \
+ const Private * d_func() const { return _d; } \
+ Class( Private * _d_, bool b ) : _d( _d_ ) { init(b); } \
+private: \
+ void init(bool); \
+private: \
+ Private * _d
+
+#define KDTOOLS_DECLARE_PRIVATE_DERIVED( Class, Base ) \
+protected: \
+ class Private; \
+ Private * d_func() { \
+ return reinterpret_cast<Private*>( Base::d_func() ); \
+ } \
+ const Private * d_func() const { \
+ return reinterpret_cast<const Private*>( Base::d_func() ); \
+ } \
+ Class( Private * _d_, bool b ) \
+ : Base( reinterpret_cast<Base::Private*>(_d_), b ) { init(b); } \
+private: \
+ void init(bool)
+
+
+#endif /* __KDTOOLS_KDTOOLSGLOBAL_H__ */
+
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdversion.cpp b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdversion.cpp
new file mode 100644
index 000000000..53f91412f
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdversion.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdversion.h"
+
+#include <QDebug>
+
+KDVersion::KDVersion()
+{
+}
+
+KDVersion::~KDVersion()
+{
+}
+
+bool KDVersion::isNull() const
+{
+ return parts.isEmpty();
+}
+
+QString KDVersion::toString() const
+{
+ return parts.join( QChar::fromLatin1( '.' ) );
+}
+
+KDVersion KDVersion::fromString( const QString& string )
+{
+ KDVersion result;
+ result.parts = string.split( QChar::fromLatin1( '.' ) );
+ return result;
+}
+
+bool operator<( const KDVersion& lhs, const KDVersion& rhs )
+{
+ for( int i = 0; i < lhs.parts.count(); ++i )
+ {
+ if( i == rhs.parts.count() )
+ return false;
+
+ const QString& l = lhs.parts[ i ];
+ const QString& r = lhs.parts[ i ];
+
+ bool okl = false;
+ bool okr = false;
+ const int li = l.toInt( &okl );
+ const int ri = r.toInt( &okr );
+
+ if( okl && okr )
+ {
+ if( li < ri )
+ return true;
+ }
+ else if( QString::localeAwareCompare( l, r ) < 0 )
+ {
+ return true;
+ }
+ }
+ return true;
+}
+
+bool operator==( const KDVersion& lhs, const KDVersion& rhs )
+{
+ return lhs.parts == rhs.parts;
+}
+
+QDebug operator<<( QDebug debug, const KDVersion& version )
+{
+ return debug << "KDVersion(" << version.toString().toLatin1().data() << ")";
+ return debug;
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdversion.h b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdversion.h
new file mode 100644
index 000000000..b71cb1933
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdversion.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef KDVERSION_H
+#define KDVERSION_H
+
+#include <KDToolsCore/kdtoolsglobal.h>
+
+#include <QtCore/QStringList>
+
+class KDTOOLSCORE_EXPORT KDVersion
+{
+ friend bool operator<( const KDVersion& lhs, const KDVersion& rhs );
+ friend bool operator==( const KDVersion& lhs, const KDVersion& rhs );
+public:
+ KDVersion();
+ virtual ~KDVersion();
+
+ bool isNull() const;
+
+ QString toString() const;
+ static KDVersion fromString( const QString& string );
+
+private:
+ QStringList parts;
+};
+
+bool operator<( const KDVersion& lhs, const KDVersion& rhs );
+bool operator==( const KDVersion& lhs, const KDVersion& rhs );
+
+QDebug operator<<( QDebug debug, const KDVersion& version );
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdwatchdog.cpp b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdwatchdog.cpp
new file mode 100644
index 000000000..7c0abd486
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdwatchdog.cpp
@@ -0,0 +1,115 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdwatchdog.h"
+
+#include <QTimer>
+
+/*!
+ \internal
+ */
+class KDWatchdog::Private
+{
+public:
+ Private()
+ : active( true )
+ {
+ }
+
+ bool active;
+ QTimer timer;
+};
+
+/*!
+ Creates a new KDWatchdog with \a parent.
+ */
+KDWatchdog::KDWatchdog( QObject* parent )
+ : QObject( parent )
+{
+ d->timer.setSingleShot( true );
+ connect( &d->timer, SIGNAL( timeout() ), this, SIGNAL( timeout() ) );
+ setTimeoutInterval( 30000 );
+ activate();
+}
+
+/*!
+ Destroys the KDWatchdog.
+ */
+KDWatchdog::~KDWatchdog()
+{
+}
+
+bool KDWatchdog::isActive() const
+{
+ return d->active;
+}
+
+int KDWatchdog::timeoutInterval() const
+{
+ return d->timer.interval();
+}
+
+void KDWatchdog::setTimeoutInterval( int interval )
+{
+ d->timer.setInterval( interval );
+ resetTimeoutTimer();
+}
+
+void KDWatchdog::setActive( bool active )
+{
+ if( d->active == active )
+ return;
+ d->active = active;
+ if( d->active )
+ d->timer.start();
+ else
+ d->timer.stop();
+}
+
+/*!
+ Activates the watchdog.
+ */
+void KDWatchdog::activate()
+{
+ setActive( true );
+}
+
+/*!
+ Deactivates the watchdog.
+ */
+void KDWatchdog::deactivate()
+{
+ setActive( false );
+}
+
+/*!
+ Resets the watchdog timer. This slot should be called whenever
+ the watched event occures.
+ If the watchdog has been stop()'ed, nothing happens.
+ */
+void KDWatchdog::resetTimeoutTimer()
+{
+ if( d->active )
+ d->timer.start();
+}
+
+#include "moc_kdwatchdog.cpp"
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/kdwatchdog.h b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdwatchdog.h
new file mode 100644
index 000000000..4319b0e8b
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/kdwatchdog.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef __KDTOOLS__CORE__KDWATCHDOG_H__
+#define __KDTOOLS__CORE__KDWATCHDOG_H__
+
+#include <QtCore/QObject>
+
+#include <KDToolsCore/pimpl_ptr.h>
+
+class KDTOOLSCORE_EXPORT KDWatchdog : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY( bool active READ isActive WRITE setActive )
+ Q_PROPERTY( int timeoutInterval READ timeoutInterval WRITE setTimeoutInterval )
+
+public:
+ explicit KDWatchdog( QObject* parent = 0 );
+ ~KDWatchdog();
+
+ bool isActive() const;
+ int timeoutInterval() const;
+
+public Q_SLOTS:
+ void setTimeoutInterval( int interval );
+
+ void setActive( bool active );
+ void activate();
+ void deactivate();
+
+ void resetTimeoutTimer();
+
+Q_SIGNALS:
+ void timeout();
+
+private:
+ class Private;
+ kdtools::pimpl_ptr< Private > d;
+};
+
+#endif /* __KDTOOLS__CORE__KDWATCHDOG_H__ */
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/pimpl_ptr b/installerbuilder/libinstaller/kdtools/KDToolsCore/pimpl_ptr
new file mode 100644
index 000000000..aa2f3984a
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/pimpl_ptr
@@ -0,0 +1 @@
+#include "pimpl_ptr.h"
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/pimpl_ptr.cpp b/installerbuilder/libinstaller/kdtools/KDToolsCore/pimpl_ptr.cpp
new file mode 100644
index 000000000..1a7f017a1
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/pimpl_ptr.cpp
@@ -0,0 +1,225 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "pimpl_ptr.h"
+
+/*!
+ \class pimpl_ptr:
+ \ingroup core smartptr
+ \brief Owning pointer for private implementations
+ \since_c 2.1
+
+ (The exception safety of this class has not been evaluated yet.)
+
+ pimpl_ptr is a smart immutable pointer, which owns the contained object. Unlike other smart pointers,
+ it creates a standard constructed object when instanciated via the
+ \link pimpl_ptr() standard constructor\endlink.
+ Additionally, pimpl_ptr respects constness of the pointer object and returns \c const \c T* for
+ a const pimpl_ptr object.
+
+ The content of a pimpl_ptr cannot be changed during it's lifetime.
+
+ \section general-use General Use
+
+ The general use case of pimpl_ptr is the "Pimpl Idiom", i.e. hiding the private implementation of a class
+ from the user's compiler which see \c MyClass as
+
+ \code
+ class MyClass
+ {
+ public:
+ MyClass();
+ ~MyClass();
+
+ // public class API
+ int value() const;
+
+ private:
+ class Private; // defined later
+ kdtools::pimpl_ptr< Private > d;
+ };
+ \endcode
+
+ but not the private parts of it. These can only be seen (and accessed) by the code knowing \c MyClass::Private:
+
+ \code
+ class MyClass::Private
+ {
+ public:
+ int value;
+ };
+
+ MyClass::MyClass()
+ {
+ // d was automatically filled with new Private
+ d->value = 42;
+ }
+
+ MyClass::~MyClass()
+ {
+ // the content of d gets deleted automatically
+ }
+
+ int MyClass::value() const
+ {
+ // access the private part:
+ // since MyClass::value() is const, the returned pointee is const, too
+ return d->value;
+ }
+ \endcode
+
+*/
+
+/*!
+ \fn pimpl_ptr::pimpl_ptr()
+
+ Default constructor. Constructs a pimpl_tr that contains (owns) a standard constructed
+ instance of \c T.
+
+ \post \c *this owns a new object.
+*/
+
+/*!
+ \fn pimpl_ptr::pimpl_ptr( T * t )
+
+ Constructor. Constructs a pimpl_ptr that contains (owns) \a t.
+
+ \post get() == obj
+*/
+
+/*!
+ \fn pimpl_ptr::~pimpl_ptr()
+
+ Destructor.
+
+ \post The object previously owned by \c *this has been deleted.
+*/
+
+/*!
+ \fn const T * pimpl_ptr::get() const
+
+ \returns a const pointer to the contained (owned) object.
+ \overload
+*/
+
+/*!
+ \fn T * pimpl_ptr::get()
+
+ \returns a pointer to the contained (owned) object.
+*/
+
+/*!
+ \fn const T & pimpl_ptr::operator*() const
+
+ Dereference operator. Returns \link get() *get()\endlink.
+ \overload
+*/
+
+/*!
+ \fn T & pimpl_ptr::operator*()
+
+ Dereference operator. Returns \link get() *get()\endlink.
+*/
+
+/*!
+ \fn const T * pimpl_ptr::operator->() const
+
+ Member-by-pointer operator. Returns get().
+ \overload
+*/
+
+/*!
+ \fn T * pimpl_ptr::operator->()
+
+ Member-by-pointer operator. Returns get().
+*/
+
+#ifdef KDTOOLSCORE_UNITTESTS
+
+#include <KDUnitTest/test.h>
+
+#include <QObject>
+#include <QPointer>
+
+namespace
+{
+ struct ConstTester
+ {
+ bool isConst()
+ {
+ return false;
+ }
+
+ bool isConst() const
+ {
+ return true;
+ }
+ };
+}
+
+KDAB_UNITTEST_SIMPLE( pimpl_ptr, "kdcoretools" ) {
+
+ {
+ kdtools::pimpl_ptr< QObject > p;
+ assertNotNull( p.get() );
+ assertNull( p->parent() );
+ }
+
+
+ {
+ QPointer< QObject > o;
+ {
+ kdtools::pimpl_ptr< QObject > qobject( new QObject );
+ o = qobject.get();
+ assertEqual( o, qobject.operator->() );
+ assertEqual( o, &(qobject.operator*()) );
+ }
+ assertNull( o );
+ }
+
+ {
+ const kdtools::pimpl_ptr< QObject > qobject( new QObject );
+ const QObject* o = qobject.get();
+ assertEqual( o, qobject.operator->() );
+ assertEqual( o, &(qobject.operator*()) );
+ }
+
+ {
+ kdtools::pimpl_ptr< QObject > o1;
+ assertTrue( o1 );
+ kdtools::pimpl_ptr< QObject > o2( 0 );
+ assertFalse( o2 );
+ }
+
+ {
+ const kdtools::pimpl_ptr< ConstTester > o1;
+ kdtools::pimpl_ptr< ConstTester > o2;
+ assertTrue( o1->isConst() );
+ assertFalse( o2->isConst() );
+ assertTrue( (*o1).isConst() );
+ assertFalse( (*o2).isConst() );
+ assertTrue( o1.get()->isConst() );
+ assertFalse( o2.get()->isConst() );
+ }
+}
+
+#endif // KDTOOLSCORE_UNITTESTS
diff --git a/installerbuilder/libinstaller/kdtools/KDToolsCore/pimpl_ptr.h b/installerbuilder/libinstaller/kdtools/KDToolsCore/pimpl_ptr.h
new file mode 100644
index 000000000..195b967d1
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDToolsCore/pimpl_ptr.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef __KDTOOLSCORE__PIMPL_PTR_H__
+#define __KDTOOLSCORE__PIMPL_PTR_H__
+
+#include <KDToolsCore/kdtoolsglobal.h>
+
+#ifndef DOXYGEN_RUN
+namespace kdtools {
+#endif
+
+ template <typename T>
+ class MAKEINCLUDES_EXPORT pimpl_ptr {
+ KDAB_DISABLE_COPY( pimpl_ptr );
+ T * d;
+ public:
+ pimpl_ptr() : d( new T ) {}
+ explicit pimpl_ptr( T * t ) : d( t ) {}
+ ~pimpl_ptr() { delete d; d = 0; }
+
+ T * get() { return d; }
+ const T * get() const { return d; }
+
+ T * operator->() { return get(); }
+ const T * operator->() const { return get(); }
+
+ T & operator*() { return *get(); }
+ const T & operator*() const { return *get(); }
+
+ KDAB_IMPLEMENT_SAFE_BOOL_OPERATOR( get() )
+ };
+
+ // these are not implemented, so's we can catch their use at
+ // link-time. Leaving them undeclared would open up a comparison
+ // via operator unspecified-bool-type().
+ template <typename T, typename S>
+ void operator==( const pimpl_ptr<T> &, const pimpl_ptr<S> & );
+ template <typename T, typename S>
+ void operator!=( const pimpl_ptr<T> &, const pimpl_ptr<S> & );
+
+#ifndef DOXYGEN_RUN
+} // namespace kdtools
+#endif
+
+#endif /* __KDTOOLSCORE__PIMPL_PTR_H__ */
+
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/Application b/installerbuilder/libinstaller/kdtools/KDUpdater/Application
new file mode 100644
index 000000000..7545e9447
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/Application
@@ -0,0 +1 @@
+#include "kdupdaterapplication.h"
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/FileDownloader b/installerbuilder/libinstaller/kdtools/KDUpdater/FileDownloader
new file mode 100644
index 000000000..beca4f9c1
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/FileDownloader
@@ -0,0 +1 @@
+#include "kdupdaterfiledownloader.h"
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/FileDownloaderFactory b/installerbuilder/libinstaller/kdtools/KDUpdater/FileDownloaderFactory
new file mode 100644
index 000000000..65dbb7a4e
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/FileDownloaderFactory
@@ -0,0 +1 @@
+#include "kdupdaterfiledownloaderfactory.h"
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/KDUpdater b/installerbuilder/libinstaller/kdtools/KDUpdater/KDUpdater
new file mode 100644
index 000000000..a327ece5b
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/KDUpdater
@@ -0,0 +1,20 @@
+#include "kdupdater.h"
+#include "kdupdaterapplication.h"
+#include "kdupdatercrypto.h"
+#include "kdupdaterfiledownloader.h"
+#include "kdupdaterfiledownloaderfactory.h"
+#include "kdupdaterpackagesinfo.h"
+#include "kdupdaterpackagesview.h"
+#include "kdupdatersignatureverificationresult.h"
+#include "kdupdatersignatureverificationrunnable.h"
+#include "kdupdatersignatureverifier.h"
+#include "kdupdatertask.h"
+#include "kdupdaterupdate.h"
+#include "kdupdaterupdatefinder.h"
+#include "kdupdaterupdateinstaller.h"
+#include "kdupdaterupdateoperation.h"
+#include "kdupdaterupdateoperationfactory.h"
+#include "kdupdaterupdateoperations.h"
+#include "kdupdaterupdatesdialog.h"
+#include "kdupdaterupdatesourcesinfo.h"
+#include "kdupdaterupdatesourcesview.h"
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/KDUpdater.pri b/installerbuilder/libinstaller/kdtools/KDUpdater/KDUpdater.pri
new file mode 100644
index 000000000..d97399040
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/KDUpdater.pri
@@ -0,0 +1,73 @@
+DEPENDPATH += $$PWD
+INCLUDEPATH += $$PWD
+
+CONFIG( shared, static|shared) {
+ DEFINES += BUILD_SHARED_KDUPDATER
+}
+
+HEADERS += $$PWD/kdupdater.h \
+ $$PWD/kdupdaterapplication.h \
+ $$PWD/kdupdatercrypto.h \
+ $$PWD/kdupdaterfiledownloader.h \
+ $$PWD/kdupdaterfiledownloader_p.h \
+ $$PWD/kdupdaterfiledownloaderfactory.h \
+ $$PWD/kdupdaterpackagesinfo.h \
+ $$PWD/kdupdaterpackagesview.h \
+ $$PWD/kdupdatersignatureverificationresult.h \
+ $$PWD/kdupdatersignatureverifier.h \
+ $$PWD/kdupdaterupdate.h \
+ $$PWD/kdupdaterupdateoperation.h \
+ $$PWD/kdupdaterupdateoperationfactory.h \
+ $$PWD/kdupdaterupdateoperations.h \
+ $$PWD/kdupdaterupdatesourcesinfo.h \
+ $$PWD/kdupdatertask.h \
+ $$PWD/kdupdatersignatureverificationrunnable.h \
+ $$PWD/kdupdaterupdatefinder.h \
+ $$PWD/kdupdaterupdatesinfo_p.h \
+ $$PWD/kdupdaterupdateinstaller.h \
+ $$PWD/kdupdaterufuncompressor_p.h \
+ $$PWD/kdupdaterupdatesdialog.h \
+ $$PWD/kdupdaterupdatesourcesview.h \
+ $$PWD/kdupdaterufcompresscommon_p.h \
+ $$PWD/environment.h
+
+SOURCES += $$PWD/kdupdaterapplication.cpp \
+ $$PWD/kdupdatercrypto.cpp \
+ $$PWD/kdupdaterfiledownloader.cpp \
+ $$PWD/kdupdaterfiledownloaderfactory.cpp \
+ $$PWD/kdupdaterpackagesinfo.cpp \
+ $$PWD/kdupdaterpackagesview.cpp \
+ $$PWD/kdupdatersignatureverificationresult.cpp \
+ $$PWD/kdupdatersignatureverifier.cpp \
+ $$PWD/kdupdaterupdate.cpp \
+ $$PWD/kdupdaterupdateoperation.cpp \
+ $$PWD/kdupdaterupdateoperationfactory.cpp \
+ $$PWD/kdupdaterupdateoperations.cpp \
+ $$PWD/kdupdaterupdatesourcesinfo.cpp \
+ $$PWD/kdupdatertask.cpp \
+ $$PWD/kdupdatersignatureverificationrunnable.cpp \
+ $$PWD/kdupdaterupdatefinder.cpp \
+ $$PWD/kdupdaterupdatesinfo.cpp \
+ $$PWD/kdupdaterupdateinstaller.cpp \
+ $$PWD/kdupdaterufuncompressor.cpp \
+ $$PWD/kdupdaterupdatesdialog.cpp \
+ $$PWD/kdupdaterupdatesourcesview.cpp \
+ $$PWD/kdupdaterufcompresscommon.cpp \
+ $$PWD/environment.cpp
+
+
+
+FORMS += $$PWD/updatesdialog.ui \
+ $$PWD/addupdatesourcedialog.ui
+
+DEFINES += KDUPDATERGUITEXTBROWSER \
+ KDUPDATERVIEW=QTextBrowser
+QT += gui
+
+TRY_INCLUDEPATHS = /include /usr/include /usr/local/include $$QMAKE_INCDIR $$INCLUDEPATH
+win32:TRY_INCLUDEPATHS += $$PWD/../../3rdparty/openssl-0.9.8k/src/include
+linux-lsb-g++:TRY_INCLUDEPATHS = $$QMAKE_INCDIR $$INCLUDEPATH
+for(p, TRY_INCLUDEPATHS) {
+ pp = $$join(p, "", "", "/openssl")
+ exists($$pp):INCLUDEPATH *= $$p
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/PackagesInfo b/installerbuilder/libinstaller/kdtools/KDUpdater/PackagesInfo
new file mode 100644
index 000000000..8e709882d
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/PackagesInfo
@@ -0,0 +1 @@
+#include "kdupdaterpackagesinfo.h"
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/SignatureVerificationResult b/installerbuilder/libinstaller/kdtools/KDUpdater/SignatureVerificationResult
new file mode 100644
index 000000000..5a71cdfde
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/SignatureVerificationResult
@@ -0,0 +1 @@
+#include "kdupdatersignatureverificationresult.h"
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/SignatureVerifier b/installerbuilder/libinstaller/kdtools/KDUpdater/SignatureVerifier
new file mode 100644
index 000000000..3d9d7f946
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/SignatureVerifier
@@ -0,0 +1 @@
+#include "kdupdatersignatureverifier.h"
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/Update b/installerbuilder/libinstaller/kdtools/KDUpdater/Update
new file mode 100644
index 000000000..8328b020b
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/Update
@@ -0,0 +1 @@
+#include "kdupdaterupdate.h"
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/UpdateFinder b/installerbuilder/libinstaller/kdtools/KDUpdater/UpdateFinder
new file mode 100644
index 000000000..71666b90d
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/UpdateFinder
@@ -0,0 +1 @@
+#include "kdupdaterupdatefinder.h"
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/UpdateOperation b/installerbuilder/libinstaller/kdtools/KDUpdater/UpdateOperation
new file mode 100644
index 000000000..fd82bafdb
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/UpdateOperation
@@ -0,0 +1 @@
+#include "kdupdaterupdateoperation.h"
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/UpdateOperationFactory b/installerbuilder/libinstaller/kdtools/KDUpdater/UpdateOperationFactory
new file mode 100644
index 000000000..bd13c19c5
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/UpdateOperationFactory
@@ -0,0 +1 @@
+#include "kdupdaterupdateoperationfactory.h"
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/UpdateSourcesInfo b/installerbuilder/libinstaller/kdtools/KDUpdater/UpdateSourcesInfo
new file mode 100644
index 000000000..b422ec594
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/UpdateSourcesInfo
@@ -0,0 +1 @@
+#include "kdupdaterupdatesourcesinfo.h"
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/UpdatesDialog b/installerbuilder/libinstaller/kdtools/KDUpdater/UpdatesDialog
new file mode 100644
index 000000000..b1fbb7803
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/UpdatesDialog
@@ -0,0 +1 @@
+#include "kdupdaterupdatesdialog.h"
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/addupdatesourcedialog.ui b/installerbuilder/libinstaller/kdtools/KDUpdater/addupdatesourcedialog.ui
new file mode 100644
index 000000000..c0de05109
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/addupdatesourcedialog.ui
@@ -0,0 +1,193 @@
+<ui version="4.0" >
+ <class>AddUpdateSourceDialog</class>
+ <widget class="QDialog" name="AddUpdateSourceDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>239</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Add Update Source</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>&amp;Name</string>
+ </property>
+ <property name="buddy" >
+ <cstring>txtName</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QLineEdit" name="txtName" >
+ <property name="font" >
+ <font>
+ <pointsize>10</pointsize>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label_2" >
+ <property name="text" >
+ <string>&amp;Title</string>
+ </property>
+ <property name="buddy" >
+ <cstring>txtTitle</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QLineEdit" name="txtTitle" >
+ <property name="font" >
+ <font>
+ <pointsize>9</pointsize>
+ <italic>false</italic>
+ </font>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <widget class="QLabel" name="label_3" >
+ <property name="text" >
+ <string>&amp;Description</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <property name="buddy" >
+ <cstring>txtDescription</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QTextEdit" name="txtDescription" />
+ </item>
+ <item row="3" column="0" >
+ <widget class="QLabel" name="label_4" >
+ <property name="text" >
+ <string>&amp;URL</string>
+ </property>
+ <property name="buddy" >
+ <cstring>txtUrl</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" >
+ <widget class="QLineEdit" name="txtUrl" >
+ <property name="palette" >
+ <palette>
+ <active>
+ <colorrole role="Text" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>45</green>
+ <blue>195</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </active>
+ <inactive>
+ <colorrole role="Text" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>45</green>
+ <blue>195</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </inactive>
+ <disabled>
+ <colorrole role="Text" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>106</red>
+ <green>104</green>
+ <blue>100</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </disabled>
+ </palette>
+ </property>
+ <property name="font" >
+ <font>
+ <underline>true</underline>
+ </font>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>AddUpdateSourceDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>257</x>
+ <y>229</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>AddUpdateSourceDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>325</x>
+ <y>229</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/environment.cpp b/installerbuilder/libinstaller/kdtools/KDUpdater/environment.cpp
new file mode 100644
index 000000000..c1ddc11f1
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/environment.cpp
@@ -0,0 +1,55 @@
+#include "environment.h"
+
+#include <QHash>
+#include <QProcess>
+#include <QProcessEnvironment>
+
+using namespace KDUpdater;
+
+class Environment::Private {
+public:
+ static Environment* s_instance;
+ QHash<QString, QString> tempValues;
+};
+
+Environment* Environment::Private::s_instance = 0;
+
+Environment::Environment()
+ : d( new Private )
+{
+}
+
+Environment::~Environment() {
+ delete d;
+}
+
+Environment* Environment::instance() {
+ if ( !Private::s_instance )
+ Private::s_instance = new Environment;
+ return Private::s_instance;
+}
+
+QString Environment::value( const QString& key, const QString& defvalue ) const {
+ const QHash<QString,QString>::ConstIterator it = d->tempValues.constFind( key );
+ if ( it != d->tempValues.constEnd() )
+ return *it;
+ else
+ return QProcessEnvironment::systemEnvironment().value( key, defvalue );
+}
+
+void Environment::setTemporaryValue( const QString& key, const QString& value ) {
+ d->tempValues.insert( key, value );
+}
+
+QProcessEnvironment Environment::applyTo( const QProcessEnvironment& qpe_ ) const {
+ QProcessEnvironment qpe( qpe_ );
+ QHash<QString, QString>::ConstIterator it = d->tempValues.constBegin();
+ const QHash<QString, QString>::ConstIterator end = d->tempValues.constEnd();
+ for ( ; it != end; ++it )
+ qpe.insert( it.key(), it.value() );
+ return qpe;
+}
+
+void Environment::applyTo( QProcess* proc ) {
+ proc->setProcessEnvironment( applyTo( proc->processEnvironment() ) );
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/environment.h b/installerbuilder/libinstaller/kdtools/KDUpdater/environment.h
new file mode 100644
index 000000000..001afbbc2
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/environment.h
@@ -0,0 +1,36 @@
+#ifndef LIBINSTALLER_ENVIRONMENT_H
+#define LIBINSTALLER_ENVIRONMENT_H
+
+#include "kdupdaterupdateoperation.h"
+
+#include <QString>
+
+class QProcess;
+class QProcessEnvironment;
+
+namespace KDUpdater {
+
+class KDTOOLS_UPDATER_EXPORT Environment {
+ public:
+ static Environment* instance();
+
+ ~Environment();
+
+ QString value( const QString& key, const QString& defaultValue=QString() ) const;
+ void setTemporaryValue( const QString& key, const QString& value );
+
+ QProcessEnvironment applyTo( const QProcessEnvironment& qpe ) const;
+ void applyTo( QProcess* process );
+
+ private:
+ Environment();
+
+ private:
+ Q_DISABLE_COPY(Environment)
+ class Private;
+ Private* const d;
+};
+
+}
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdater.h b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdater.h
new file mode 100644
index 000000000..9e0007155
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdater.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef KD_UPDATER_H
+#define KD_UPDATER_H
+
+#include <QtGlobal>
+
+#ifdef KDTOOLS_SHARED
+ #if defined(BUILD_SHARED_KDUPDATER)
+ #define KDTOOLS_UPDATER_EXPORT Q_DECL_EXPORT
+ #else
+ #define KDTOOLS_UPDATER_EXPORT Q_DECL_IMPORT
+ #endif
+#else
+ #define KDTOOLS_UPDATER_EXPORT
+#endif
+
+namespace KDUpdater
+{
+ enum Error
+ {
+ ENoError = 0,
+ ECannotStartTask,
+ ECannotPauseTask,
+ ECannotResumeTask,
+ ECannotStopTask,
+ EUnknown
+ };
+
+ enum UpdateType {
+ PackageUpdate = 0x1,
+ CompatUpdate = 0x2,
+ NewPackage = 0x4,
+ AllUpdate = PackageUpdate | CompatUpdate
+ };
+ Q_DECLARE_FLAGS( UpdateTypes, UpdateType )
+ Q_DECLARE_OPERATORS_FOR_FLAGS( UpdateTypes )
+
+ KDTOOLS_UPDATER_EXPORT int compareVersion(const QString& v1, const QString& v2);
+}
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterapplication.cpp b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterapplication.cpp
new file mode 100644
index 000000000..cf4379c90
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterapplication.cpp
@@ -0,0 +1,324 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdupdaterapplication.h"
+#include "kdupdaterpackagesinfo.h"
+#include "kdupdatersignatureverifier.h"
+#include "kdupdaterupdatesourcesinfo.h"
+
+#include <QCoreApplication>
+#include <QDebug>
+#include <QDir>
+#include <QSettings>
+
+using namespace KDUpdater;
+
+/*!
+ \defgroup kdupdater KD Updater
+ \since_l 2.1
+
+ "KD Updater" is a library from KDAB that helps in enabling automatic updates for your applications.
+ All classes belonging to the "KD Updater" library are defined in the \ref KDUpdater namespace.
+
+ TODO: this comes from the former mainpage:
+KD Updater is a tool to automatically detect, retrieve, install and activate updates to software
+applications and libraries. It is intended to be used with Qt based applications, and developed
+against the Qt 4 series. It is a library that users link to their application. It uses only accepted
+standard protocols, and does not require any other 3rd party libraries that are not shipped with
+Qt.
+
+KD Updater is generic in that it is not developed for one specific application. The first version is
+experimental. If it proves successful and useful, it will be integrated into KDAB's KD Tools
+package. It is part of KDAB's strategy to provide functionality missing in Qt that is required for
+medium-to-large scale software systems.
+*/
+
+/*!
+ \namespace KDUpdater
+*/
+
+ConfigurationInterface::~ConfigurationInterface()
+{
+}
+
+namespace {
+ class DefaultConfigImpl : public ConfigurationInterface
+ {
+ public:
+ QVariant value( const QString& key ) const
+ {
+ QSettings settings;
+ settings.beginGroup( QLatin1String("KDUpdater") );
+ return settings.value( key );
+ }
+
+ void setValue( const QString& key, const QVariant& value )
+ {
+ QSettings settings;
+ settings.beginGroup( QLatin1String("KDUpdater") );
+ settings.setValue( key, value );
+ }
+ };
+}
+
+/*!
+ \class KDUpdater::Application kdupdaterapplication.h KDUpdaterApplication
+ \ingroup kdupdater
+ \brief This class represents an application that can be updated.
+
+ A KDUpdater application is an application that needs to interact with one or more update servers and
+ downloads/installs updates This class helps in describing an application in terms of:
+ \li application Directory
+ \li packages XML file name and its corresponding KDUpdater::PackagesInfo object
+ \li update Sources XML file name and its corresponding KDUpdater::UpdateSourcesInfo object
+
+ User can also retrieve some informations from this class:
+ \li application name
+ \li application version
+ \li compat level
+*/
+
+struct Application::ApplicationData
+{
+ explicit ApplicationData( ConfigurationInterface* config ) :
+ packagesInfo(0),
+ updateSourcesInfo(0),
+ configurationInterface( config ? config : new DefaultConfigImpl )
+ {
+ const QStringList oldFiles = configurationInterface->value( QLatin1String("FilesForDelayedDeletion") ).toStringList();
+ Q_FOREACH( const QString& i, oldFiles ) { //TODO this should happen asnyc and report errors, I guess
+ QFile f( i );
+ if ( f.exists() && !f.remove() ) {
+ qWarning( "Could not delete file %s: %s", qPrintable(i), qPrintable(f.errorString()) );
+ filesForDelayedDeletion << i; // try again next time
+ }
+ }
+ configurationInterface->setValue( QLatin1String("FilesForDelayedDeletion"), filesForDelayedDeletion );
+ }
+
+ ~ApplicationData()
+ {
+ delete packagesInfo;
+ delete updateSourcesInfo;
+ qDeleteAll( verifiers );
+ delete configurationInterface;
+ }
+
+ static Application* instance;
+
+ QString applicationDirectory;
+ PackagesInfo* packagesInfo;
+ UpdateSourcesInfo* updateSourcesInfo;
+ QMap<Application::SignatureTarget, const SignatureVerifier*> verifiers;
+ QStringList filesForDelayedDeletion;
+ ConfigurationInterface* configurationInterface;
+};
+
+Application* Application::ApplicationData::instance = 0;
+
+/*!
+ Constructor of the Application class. The class will be constructed and configured to
+ assume the application directory to be the directory in which the application exists. The
+ application name is assumed to be QCoreApplication::applicationName()
+*/
+Application::Application(ConfigurationInterface* config, QObject* p) : QObject(p)
+{
+ d = new Application::ApplicationData( config );
+ d->packagesInfo = new PackagesInfo(this);
+ d->updateSourcesInfo = new UpdateSourcesInfo(this);
+
+ setApplicationDirectory( QCoreApplication::applicationDirPath() );
+
+ ApplicationData::instance = this;
+}
+
+/*!
+ Destructor
+*/
+Application::~Application()
+{
+ if( this == ApplicationData::instance )
+ ApplicationData::instance = 0;
+ delete d;
+}
+
+/*!
+ Returns a previousle created Application instance.
+ */
+Application* Application::instance()
+{
+ return ApplicationData::instance;
+}
+
+/*!
+ Changes the applicationDirPath directory to \c dir. Packages.xml and UpdateSources.xml found in the new
+ application directory will be used.
+*/
+void Application::setApplicationDirectory(const QString& dir)
+{
+ if( d->applicationDirectory == dir )
+ return;
+
+ QDir dirObj(dir);
+
+ // FIXME: Perhaps we should check whether dir exists on the local file system or not
+ d->applicationDirectory = dirObj.absolutePath();
+ setPackagesXMLFileName( QString::fromLatin1( "%1/Packages.xml" ).arg(dir) );
+ setUpdateSourcesXMLFileName( QString::fromLatin1( "%1/UpdateSources.xml" ).arg(dir) );
+}
+
+/*!
+ Returns path to the application directory.
+*/
+QString Application::applicationDirectory() const
+{
+ return d->applicationDirectory;
+}
+
+/*!
+ Returns the application name.
+*/
+QString Application::applicationName() const
+{
+ if( d->packagesInfo->isValid() )
+ return d->packagesInfo->applicationName();
+
+ return QCoreApplication::applicationName();
+}
+
+/*!
+ Returns the application version.
+*/
+QString Application::applicationVersion() const
+{
+ if( d->packagesInfo->isValid() )
+ return d->packagesInfo->applicationVersion();
+
+ return QString();
+}
+
+const SignatureVerifier* Application::signatureVerifier( SignatureTarget target ) const
+{
+ return d->verifiers.value( target );
+}
+
+void Application::setSignatureVerifier( SignatureTarget target, const SignatureVerifier* v )
+{
+ delete d->verifiers.value( target );
+ d->verifiers.remove( target );
+ if ( v )
+ d->verifiers.insert( target, v->clone() );
+}
+
+/*!
+ Returns the compat level that this application is in.
+*/
+int Application::compatLevel() const
+{
+ if(d->packagesInfo->isValid())
+ return d->packagesInfo->compatLevel();
+
+ return -1;
+}
+
+void Application::addUpdateSource( const QString& name, const QString& title,
+ const QString& description, const QUrl& url, int priority )
+{
+ UpdateSourceInfo info;
+ info.name = name;
+ info.title = title;
+ info.description = description;
+ info.url = url;
+ info.priority = priority;
+ d->updateSourcesInfo->addUpdateSourceInfo( info );
+}
+
+
+/*!
+ Sets the file name of the Package XML file for this application. By default this is assumed to be
+ Packages.xml in the application directory.
+
+ \sa KDUpdater::PackagesInfo::setFileName()
+*/
+void Application::setPackagesXMLFileName(const QString& fileName)
+{
+ d->packagesInfo->setFileName( fileName );
+}
+
+/*!
+ Returns the Package XML file name.
+*/
+QString Application::packagesXMLFileName() const
+{
+ return d->packagesInfo->fileName();
+}
+
+/*!
+ Returns the \ref PackagesInfo object associated with this application.
+*/
+PackagesInfo* Application::packagesInfo() const
+{
+ return d->packagesInfo;
+}
+
+/*!
+ Sets the file name of the Package XML file for this application. By default this is assumed to be
+ Packages.xml in the application directory.
+
+ \sa KDUpdater::UpdateSourcesInfo::setFileName()
+*/
+void Application::setUpdateSourcesXMLFileName(const QString& fileName)
+{
+ d->updateSourcesInfo->setFileName( fileName );
+}
+
+/*!
+ Returns the Update Sources XML file name.
+*/
+QString Application::updateSourcesXMLFileName() const
+{
+ return d->updateSourcesInfo->fileName();
+}
+
+/*!
+ Returns the \ref UpdateSourcesInfo object associated with this application.
+*/
+UpdateSourcesInfo* Application::updateSourcesInfo() const
+{
+ return d->updateSourcesInfo;
+}
+
+void Application::printError( int errorCode, const QString& error )
+{
+ qDebug() << errorCode << error;
+}
+
+QStringList Application::filesForDelayedDeletion() const
+{
+ return d->filesForDelayedDeletion;
+}
+
+void Application::addFilesForDelayedDeletion( const QStringList& files )
+{
+ d->filesForDelayedDeletion << files;
+ d->configurationInterface->setValue( QLatin1String("FilesForDelayedDeletion"), d->filesForDelayedDeletion );
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterapplication.h b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterapplication.h
new file mode 100644
index 000000000..3970236d3
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterapplication.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef KD_UPDATER_APPLICATION_H
+#define KD_UPDATER_APPLICATION_H
+
+#include "kdupdater.h"
+#include <QObject>
+
+class QUrl;
+
+namespace KDUpdater
+{
+ class PackagesInfo;
+ class SignatureVerifier;
+ class UpdateSourcesInfo;
+
+ class ConfigurationInterface {
+ public:
+ virtual ~ConfigurationInterface();
+ virtual QVariant value( const QString& key ) const = 0;
+ virtual void setValue( const QString& key, const QVariant& value ) = 0;
+ };
+
+ class KDTOOLS_UPDATER_EXPORT Application : public QObject
+ {
+ Q_OBJECT
+
+ public:
+ enum SignatureTarget {
+ Metadata,
+ Packages
+ };
+
+ explicit Application( ConfigurationInterface* config=0, QObject* parent=0);
+ ~Application();
+
+ static Application* instance();
+
+ void setApplicationDirectory(const QString& dir);
+ QString applicationDirectory() const;
+
+ QString applicationName() const;
+ QString applicationVersion() const;
+ int compatLevel() const;
+
+ const SignatureVerifier* signatureVerifier( SignatureTarget target ) const;
+ void setSignatureVerifier( SignatureTarget target, const SignatureVerifier* verifier );
+
+ void setPackagesXMLFileName(const QString& fileName);
+ QString packagesXMLFileName() const;
+ PackagesInfo* packagesInfo() const;
+
+ void addUpdateSource( const QString& name, const QString& title,
+ const QString& description, const QUrl& url, int priority = -1 );
+
+ void setUpdateSourcesXMLFileName(const QString& fileName);
+ QString updateSourcesXMLFileName() const;
+ UpdateSourcesInfo* updateSourcesInfo() const;
+
+ QStringList filesForDelayedDeletion() const;
+ void addFilesForDelayedDeletion( const QStringList& files );
+
+ public Q_SLOTS:
+ void printError( int errorCode, const QString& error );
+
+ private:
+ struct ApplicationData;
+ ApplicationData* d;
+ };
+
+}
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatercrypto.cpp b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatercrypto.cpp
new file mode 100644
index 000000000..8e5832084
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatercrypto.cpp
@@ -0,0 +1,743 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdupdatercrypto.h"
+
+#include <openssl/ssl.h>
+#include <openssl/rsa.h>
+
+#include <QCoreApplication>
+#include <QCryptographicHash>
+#include <QDebug>
+#include <QStringList>
+#include <QFile>
+#include <QMutex>
+#include <QLibrary>
+#include <QDir>
+#include <QTemporaryFile>
+
+//BEGIN code taken from qsslsocket_openssl_symbols.cpp
+
+#define DUMMYARG
+
+#define CLEARFUNC(func) \
+ _kd_##func = 0;
+
+#define RESOLVEFUNC(func) \
+ if (!(_kd_##func = _kd_PTR_##func(libs->resolve(#func)))) \
+ qWarning("QSslSocket: cannot resolve "#func);
+
+#define DEFINEFUNC(ret, func, arg, a, err, funcret) \
+ typedef ret (*_kd_PTR_##func)(arg); \
+ _kd_PTR_##func _kd_##func; \
+ ret kd_##func(arg) { \
+ Q_ASSERT(_kd_##func); \
+ funcret _kd_##func(a); \
+ }
+
+#define DEFINEFUNC3(ret, func, arg1, a, arg2, b, arg3, c, err, funcret) \
+ typedef ret (*_kd_PTR_##func)(arg1, arg2, arg3); \
+ _kd_PTR_##func _kd_##func; \
+ ret kd_##func(arg1, arg2, arg3) { \
+ Q_ASSERT(_kd_##func); \
+ funcret _kd_##func(a, b, c); \
+ }
+
+#define DEFINEFUNC4(ret, func, arg1, a, arg2, b, arg3, c, arg4, d, err, funcret) \
+ typedef ret (*_kd_PTR_##func)(arg1, arg2, arg3, arg4); \
+ _kd_PTR_##func _kd_##func; \
+ ret kd_##func(arg1, arg2, arg3, arg4) { \
+ Q_ASSERT(_kd_##func); \
+ funcret _kd_##func(a, b, c, d); \
+ }
+
+#define DEFINEFUNC5(ret, func, arg1, a, arg2, b, arg3, c, arg4, d, arg5, e, err, funcret) \
+ typedef ret (*_kd_PTR_##func)(arg1, arg2, arg3, arg4, arg5); \
+ _kd_PTR_##func _kd_##func; \
+ ret kd_##func(arg1, arg2, arg3, arg4, arg5) { \
+ Q_ASSERT(_kd_##func); \
+ funcret _kd_##func(a, b, c, d, e); \
+ }
+
+#define DEFINEFUNC6(ret, func, arg1, a, arg2, b, arg3, c, arg4, d, arg5, e, arg6, f, err, funcret) \
+ typedef ret (*_kd_PTR_##func)(arg1, arg2, arg3, arg4, arg5, arg6); \
+ _kd_PTR_##func _kd_##func; \
+ ret kd_##func(arg1, arg2, arg3, arg4, arg5, arg6) { \
+ Q_ASSERT(_kd_##func); \
+ funcret _kd_##func(a, b, c, d, e, f); \
+ }
+
+
+# ifdef Q_OS_UNIX
+static bool libGreaterThan(const QString &lhs, const QString &rhs)
+{
+ QStringList lhsparts = lhs.split(QLatin1Char('.'));
+ QStringList rhsparts = rhs.split(QLatin1Char('.'));
+ Q_ASSERT(lhsparts.count() > 1 && rhsparts.count() > 1);
+
+ for (int i = 1; i < rhsparts.count(); ++i) {
+ if (lhsparts.count() <= i)
+ // left hand side is shorter, so it's less than rhs
+ return false;
+
+ bool ok = false;
+ int b = 0;
+ int a = lhsparts.at(i).toInt(&ok);
+ if (ok)
+ b = rhsparts.at(i).toInt(&ok);
+ if (ok) {
+ // both toInt succeeded
+ if (a == b)
+ continue;
+ return a > b;
+ } else {
+ // compare as strings;
+ if (lhsparts.at(i) == rhsparts.at(i))
+ continue;
+ return lhsparts.at(i) > rhsparts.at(i);
+ }
+ }
+
+ // they compared strictly equally so far
+ // lhs cannot be less than rhs
+ return true;
+}
+static QStringList findAllLibSsl()
+{
+ QStringList paths;
+# ifdef Q_OS_DARWIN
+ paths = QString::fromLatin1(qgetenv("DYLD_LIBRARY_PATH"))
+ .split(QLatin1Char(':'), QString::SkipEmptyParts);
+# else
+ paths = QString::fromLatin1(qgetenv("LD_LIBRARY_PATH"))
+ .split(QLatin1Char(':'), QString::SkipEmptyParts);
+# endif
+ paths << QLatin1String("/usr/lib") << QLatin1String("/usr/local/lib");
+
+ QStringList foundSsls;
+ Q_FOREACH (const QString &path, paths) {
+ QDir dir = QDir(path);
+ QStringList entryList = dir.entryList(QStringList() << QLatin1String("libssl.*"), QDir::Files);
+
+ qSort(entryList.begin(), entryList.end(), libGreaterThan);
+ Q_FOREACH (const QString &entry, entryList)
+ foundSsls << path + QLatin1Char('/') + entry;
+ }
+
+ return foundSsls;
+}
+#endif
+
+class KDLibraryLoader : public QObject
+{
+ static QMutex* mutex;
+public:
+ KDLibraryLoader()
+ {
+ const QMutexLocker ml( mutex );
+ if( tempDir.isEmpty() )
+ {
+ QTemporaryFile file( QDir::temp().absoluteFilePath( QString::fromLatin1( "templibsXXXXXX" ) ) );
+ file.open();
+ tempDir = file.fileName();
+ file.close();
+ file.remove();
+ }
+ QDir::temp().mkdir( QFileInfo( tempDir ).fileName() );
+ }
+
+ ~KDLibraryLoader()
+ {
+ const QMutexLocker ml( mutex );
+ for( QVector< QLibrary* >::const_iterator it = loadedLibraries.begin(); it != loadedLibraries.end(); ++it )
+ {
+ QLibrary* const lib = *it;
+ lib->unload();
+ delete lib;
+ }
+
+ for( QStringList::const_iterator it = temporaryFiles.begin(); it != temporaryFiles.end(); ++it )
+ {
+ QFile file( *it );
+ file.setPermissions( file.permissions() | QFile::WriteOwner | QFile::WriteUser );
+ file.remove();
+ }
+
+ QDir::temp().rmdir( QFileInfo( tempDir ).fileName() );
+ }
+
+ bool load( const QString& filename )
+ {
+ const QMutexLocker ml( mutex );
+ // does it work out of the box? great!
+ QLibrary* const lib = new QLibrary;
+ loadedLibraries.push_back( lib );
+ lib->setFileName( filename );
+ if( lib->load() )
+ return true;
+
+ // if this failed, we copy the filename to a different place
+ // it might as well come from a resource
+ const QString realFilename = QFileInfo( QDir( tempDir ), QFileInfo( filename ).fileName() ).absoluteFilePath();
+
+ QFile::copy( filename, realFilename );
+ temporaryFiles.push_back( realFilename );
+
+ lib->setFileName( realFilename );
+ if( lib->load() )
+ return true;
+
+ // if all fails... sorry, we can't perform magic. Seriously!
+ QFile::remove( realFilename );
+ temporaryFiles.pop_back();
+
+ delete lib;
+ loadedLibraries.pop_back();
+
+ return false;
+ }
+
+ template< typename VERSION >
+ bool load( const QString& filename, VERSION version )
+ {
+ const QMutexLocker ml( mutex );
+ // does it work out of the box? great!
+ QLibrary* const lib = new QLibrary;
+ loadedLibraries.push_back( lib );
+ lib->setFileNameAndVersion( filename, version );
+ if( lib->load() )
+ return true;
+
+ // if this failed, we copy the filename to a different place
+ // it might as well come from a resource
+ const QString realFilename = QFileInfo( QDir( tempDir ), QFileInfo( filename ).fileName() ).absoluteFilePath();
+
+ QFile::copy( filename, realFilename );
+ temporaryFiles.push_back( realFilename );
+
+ lib->setFileNameAndVersion( realFilename, version );
+ if( lib->load() )
+ return true;
+
+ // if all fails... sorry, we can't perform magic. Seriously!
+ QFile::remove( realFilename );
+ temporaryFiles.pop_back();
+
+ delete lib;
+ loadedLibraries.pop_back();
+
+ return false;
+
+ }
+
+ void* resolve( const char* symbol )
+ {
+ const QMutexLocker ml( mutex );
+ for( QVector< QLibrary* >::const_iterator it = loadedLibraries.begin(); it != loadedLibraries.end(); ++it )
+ {
+ QLibrary* const lib = *it;
+ void* const ptr = lib->resolve( symbol );
+ if( ptr != 0 )
+ return ptr;
+ }
+ return 0;
+ }
+
+private:
+ QVector< QLibrary* > loadedLibraries;
+ QStringList temporaryFiles;
+ static QString tempDir;
+};
+
+QString KDLibraryLoader::tempDir;
+
+// TODO: this one get leaked
+QMutex* KDLibraryLoader::mutex = new QMutex;
+
+static KDLibraryLoader* loadOpenSsl()
+{
+ KDLibraryLoader* result = new KDLibraryLoader;
+#ifdef Q_OS_WIN
+ if( result->load( QLatin1String( ":/openssllibs/libeay32.dll" ) ) && result->load( QLatin1String( ":/openssllibs/libssl32.dll" ) ) )
+ return result;
+
+ delete result;
+ return 0;
+
+# elif defined(Q_OS_UNIX)
+ // Try to find the libssl library on the system.
+ //
+ // Up until Qt 4.3, this only searched for the "ssl" library at version -1, that
+ // is, libssl.so on most Unix systems. However, the .so file isn't present in
+ // user installations because it's considered a development file.
+ //
+ // The right thing to do is to load the library at the major version we know how
+ // to work with: the SHLIB_VERSION_NUMBER version (macro defined in opensslv.h)
+ //
+ // However, OpenSSL is a well-known case of binary-compatibility breakage. To
+ // avoid such problems, many system integrators and Linux distributions change
+ // the soname of the binary, letting the full version number be the soname. So
+ // we'll find libssl.so.0.9.7, libssl.so.0.9.8, etc. in the system. For that
+ // reason, we will search a few common paths (see findAllLibSsl() above) in hopes
+ // we find one that works.
+ //
+ // It is important, however, to try the canonical name and the unversioned name
+ // without going through the loop. By not specifying a path, we let the system
+ // dlopen(3) function determine it for us. This will include any DT_RUNPATH or
+ // DT_RPATH tags on our library header as well as other system-specific search
+ // paths. See the man page for dlopen(3) on your system for more information.
+
+#ifdef SHLIB_VERSION_NUMBER
+ // first attempt: the canonical name is libssl.so.<SHLIB_VERSION_NUMBER>
+
+ if( result->load( QLatin1String( "ssl" ), QLatin1String( SHLIB_VERSION_NUMBER ) ) &&
+ result->load( QLatin1String( "crypto" ), QLatin1String( SHLIB_VERSION_NUMBER ) ) ) {
+ // libssl.so.<SHLIB_VERSION_NUMBER> and libcrypto.so.<SHLIB_VERSION_NUMBER> found
+ return result;
+ } else {
+ delete result;
+ result = new KDLibraryLoader;
+ }
+#endif
+
+ // second attempt: find the development files libssl.so and libcrypto.so
+ if( result->load( QLatin1String( "ssl" ), -1 ) &&
+ result->load( QLatin1String( "crypto" ), -1 ) ) {
+ // libssl.so.0 and libcrypto.so.0 found
+ return result;
+ } else {
+ delete result;
+ result = new KDLibraryLoader;
+ }
+
+ // third attempt: loop on the most common library paths and find libssl
+ QStringList sslList = findAllLibSsl();
+ Q_FOREACH (const QString &ssl, sslList) {
+ QString crypto = ssl;
+ crypto.replace(QLatin1String("ssl"), QLatin1String("crypto"));
+ if( result->load( ssl, -1 ) &&
+ result->load( crypto ), -1 ) {
+ // libssl.so.0 and libcrypto.so.0 found
+ return result;
+ } else {
+ delete result;
+ result = new KDLibraryLoader;
+ }
+ }
+
+ // failed to load anything
+ delete result;
+ return 0;
+
+# else
+ // not implemented for this platform yet
+ return 0;
+# endif
+}
+
+//END code taken from qsslsocket_openssl_symbols.cpp
+
+class KDUpdaterCrypto::Private
+{
+ public:
+ KDUpdaterCrypto *q;
+
+ QByteArray m_privateKey;
+ QByteArray m_privatePassword;
+ RSA *m_private_key;
+ BIO *m_private_key_bio;
+
+ QByteArray m_publicKey;
+ RSA *m_public_key;
+ BIO *m_public_key_bio;
+
+ KDLibraryLoader* libLoader;
+
+ const PasswordProvider* passwordProvider;
+
+ DEFINEFUNC(int, SSL_library_init, void, DUMMYARG, return -1, return)
+ DEFINEFUNC(int, BIO_free, BIO *a, a, return 0, return)
+ DEFINEFUNC(BIO *, BIO_new, BIO_METHOD *a, a, return 0, return)
+ DEFINEFUNC(BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return 0, return)
+ DEFINEFUNC3(int, BIO_write, BIO *a, a, const void *b, b, int c, c, return -1, return)
+ DEFINEFUNC(RSA*, RSA_new, void, DUMMYARG, return 0, return)
+ DEFINEFUNC(void, RSA_free, RSA *a, a, return, DUMMYARG)
+ DEFINEFUNC(int, RSA_size, RSA *a, a, return 0, return)
+ DEFINEFUNC5(int, RSA_public_encrypt, int flen, flen, unsigned char *from, from, unsigned char *to, to, RSA *rsa, rsa, int padding, padding, return -1, return)
+ DEFINEFUNC5(int, RSA_private_decrypt, int flen, flen, unsigned char *from, from, unsigned char *to, to, RSA *rsa, rsa, int padding, padding, return -1, return)
+ DEFINEFUNC6(int, RSA_sign, int type, type, const unsigned char *m, m, unsigned int m_len, m_len, unsigned char *sigret, sigret, unsigned int *siglen, siglen, RSA *rsa, rsa, return 0, return)
+ DEFINEFUNC6(int, RSA_verify, int type, type, const unsigned char *m, m, unsigned int m_len, m_len, unsigned char *sigret, sigret, unsigned int siglen, siglen, RSA *rsa, rsa, return 0, return)
+ DEFINEFUNC4(RSA*, PEM_read_bio_RSAPrivateKey, BIO *bp, bp, RSA **x, x, pem_password_cb *cb, cb, void *u, u, return 0, return)
+ DEFINEFUNC4(RSA*, PEM_read_bio_RSA_PUBKEY, BIO *bp, bp, RSA **x, x, pem_password_cb *cb, cb, void *u, u, return 0, return)
+
+ explicit Private( KDUpdaterCrypto* q )
+ : q( q ),
+ m_private_key( 0 ),
+ m_private_key_bio( 0 ),
+ m_public_key( 0 ),
+ m_public_key_bio( 0 ),
+ libLoader( 0 ),
+ passwordProvider( 0 )
+ {
+ CLEARFUNC(SSL_library_init)
+ CLEARFUNC(BIO_free)
+ CLEARFUNC(BIO_new)
+ CLEARFUNC(BIO_s_mem)
+ CLEARFUNC(BIO_write)
+ CLEARFUNC(RSA_new)
+ CLEARFUNC(RSA_free)
+ CLEARFUNC(RSA_size)
+ CLEARFUNC(PEM_read_bio_RSAPrivateKey)
+ CLEARFUNC(PEM_read_bio_RSA_PUBKEY)
+ CLEARFUNC(RSA_public_encrypt)
+ CLEARFUNC(RSA_private_decrypt)
+ CLEARFUNC(RSA_sign)
+ CLEARFUNC(RSA_verify)
+ }
+ ~Private()
+ {
+ finish();
+ CLEARFUNC(SSL_library_init)
+ CLEARFUNC(BIO_free)
+ CLEARFUNC(BIO_new)
+ CLEARFUNC(BIO_s_mem)
+ CLEARFUNC(BIO_write)
+ CLEARFUNC(RSA_new)
+ CLEARFUNC(RSA_free)
+ CLEARFUNC(RSA_size)
+ CLEARFUNC(PEM_read_bio_RSAPrivateKey)
+ CLEARFUNC(PEM_read_bio_RSA_PUBKEY)
+ CLEARFUNC(RSA_public_encrypt)
+ CLEARFUNC(RSA_private_decrypt)
+ CLEARFUNC(RSA_sign)
+ CLEARFUNC(RSA_verify)
+ delete libLoader;
+ }
+
+ bool resolveOpenSslSymbols()
+ {
+ volatile bool symbolsResolved = false;
+ volatile bool triedToResolveSymbols = false;
+ //QMutexLocker locker(QMutexPool::globalInstanceGet((void *)&kd_SSL_library_init));
+ if (symbolsResolved)
+ return true;
+ if (triedToResolveSymbols)
+ return false;
+ if( libLoader != 0 )
+ return true;
+ triedToResolveSymbols = true;
+
+ KDLibraryLoader* const libs = loadOpenSsl();
+ if( libs == 0 )
+ // failed to load them
+ return false;
+
+ RESOLVEFUNC(SSL_library_init)
+ RESOLVEFUNC(BIO_free)
+ RESOLVEFUNC(BIO_new)
+ RESOLVEFUNC(BIO_s_mem)
+ RESOLVEFUNC(BIO_write)
+ RESOLVEFUNC(RSA_new)
+ RESOLVEFUNC(RSA_free)
+ RESOLVEFUNC(RSA_size)
+ RESOLVEFUNC(PEM_read_bio_RSAPrivateKey)
+ RESOLVEFUNC(PEM_read_bio_RSA_PUBKEY)
+ RESOLVEFUNC(RSA_public_encrypt)
+ RESOLVEFUNC(RSA_private_decrypt)
+ RESOLVEFUNC(RSA_sign)
+ RESOLVEFUNC(RSA_verify)
+
+ symbolsResolved = true;
+ libLoader = libs;
+ return true;
+ }
+
+ void init()
+ {
+ resolveOpenSslSymbols();
+ const int inited = kd_SSL_library_init();
+ Q_UNUSED( inited );
+ Q_ASSERT(inited);
+ //OpenSSL_add_all_algorithms();
+ }
+
+ void finish()
+ {
+ finishPrivateKey();
+ finishPublicKey();
+ }
+
+ void finishPrivateKey()
+ {
+ if( m_private_key ) {
+ kd_RSA_free(m_private_key);
+ m_private_key = 0;
+ }
+ if( m_private_key_bio ) {
+ kd_BIO_free(m_private_key_bio);
+ m_private_key_bio = 0;
+ }
+ }
+
+ void finishPublicKey()
+ {
+ if( m_public_key ) {
+ kd_RSA_free(m_public_key);
+ m_public_key = 0;
+ }
+ if( m_public_key_bio ) {
+ kd_BIO_free(m_public_key_bio);
+ m_public_key_bio = 0;
+ }
+ }
+
+ static int password_callback(char *buf, int bufsiz, int verify, void *userdata)
+ {
+ Q_UNUSED( verify );
+ //qDebug()<<"KDUpdaterCrypto::password_callback verify="<<verify;
+ KDUpdaterCrypto *crypto = static_cast<KDUpdaterCrypto*>(userdata);
+ const QByteArray password = crypto->d->passwordProvider == 0 ? crypto->privatePassword()
+ : crypto->d->passwordProvider->password();
+ int len = password.length();
+ if (len <= 0)
+ return 0;
+ if (len > bufsiz)
+ len = bufsiz;
+ memcpy(buf, password.constData(), len);
+ return len;
+ }
+
+ bool initPrivateKey()
+ {
+ finishPrivateKey();
+
+ m_private_key_bio = kd_BIO_new(kd_BIO_s_mem());
+ Q_ASSERT(m_private_key_bio);
+
+ Q_ASSERT( ! m_privateKey.isNull());
+ const int priv_bio_size = kd_BIO_write(m_private_key_bio, m_privateKey.constData(), m_privateKey.length());
+ Q_UNUSED( priv_bio_size );
+ Q_ASSERT(priv_bio_size >= 1);
+
+ m_private_key = kd_RSA_new();
+ Q_ASSERT(m_private_key);
+ if( ! kd_PEM_read_bio_RSAPrivateKey(m_private_key_bio, &m_private_key, Private::password_callback, q)) {
+ qWarning() << "PEM_read_bio_RSAPrivateKey failed";
+ kd_RSA_free( m_private_key );
+ m_private_key = 0;
+ return false;
+ }
+ return true;
+ }
+
+ bool initPublicKey()
+ {
+ finishPublicKey();
+
+ m_public_key_bio = kd_BIO_new(kd_BIO_s_mem());
+ Q_ASSERT(m_public_key_bio);
+
+ Q_ASSERT( ! m_publicKey.isNull());
+ const int pub_bio_size = kd_BIO_write(m_public_key_bio, m_publicKey.constData(), m_publicKey.length());
+ Q_UNUSED( pub_bio_size );
+ Q_ASSERT(pub_bio_size >= 1);
+
+ m_public_key = kd_RSA_new();
+ Q_ASSERT(m_public_key);
+ if( ! kd_PEM_read_bio_RSA_PUBKEY(m_public_key_bio, &m_public_key, password_callback, q)) {
+ qWarning() << "PEM_read_bio_RSAPublicKey failed";
+ kd_RSA_free( m_public_key );
+ m_public_key = 0;
+ return false;
+ }
+ return true;
+ }
+};
+
+KDUpdaterCrypto::KDUpdaterCrypto()
+ : d(new Private(this))
+{
+ d->init();
+}
+
+KDUpdaterCrypto::~KDUpdaterCrypto()
+{
+}
+
+QByteArray KDUpdaterCrypto::privateKey() const
+{
+ return d->m_privateKey;
+}
+
+void KDUpdaterCrypto::setPrivateKey(const QByteArray &key)
+{
+ d->m_privateKey = key;
+ d->finish();
+}
+
+QByteArray KDUpdaterCrypto::privatePassword() const
+{
+ return d->m_privatePassword;
+}
+
+void KDUpdaterCrypto::setPrivatePassword(const QByteArray &passwd)
+{
+ d->m_privatePassword = passwd;
+ d->finish();
+}
+
+void KDUpdaterCrypto::setPrivatePasswordProvider( const PasswordProvider* provider )
+{
+ d->passwordProvider = provider;
+}
+
+QByteArray KDUpdaterCrypto::publicKey() const
+{
+ return d->m_publicKey;
+}
+
+void KDUpdaterCrypto::setPublicKey(const QByteArray &key)
+{
+ d->m_publicKey = key;
+ d->finish();
+}
+
+QByteArray KDUpdaterCrypto::encrypt(const QByteArray &plaintext)
+{
+ if( !d->m_public_key && !d->initPublicKey() )
+ return QByteArray();
+
+ Q_ASSERT(d->m_public_key);
+ unsigned char *encrypted = new unsigned char[ d->kd_RSA_size(d->m_public_key) ];
+ const int encryptedlen = d->kd_RSA_public_encrypt(plaintext.length(), (unsigned char *) plaintext.constData(), encrypted, d->m_public_key, RSA_PKCS1_PADDING);
+ const QByteArray ret = encryptedlen>=0 ? QByteArray( (const char*) encrypted, encryptedlen ) : QByteArray();
+ Q_ASSERT(!ret.isNull());
+ delete [] encrypted;
+ return ret;
+}
+
+QByteArray KDUpdaterCrypto::decrypt(const QByteArray &encryptedtext)
+{
+ if( !d->m_private_key && !d->initPrivateKey() )
+ return QByteArray();
+
+ Q_ASSERT(d->m_private_key);
+ unsigned char *decrypted = new unsigned char[ d->kd_RSA_size(d->m_private_key) ];
+ const int decryptedlen = d->kd_RSA_private_decrypt(encryptedtext.length(), (unsigned char *) encryptedtext.constData(), decrypted, d->m_private_key, RSA_PKCS1_PADDING);
+ const QByteArray ret = decryptedlen>=0 ? QByteArray( (const char*) decrypted, decryptedlen ) : QByteArray();
+ delete [] decrypted;
+ return ret;
+}
+
+bool KDUpdaterCrypto::verify(const QByteArray &data, const QByteArray &signature)
+{
+ if( !d->m_public_key && !d->initPublicKey() )
+ return false;
+
+ unsigned char *sigret = (unsigned char*) signature.constData();
+ unsigned int siglen = signature.length();
+ const int verifyresult = d->kd_RSA_verify(NID_sha1, (const unsigned char*) data.constData(), data.length(), sigret, siglen, d->m_public_key);
+ return verifyresult == 1;
+}
+
+static QByteArray hash( QIODevice* dev, QCryptographicHash::Algorithm method )
+{
+ QByteArray buffer;
+ buffer.resize( 8192 );
+ QCryptographicHash h( method );
+ while( !dev->atEnd() )
+ {
+ const int read = dev->read( buffer.data(), buffer.length() );
+ h.addData( buffer.constData(), read );
+ }
+ return h.result();
+}
+
+bool KDUpdaterCrypto::verify( QIODevice* dev, const QByteArray& signature )
+{
+ const bool wasOpen = dev->isOpen();
+ if( !wasOpen && !dev->open( QIODevice::ReadOnly ) )
+ {
+ qWarning() << "KDUpdaterCrypto::verify: could not open the device";
+ return false;
+ }
+
+ const qint64 pos = dev->pos();
+ const bool result = verify( hash( dev, QCryptographicHash::Sha1 ), signature );
+ dev->seek( pos );
+ if( !wasOpen )
+ dev->close();
+ return result;
+
+}
+
+bool KDUpdaterCrypto::verify( const QString& dataPath, const QByteArray& signature )
+{
+ QFile dFile( dataPath );
+ return verify( &dFile, signature );
+}
+
+bool KDUpdaterCrypto::verify( const QString& dataPath, const QString& signaturePath )
+{
+ QFile sFile( signaturePath );
+ if( !sFile.open( QIODevice::ReadOnly ) )
+ {
+ qWarning() << "KDUpdaterCrypto::veryfi: could not open the signature file";
+ return false;
+ }
+
+ return verify( dataPath, sFile.readAll() );
+}
+
+QByteArray KDUpdaterCrypto::sign( QIODevice* dev )
+{
+ const bool wasOpen = dev->isOpen();
+ if( !wasOpen && !dev->open( QIODevice::ReadOnly ) )
+ return QByteArray();
+
+ const qint64 pos = dev->pos();
+ const QByteArray signature = sign( hash( dev, QCryptographicHash::Sha1 ) );
+ dev->seek( pos );
+ if( !wasOpen )
+ dev->close();
+ return signature;
+}
+
+QByteArray KDUpdaterCrypto::sign( const QString& path )
+{
+ QFile file( path );
+ return sign( &file );
+}
+
+QByteArray KDUpdaterCrypto::sign(const QByteArray &data)
+{
+ if( !d->m_private_key && !d->initPrivateKey() )
+ return QByteArray();
+
+ const char *msg = data.constData();
+ unsigned char *sigret = new unsigned char[ d->kd_RSA_size(d->m_private_key) ];
+ unsigned int siglen;
+ const int signresult = d->kd_RSA_sign(NID_sha1, (const unsigned char*) msg, strlen(msg), sigret, &siglen, d->m_private_key);
+ const QByteArray ret = signresult == 1 ? QByteArray( (const char*) sigret, siglen) : QByteArray();
+ delete [] sigret;
+ return ret;
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatercrypto.h b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatercrypto.h
new file mode 100644
index 000000000..15d0011a0
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatercrypto.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef __KDTOOLS_KDUPDATERCRYPTO_H__
+#define __KDTOOLS_KDUPDATERCRYPTO_H__
+
+#include "kdupdater.h"
+
+class QByteArray;
+class QIODevice;
+
+#include <KDToolsCore/pimpl_ptr.h>
+
+/**
+ * Class that provides cryptographic functionality like signing and verifying
+ * or encrypting and decrypting content.
+ */
+class KDTOOLS_UPDATER_EXPORT KDUpdaterCrypto {
+ public:
+ class PasswordProvider
+ {
+ public:
+ virtual ~PasswordProvider() {}
+ virtual QByteArray password() const = 0;
+ };
+
+ KDUpdaterCrypto();
+ virtual ~KDUpdaterCrypto();
+
+ /**
+ * The private key.
+ */
+ QByteArray privateKey() const;
+ void setPrivateKey(const QByteArray &key);
+
+ /**
+ * The password for the private key.
+ */
+ QByteArray privatePassword() const;
+ void setPrivatePassword(const QByteArray &passwd);
+
+ void setPrivatePasswordProvider( const PasswordProvider* provider );
+
+ /**
+ * The public key.
+ */
+ QByteArray publicKey() const;
+ void setPublicKey(const QByteArray &key);
+
+ /**
+ * Encrypt content using the public key.
+ */
+ QByteArray encrypt(const QByteArray &plaintext);
+
+ /**
+ * Decript encrypted content using the private key.
+ */
+ QByteArray decrypt(const QByteArray &encryptedtext);
+
+ /**
+ * Sign content with the private key.
+ */
+ QByteArray sign(const QByteArray &data);
+ QByteArray sign( const QString& path );
+ QByteArray sign( QIODevice* dev );
+
+ /**
+ * Verify signed content with the public key.
+ */
+ bool verify(const QByteArray &data, const QByteArray &signature);
+ bool verify( const QString& dataPath, const QString& signaturePath );
+ bool verify( const QString& dataPath, const QByteArray& signature );
+ bool verify( QIODevice* dev, const QByteArray& signature );
+
+ private:
+ class Private;
+ kdtools::pimpl_ptr< Private > d;
+};
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterfiledownloader.cpp b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterfiledownloader.cpp
new file mode 100644
index 000000000..c23badb5b
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterfiledownloader.cpp
@@ -0,0 +1,1165 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdupdaterfiledownloader_p.h"
+#include "kdupdaterfiledownloaderfactory.h"
+#include "kdupdatersignatureverifier.h"
+#include "kdupdatersignatureverificationresult.h"
+
+#include <KDToolsCore/KDAutoPointer>
+
+#include <QFile>
+#include <QFtp>
+#include <QNetworkAccessManager>
+#include <QNetworkProxyFactory>
+#include <QPointer>
+#include <QUrl>
+#include <QTemporaryFile>
+#include <QFileInfo>
+#include <QCryptographicHash>
+#include <QThreadPool>
+#include <QDebug>
+
+using namespace KDUpdater;
+
+static double calcProgress(qint32 done, qint32 total)
+{
+ return total ? (double(done) / double(total)) : 0 ;
+}
+
+QByteArray KDUpdater::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
+}
+
+QByteArray KDUpdater::calculateHash( const QString& path, QCryptographicHash::Algorithm algo ) {
+ QFile file( path );
+ if ( !file.open( QIODevice::ReadOnly ) )
+ return QByteArray();
+ return calculateHash( &file, algo );
+}
+
+class HashVerificationJob::Private {
+public:
+ Private() : hash( QCryptographicHash::Sha1 ), error( HashVerificationJob::ReadError ), timerId( -1 ) {
+ }
+
+ QPointer<QIODevice> device;
+ QByteArray sha1Sum;
+ QCryptographicHash hash;
+ HashVerificationJob::Error error;
+ int timerId;
+};
+
+HashVerificationJob::HashVerificationJob( QObject* parent ) : QObject( parent ), d( new Private )
+{
+}
+
+HashVerificationJob::~HashVerificationJob()
+{
+}
+
+void HashVerificationJob::setDevice( QIODevice* dev )
+{
+ d->device = dev;
+}
+
+void HashVerificationJob::setSha1Sum( const QByteArray& sum )
+{
+ d->sha1Sum = sum;
+}
+
+int HashVerificationJob::error() const
+{
+ return d->error;
+}
+
+bool HashVerificationJob::hasError() const
+{
+ return d->error != NoError;
+}
+
+void HashVerificationJob::start()
+{
+ Q_ASSERT( d->device );
+ d->timerId = startTimer( 0 );
+}
+
+void HashVerificationJob::emitFinished()
+{
+ emit finished( this );
+ deleteLater();
+}
+
+void HashVerificationJob::timerEvent( QTimerEvent* )
+{
+ Q_ASSERT( d->timerId >= 0 );
+ if ( d->sha1Sum.isEmpty() ) {
+ killTimer( d->timerId );
+ d->timerId = -1;
+ d->error = NoError;
+ d->device->close();
+ emitFinished();
+ return;
+ }
+
+ QByteArray buf;
+ buf.resize( 128 * 1024 );
+ const qint64 read = d->device->read( buf.data(), buf.size() );
+ if ( read > 0 ) {
+ d->hash.addData( buf.constData(), read );
+ return;
+ }
+
+ d->error = d->hash.result() == d->sha1Sum ? NoError : SumsDifferError;
+ killTimer( d->timerId );
+ d->timerId = -1;
+ emitFinished();
+}
+
+////////////////////////////////////////////////////////////////////////////
+// KDUpdater::FileDownloader
+////////////////////////////////////////////////////////////////////////////
+
+/*!
+ \internal
+ \ingroup kdupdater
+ \class KDUpdater::FileDownloader kdupdaterfiledownloader.h
+
+ Base class for file downloaders used in KDUpdater. File downloaders are used by
+ the KDUpdater::Update class to download update files. Each subclass of FileDownloader
+ can download file from a specific category of sources (eg. local, ftp, http etc).
+
+ This is an internal class, not a part of the public API. Currently we have three
+ subclasses of FileDownloader
+ \li LocalFileDownloader - downloads from the local file system
+ \li FtpDownloader - downloads from a FTP site
+ \li HttpDownloader - downloads from a HTTP site
+
+ Usage
+
+ \code
+ KDUpdater::FileDownloader* downloader = new KDUpdater::(some subclass name)
+
+ downloader->setUrl( url );
+ downloader->download();
+
+// wait for downloadCompleted() signal
+
+QString downloadedFile = downloader->downloadedFileName();
+\endcode
+*/
+
+struct KDUpdater::FileDownloader::FileDownloaderData
+{
+ FileDownloaderData() : autoRemove( true ) {
+ }
+
+ QUrl url;
+ QString scheme;
+ QByteArray sha1Sum;
+ QString errorString;
+ bool autoRemove;
+ bool followRedirect;
+};
+
+KDUpdater::FileDownloader::FileDownloader(const QString& scheme, QObject* parent)
+ : QObject(parent),
+ d( new FileDownloaderData )
+{
+ d->scheme = scheme;
+ d->followRedirect = false;
+}
+
+KDUpdater::FileDownloader::~FileDownloader()
+{
+}
+
+void KDUpdater::FileDownloader::setUrl(const QUrl& url)
+{
+ d->url = url;
+}
+
+QUrl KDUpdater::FileDownloader::url() const
+{
+ return d->url;
+}
+
+void KDUpdater::FileDownloader::setSha1Sum( const QByteArray& sum )
+{
+ d->sha1Sum = sum;
+}
+
+QByteArray KDUpdater::FileDownloader::sha1Sum() const
+{
+ return d->sha1Sum;
+}
+
+QString FileDownloader::errorString() const
+{
+ return d->errorString;
+}
+
+void FileDownloader::setDownloadAborted( const QString& error )
+{
+ d->errorString = error;
+ emit downloadAborted( error );
+}
+
+void KDUpdater::FileDownloader::setDownloadCompleted( const QString& path )
+{
+ KDAutoPointer<HashVerificationJob> job( new HashVerificationJob );
+ QFile* file = new QFile( path, job.get() );
+ if ( !file->open( QIODevice::ReadOnly ) ) {
+ emit downloadProgress( 1 );
+ onError();
+ setDownloadAborted( tr("Could not reopen downloaded file %1 for reading: %2").arg( path, file->errorString() ) );
+ return;
+ }
+
+ job->setDevice( file );
+ job->setSha1Sum( d->sha1Sum );
+ connect( job.get(), SIGNAL(finished(KDUpdater::HashVerificationJob*)), this, SLOT(sha1SumVerified(KDUpdater::HashVerificationJob*)) );
+ job.release()->start();
+}
+
+void KDUpdater::FileDownloader::sha1SumVerified( KDUpdater::HashVerificationJob* job )
+{
+ if ( job->hasError() ) {
+ onError();
+ setDownloadAborted( tr("Cryptographic hashes do not match.") );
+ }
+ else {
+ onSuccess();
+ emit downloadCompleted();
+ }
+}
+
+QString KDUpdater::FileDownloader::scheme() const
+{
+ return d->scheme;
+}
+
+void KDUpdater::FileDownloader::setAutoRemoveDownloadedFile(bool val)
+{
+ d->autoRemove = val;
+}
+
+void KDUpdater::FileDownloader::setFollowRedirects( bool val )
+{
+ d->followRedirect = val;
+}
+
+bool KDUpdater::FileDownloader::followRedirects() const
+{
+ return d->followRedirect;
+}
+
+bool KDUpdater::FileDownloader::isAutoRemoveDownloadedFile() const
+{
+ return d->autoRemove;
+}
+
+void KDUpdater::FileDownloader::download() {
+ QMetaObject::invokeMethod( this, "doDownload", Qt::QueuedConnection );
+}
+
+void KDUpdater::FileDownloader::cancelDownload()
+{
+ // Do nothing
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////
+// KDUpdater::FileDownloader
+////////////////////////////////////////////////////////////////////////////
+
+/*
+ Even though QFile::copy() does the task of copying local files from one place
+ to another, I prefer to use the timer and copy one block of data per unit time.
+
+ This is because, it is possible that the user of KDUpdater is simultaneously
+ downloading several files. Sometimes in tandem with other file downloaders.
+ If the local file that is being downloaded takes a long time; then that will
+ hang the other downloads.
+
+ On the otherhand, local downloads need not actually download the file. It can
+ simply pass on the source file as destination file. At this moment however,
+ I think the user of LocalFileDownloader will assume that the downloaded file
+ can be fiddled around with without worrying about whether it would mess up
+ the original source or not.
+*/
+
+struct KDUpdater::LocalFileDownloader::LocalFileDownloaderData
+{
+ LocalFileDownloaderData() : source(0), destination(0),
+ downloaded(false), timerId(-1) { }
+
+ QFile* source;
+ QTemporaryFile* destination;
+ QString destFileName;
+ bool downloaded;
+ int timerId;
+};
+
+KDUpdater::LocalFileDownloader::LocalFileDownloader(QObject* parent)
+ :KDUpdater::FileDownloader(QLatin1String( "file" ), parent),
+ d ( new LocalFileDownloaderData )
+{
+}
+
+KDUpdater::LocalFileDownloader::~LocalFileDownloader()
+{
+ if( this->isAutoRemoveDownloadedFile() && !d->destFileName.isEmpty() )
+ QFile::remove(d->destFileName);
+
+ delete d;
+}
+
+bool KDUpdater::LocalFileDownloader::canDownload() const
+{
+ const QString localFile = url().toLocalFile();
+ QFileInfo fi( localFile );
+ return fi.exists() && fi.isReadable();
+}
+
+bool KDUpdater::LocalFileDownloader::isDownloaded() const
+{
+ return d->downloaded;
+}
+
+void KDUpdater::LocalFileDownloader::doDownload()
+{
+ // Already downloaded
+ if( d->downloaded )
+ return;
+
+ // Already started downloading
+ if( d->timerId >= 0 )
+ return;
+
+ // Open source and destination files
+ QString localFile = this->url().toLocalFile();
+ d->source = new QFile(localFile, this);
+ d->destination = new QTemporaryFile(this);
+
+ if( !d->source->open(QFile::ReadOnly) )
+ {
+ onError();
+ setDownloadAborted(tr("Cannot open source file for reading."));
+ return;
+ }
+
+ if( !d->destination->open() )
+ {
+ onError();
+ setDownloadAborted(tr("Cannot open destination file for writing."));
+ return;
+ }
+
+ // Start a timer and kickoff the copy process
+ d->timerId = startTimer(0); // as fast as possible
+ emit downloadStarted();
+ emit downloadProgress(0);
+}
+
+QString KDUpdater::LocalFileDownloader::downloadedFileName() const
+{
+ return d->destFileName;
+}
+
+KDUpdater::LocalFileDownloader* KDUpdater::LocalFileDownloader::clone( QObject* parent ) const
+{
+ return new LocalFileDownloader( parent );
+}
+
+void KDUpdater::LocalFileDownloader::cancelDownload()
+{
+ if( d->timerId < 0 )
+ return;
+
+ killTimer( d->timerId );
+ d->timerId = -1;
+
+ onError();
+ emit downloadCanceled();
+}
+
+void KDUpdater::LocalFileDownloader::timerEvent(QTimerEvent*)
+{
+ if( !d->source || !d->destination )
+ return;
+
+ const qint64 blockSize = 32768;
+ QByteArray buffer;
+ buffer.resize( blockSize );
+ const qint64 numRead = d->source->read( buffer.data(), buffer.size() );
+ qint64 toWrite = numRead;
+ while ( toWrite > 0 ) {
+ const qint64 numWritten = d->destination->write( buffer.constData() + numRead - toWrite, toWrite );
+ if ( numWritten < 0 ) {
+ killTimer( d->timerId );
+ d->timerId = -1;
+ onError();
+ setDownloadAborted( tr("Writing to %1 failed: %2").arg( d->destination->fileName(), d->destination->errorString() ) );
+ return;
+ }
+ toWrite -= numWritten;
+ }
+
+ if( numRead > 0 ) {
+ emit downloadProgress( calcProgress(d->source->pos(), d->source->size()) );
+ return;
+ }
+
+ d->destination->flush();
+
+ killTimer( d->timerId );
+ d->timerId = -1;
+
+ setDownloadCompleted( d->destination->fileName() );
+}
+
+void LocalFileDownloader::onSuccess()
+{
+ d->downloaded = true;
+ d->destFileName = d->destination->fileName();
+ d->destination->setAutoRemove( false );
+ d->destination->close();
+ delete d->destination;
+ d->destination = 0;
+ delete d->source;
+ d->source = 0;
+}
+
+void LocalFileDownloader::onError()
+{
+ d->downloaded = false;
+ d->destFileName.clear();
+ delete d->destination;
+ d->destination = 0;
+ delete d->source;
+ d->source = 0;
+}
+
+struct KDUpdater::ResourceFileDownloader::ResourceFileDownloaderData
+{
+ ResourceFileDownloaderData()
+ : downloaded( false ),
+ timerId( -1 )
+ {
+ }
+
+ QString destFileName;
+ bool downloaded;
+ int timerId;
+};
+
+KDUpdater::ResourceFileDownloader::ResourceFileDownloader(QObject* parent)
+ :KDUpdater::FileDownloader(QLatin1String( "resource" ), parent),
+ d ( new ResourceFileDownloaderData )
+{
+}
+
+KDUpdater::ResourceFileDownloader::~ResourceFileDownloader()
+{
+ delete d;
+}
+
+bool KDUpdater::ResourceFileDownloader::canDownload() const
+{
+ QUrl url = this->url();
+ url.setScheme( QString::fromLatin1( "file" ) );
+ QString localFile = QString::fromLatin1( ":%1" ).arg( url.toLocalFile() );
+ QFileInfo fi(localFile);
+ return fi.exists() && fi.isReadable();
+}
+
+bool KDUpdater::ResourceFileDownloader::isDownloaded() const
+{
+ return d->downloaded;
+}
+
+void KDUpdater::ResourceFileDownloader::doDownload()
+{
+ // Already downloaded
+ if( d->downloaded )
+ return;
+
+ // Already started downloading
+ if( d->timerId >= 0 )
+ return;
+
+ // Open source and destination files
+ QUrl url = this->url();
+ url.setScheme( QString::fromLatin1( "file" ) );
+ d->destFileName = QString::fromLatin1( ":%1" ).arg( url.toLocalFile() );
+
+ // Start a timer and kickoff the copy process
+ d->timerId = startTimer(0); // as fast as possible
+ emit downloadStarted();
+ emit downloadProgress(0);
+}
+
+QString KDUpdater::ResourceFileDownloader::downloadedFileName() const
+{
+ return d->destFileName;
+}
+
+KDUpdater::ResourceFileDownloader* KDUpdater::ResourceFileDownloader::clone( QObject* parent ) const
+{
+ return new ResourceFileDownloader( parent );
+}
+
+void KDUpdater::ResourceFileDownloader::cancelDownload()
+{
+ if( d->timerId < 0 )
+ return;
+
+ killTimer( d->timerId );
+ d->timerId = -1;
+
+ emit downloadCanceled();
+}
+
+void KDUpdater::ResourceFileDownloader::timerEvent(QTimerEvent*)
+{
+ killTimer( d->timerId );
+ d->timerId = -1;
+ setDownloadCompleted( d->destFileName );
+}
+
+void KDUpdater::ResourceFileDownloader::onSuccess()
+{
+ d->downloaded = true;
+}
+
+void KDUpdater::ResourceFileDownloader::onError()
+{
+ d->downloaded = false;
+}
+
+////////////////////////////////////////////////////////////////////////////
+// KDUpdater::FileDownloader
+////////////////////////////////////////////////////////////////////////////
+
+struct KDUpdater::FtpDownloader::FtpDownloaderData
+{
+ FtpDownloaderData() : ftp(0), destination(0),
+ downloaded(false), ftpCmdId(-1), aborted(false) { }
+
+ QFtp* ftp;
+ QTemporaryFile* destination;
+ QString destFileName;
+ bool downloaded;
+ int ftpCmdId;
+ bool aborted;
+};
+
+KDUpdater::FtpDownloader::FtpDownloader(QObject* parent)
+ : KDUpdater::FileDownloader(QLatin1String( "ftp" ), parent),
+ d ( new FtpDownloaderData )
+{
+}
+
+KDUpdater::FtpDownloader::~FtpDownloader()
+{
+ if( this->isAutoRemoveDownloadedFile() && !d->destFileName.isEmpty() )
+ QFile::remove(d->destFileName);
+
+ delete d;
+}
+
+bool KDUpdater::FtpDownloader::canDownload() const
+{
+ // TODO: Check whether the ftp file actually exists or not.
+ return true;
+}
+
+bool KDUpdater::FtpDownloader::isDownloaded() const
+{
+ return d->downloaded;
+}
+
+void KDUpdater::FtpDownloader::doDownload()
+{
+ if( d->downloaded )
+ return;
+
+ if( d->ftp )
+ return;
+
+ d->ftp = new QFtp(this);
+ connect(d->ftp, SIGNAL(done(bool)), this, SLOT(ftpDone(bool)));
+ connect(d->ftp, SIGNAL(commandStarted(int)), this, SLOT(ftpCmdStarted(int)));
+ connect(d->ftp, SIGNAL(commandFinished(int,bool)), this, SLOT(ftpCmdFinished(int,bool)));
+ connect(d->ftp, SIGNAL(stateChanged(int)), this, SLOT(ftpStateChanged(int)));
+ connect(d->ftp, SIGNAL(dataTransferProgress(qint64,qint64)), this, SLOT(ftpDataTransferProgress(qint64,qint64)));
+
+ d->ftp->connectToHost( url().host(), url().port(21) );
+ d->ftp->login();
+}
+
+QString KDUpdater::FtpDownloader::downloadedFileName() const
+{
+ return d->destFileName;
+}
+
+KDUpdater::FtpDownloader* KDUpdater::FtpDownloader::clone( QObject* parent ) const
+{
+ return new FtpDownloader( parent );
+}
+
+
+void KDUpdater::FtpDownloader::cancelDownload()
+{
+ if( d->ftp )
+ {
+ d->aborted = true;
+ d->ftp->abort();
+ }
+}
+
+void KDUpdater::FtpDownloader::ftpDone(bool error)
+{
+ if( error )
+ {
+ d->ftp->deleteLater();
+ d->ftp = 0;
+ d->ftpCmdId = -1;
+
+ onError();
+
+ if( d->aborted )
+ {
+ d->aborted = false;
+ emit downloadCanceled();
+ }
+ else
+ setDownloadAborted( d->ftp->errorString() );
+ }
+ //PENDING what about the non-error case??
+}
+
+void KDUpdater::FtpDownloader::ftpCmdStarted(int id)
+{
+ if( id != d->ftpCmdId )
+ return;
+
+ emit downloadStarted();
+ emit downloadProgress(0);
+}
+
+void KDUpdater::FtpDownloader::ftpCmdFinished(int id, bool error)
+{
+ if( id != d->ftpCmdId || error ) // PENDING why error -> return??
+ return;
+
+ disconnect(d->ftp, 0, this, 0);
+ d->ftp->deleteLater();
+ d->ftp = 0;
+ d->ftpCmdId = -1;
+ d->destination->flush();
+
+ setDownloadCompleted( d->destination->fileName() );
+}
+
+void FtpDownloader::onSuccess()
+{
+ d->downloaded = true;
+ d->destFileName = d->destination->fileName();
+ d->destination->setAutoRemove( false );
+ delete d->destination;
+ d->destination = 0;
+
+}
+
+void FtpDownloader::onError()
+{
+ d->downloaded = false;
+ d->destFileName.clear();
+ delete d->destination;
+ d->destination = 0;
+
+}
+
+void KDUpdater::FtpDownloader::ftpStateChanged(int state)
+{
+ switch(state)
+ {
+ case QFtp::Connected:
+ // begin the download
+ d->destination = new QTemporaryFile(this);
+ d->destination->open(); //PENDING handle error
+ d->ftpCmdId = d->ftp->get( url().path(), d->destination );
+ break;
+ case QFtp::Unconnected:
+ // download was unconditionally aborted
+ disconnect(d->ftp, 0, this, 0);
+ d->ftp->deleteLater();
+ d->ftp = 0;
+ d->ftpCmdId = -1;
+ onError();
+ setDownloadAborted(tr("Download was aborted due to network errors."));
+ break;
+ }
+}
+
+void KDUpdater::FtpDownloader::ftpDataTransferProgress(qint64 done, qint64 total)
+{
+ emit downloadProgress( calcProgress(done, total) );
+}
+
+////////////////////////////////////////////////////////////////////////////
+// KDUpdater::FileDownloader
+////////////////////////////////////////////////////////////////////////////
+
+struct KDUpdater::HttpDownloader::HttpDownloaderData
+{
+ explicit HttpDownloaderData( HttpDownloader* qq ) : q( qq ), http(0), destination(0), downloaded(false),
+ aborted(false), retrying(false) { }
+
+ HttpDownloader* const q;
+ QNetworkAccessManager manager;
+ QNetworkReply* http;
+ QTemporaryFile* destination;
+ QString destFileName;
+ bool downloaded;
+ bool aborted;
+ bool retrying;
+
+ void shutDown() {
+ disconnect( http, SIGNAL( finished() ), q, SLOT( httpReqFinished() ) );
+ http->deleteLater();
+ http = 0;
+ destination->close();
+ destination->deleteLater();
+ destination = 0;
+
+ }
+};
+
+KDUpdater::HttpDownloader::HttpDownloader(QObject* parent)
+ : KDUpdater::FileDownloader(QLatin1String( "http" ), parent),
+ d ( new HttpDownloaderData( this ) )
+{
+}
+
+KDUpdater::HttpDownloader::~HttpDownloader()
+{
+ if( this->isAutoRemoveDownloadedFile() && !d->destFileName.isEmpty() )
+ QFile::remove(d->destFileName);
+ delete d;
+}
+
+bool KDUpdater::HttpDownloader::canDownload() const
+{
+ // TODO: Check whether the ftp file actually exists or not.
+ return true;
+}
+
+bool KDUpdater::HttpDownloader::isDownloaded() const
+{
+ return d->downloaded;
+}
+
+void KDUpdater::HttpDownloader::doDownload()
+{
+ if( d->downloaded )
+ return;
+
+ if( d->http )
+ return;
+
+ d->http = d->manager.get( QNetworkRequest( url() ) );
+
+ connect( d->http, SIGNAL( readyRead() ), this, SLOT( httpReadyRead() ) );
+ connect( d->http, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( httpReadProgress( qint64, qint64) ) );
+ connect( d->http, SIGNAL( finished() ), this, SLOT( httpReqFinished() ) );
+ connect( d->http, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( httpError( QNetworkReply::NetworkError ) ) );
+
+ /*
+ // In a future update, authentication should also be supported.
+
+ connect(d->http, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
+ this, SLOT(httpProxyAuth(QNetworkProxy,QAuthenticator*)));
+ connect(d->http, SIGNAL(authenticationRequired(QString,QAuthenticator*)),
+ this, SLOT(httpAuth(QString,QAuthenticator*)));
+ */
+
+ // Begin the download
+ d->destination = new QTemporaryFile(this);
+ if ( !d->destination->open() ) {
+ const QString err = d->destination->errorString();
+ d->shutDown();
+ setDownloadAborted( tr("Cannot download %1: Could not create temporary file: %2").arg( url().toString(), err ) );
+ return;
+ }
+}
+
+QString KDUpdater::HttpDownloader::downloadedFileName() const
+{
+ return d->destFileName;
+}
+
+KDUpdater::HttpDownloader* KDUpdater::HttpDownloader::clone( QObject* parent ) const
+{
+ return new HttpDownloader( parent );
+}
+
+void KDUpdater::HttpDownloader::httpReadyRead()
+{
+ static QByteArray buffer( 16384, '\0' );
+ while( d->http->bytesAvailable() )
+ {
+ const qint64 read = d->http->read( buffer.data(), buffer.size() );
+ qint64 written = 0;
+ while( written < read ) {
+ const qint64 numWritten = d->destination->write( buffer.data() + written, read - written );
+ if ( numWritten < 0 ) {
+ const QString err = d->destination->errorString();
+ d->shutDown();
+ setDownloadAborted( tr("Cannot download %1: Writing to temporary file failed: %2").arg( url().toString(), err ) );
+ return;
+ }
+ written += numWritten;
+ }
+ }
+}
+
+void KDUpdater::HttpDownloader::httpError( QNetworkReply::NetworkError )
+{
+ static bool setProxySettings = false;
+ if( !d->retrying && !setProxySettings )
+ {
+ d->shutDown();
+ d->retrying = true;
+ setProxySettings = true;
+
+ // silently force retry with global proxy settings
+ QNetworkProxyFactory::setUseSystemConfiguration( true );
+
+ doDownload();
+ return;
+ }
+ httpDone( true );
+}
+
+void KDUpdater::HttpDownloader::cancelDownload()
+{
+ d->aborted = true;
+ if( d->http )
+ {
+ d->http->abort();
+ httpDone( true );
+ }
+}
+
+void KDUpdater::HttpDownloader::httpDone( bool error )
+{
+ if( error )
+ {
+ QString err;
+ if( d->http )
+ {
+ err = d->http->errorString();
+ d->http->deleteLater();
+ d->http = 0;
+ onError();
+ }
+
+ if( d->aborted )
+ {
+ d->aborted = false;
+ emit downloadCanceled();
+ }
+ else
+ setDownloadAborted( err );
+ }
+ //PENDING: what about the non-error case??
+}
+
+void KDUpdater::HttpDownloader::onError()
+{
+ d->downloaded = false;
+ d->destFileName.clear();
+ delete d->destination;
+ d->destination = 0;
+}
+
+void KDUpdater::HttpDownloader::onSuccess()
+{
+ d->downloaded = true;
+ d->destFileName = d->destination->fileName();
+ d->destination->setAutoRemove( false );
+ delete d->destination;
+ d->destination = 0;
+}
+
+void KDUpdater::HttpDownloader::httpReqFinished()
+{
+ const QVariant redirect = d->http == 0 ? QVariant() : d->http->attribute( QNetworkRequest::RedirectionTargetAttribute );
+ const QUrl redirectUrl = redirect.toUrl();
+ //if ( redirect.isValid() )
+ // redirectUrl = redirect.toUrl();
+ if ( followRedirects() && redirectUrl.isValid() )
+ {
+ // clean the previous download
+ d->http->deleteLater();
+ d->http = 0;
+ d->destination->close();
+ d->destination->deleteLater();
+ d->destination = 0;
+
+ d->http = d->manager.get( QNetworkRequest( redirectUrl ) );
+
+ connect( d->http, SIGNAL( readyRead() ), this, SLOT( httpReadyRead() ) );
+ connect( d->http, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( httpReadProgress( qint64, qint64) ) );
+ connect( d->http, SIGNAL( finished() ), this, SLOT( httpReqFinished() ) );
+ connect( d->http, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( httpError( QNetworkReply::NetworkError ) ) );
+
+ // Begin the download
+ d->destination = new QTemporaryFile(this);
+ d->destination->open(); //PENDING handle error
+ }
+ else
+ {
+ if( d->http == 0 )
+ return;
+ httpReadyRead();
+ d->destination->flush();
+ setDownloadCompleted( d->destination->fileName() );
+ d->http->deleteLater();
+ d->http = 0;
+ }
+}
+
+void KDUpdater::HttpDownloader::httpReadProgress( qint64 done, qint64 total)
+{
+ emit downloadProgress( calcProgress( done, total ) );
+}
+
+class SignatureVerificationDownloader::Private
+{
+ SignatureVerificationDownloader* const q;
+public:
+ explicit Private( FileDownloader* dl, SignatureVerificationDownloader* qq ) : q( qq ), verifier( 0 ), downloader( dl ), sigDownloader( 0 ), actualDownloadDone( false )
+ {
+ Q_ASSERT( downloader );
+ q->connect( downloader.get(), SIGNAL( downloadProgress( double ) ), q, SIGNAL( downloadProgress( double ) ) );
+ q->connect( downloader.get(), SIGNAL(downloadStarted()), q, SLOT(dataDownloadStarted()) );
+ q->connect( downloader.get(), SIGNAL(downloadCompleted()), q, SLOT(dataDownloadCompleted()) );
+ q->connect( downloader.get(), SIGNAL(downloadCanceled()), q, SLOT(dataDownloadCanceled()) );
+ q->connect( downloader.get(), SIGNAL(downloadAborted(QString)), q, SLOT(dataDownloadAborted(QString)) );
+ }
+
+ ~Private()
+ {
+ delete verifier;
+ }
+
+ const SignatureVerifier* verifier;
+ KDAutoPointer< FileDownloader > downloader;
+ KDAutoPointer< FileDownloader > sigDownloader;
+ QUrl signatureUrl;
+ SignatureVerificationResult result;
+ QString downloadedFileName;
+ bool actualDownloadDone : 1;
+};
+
+SignatureVerificationDownloader::SignatureVerificationDownloader( FileDownloader* downloader, QObject* parent ) : FileDownloader( downloader->scheme(), parent ), d( new Private( downloader, this ) )
+{
+}
+
+SignatureVerificationDownloader::~SignatureVerificationDownloader()
+{
+}
+
+QUrl SignatureVerificationDownloader::signatureUrl() const
+{
+ return d->signatureUrl;
+}
+
+void SignatureVerificationDownloader::setSignatureUrl( const QUrl& url )
+{
+ d->signatureUrl = url;
+}
+
+const SignatureVerifier* SignatureVerificationDownloader::signatureVerifier() const {
+ return d->verifier;
+}
+
+void SignatureVerificationDownloader::setSignatureVerifier( const SignatureVerifier* verifier ) {
+ delete d->verifier;
+ d->verifier = verifier ? verifier->clone() : 0;
+}
+
+SignatureVerificationResult SignatureVerificationDownloader::result() const
+{
+ return d->result;
+}
+
+bool SignatureVerificationDownloader::canDownload() const
+{
+ return d->downloader->canDownload();
+}
+
+bool SignatureVerificationDownloader::isDownloaded() const
+{
+ return d->downloader->isDownloaded();
+}
+
+QString SignatureVerificationDownloader::downloadedFileName() const
+{
+ return d->downloadedFileName;
+}
+
+FileDownloader* SignatureVerificationDownloader::clone( QObject* parent ) const
+{
+ return new SignatureVerificationDownloader( d->downloader->clone(), parent );
+}
+
+void SignatureVerificationDownloader::onError()
+{
+ d->sigDownloader.reset();
+ if ( QFile::exists( d->downloadedFileName ) )
+ QFile::remove( d->downloadedFileName );
+}
+
+void SignatureVerificationDownloader::onSuccess()
+{
+ d->sigDownloader.reset();
+}
+
+void SignatureVerificationDownloader::cancelDownload()
+{
+ if ( !d->actualDownloadDone ) {
+ d->downloader->cancelDownload();
+ return;
+ }
+ if ( d->sigDownloader ) {
+ d->sigDownloader->cancelDownload();
+ }
+}
+
+void SignatureVerificationDownloader::doDownload()
+{
+ Q_ASSERT( d->verifier );
+ Q_ASSERT( d->downloader );
+ d->downloader->setUrl( url() );
+ d->downloader->setSha1Sum( sha1Sum() );
+ d->downloader->download();
+}
+
+void SignatureVerificationDownloader::dataDownloadStarted()
+{
+ emit downloadStarted();
+}
+
+void SignatureVerificationDownloader::dataDownloadAborted( const QString& err )
+{
+ setDownloadAborted( err );
+}
+
+void SignatureVerificationDownloader::dataDownloadCanceled()
+{
+ emit downloadCanceled();
+}
+
+static QUrl suggestSignatureUrl( const QUrl& url ) {
+ return url.toString() + QLatin1String(".sig");
+}
+
+void SignatureVerificationDownloader::dataDownloadCompleted()
+{
+ d->downloadedFileName = d->downloader->downloadedFileName();
+ d->actualDownloadDone = true;
+
+ QUrl url = d->signatureUrl;
+ if ( url.isEmpty() )
+ url = suggestSignatureUrl( d->downloader->url() );
+ d->sigDownloader.reset( FileDownloaderFactory::instance().create( url.scheme(), this ) );
+ if ( !d->sigDownloader ) {
+ setDownloadAborted( tr("Could not download signature: scheme %1 not supported").arg( url.scheme() ) );
+ return;
+ }
+ d->sigDownloader->setUrl( url );
+ connect( d->sigDownloader.get(), SIGNAL(downloadCompleted()), this, SLOT(signatureDownloadCompleted()) );
+ connect( d->sigDownloader.get(), SIGNAL(downloadCanceled()), this, SLOT(signatureDownloadCanceled()) );
+ connect( d->sigDownloader.get(), SIGNAL(downloadAborted(QString)), this, SLOT(signatureDownloadAborted(QString)) );
+ d->sigDownloader->download();
+}
+
+void SignatureVerificationDownloader::signatureDownloadAborted( const QString& err )
+{
+ setDownloadAborted( tr("Downloading signature: %1").arg( err ) );
+}
+
+void SignatureVerificationDownloader::signatureDownloadCanceled()
+{
+ emit downloadCanceled();
+}
+
+void SignatureVerificationDownloader::signatureDownloadCompleted()
+{
+ QFile sigFile( d->sigDownloader->downloadedFileName() );
+ if ( !sigFile.open( QIODevice::ReadOnly ) ) {
+ setDownloadAborted( tr("Could not open signature file: %1").arg( sigFile.errorString() ) );
+ return;
+ }
+
+ const QByteArray signature = sigFile.readAll();
+
+ QFile dataFile( d->downloadedFileName );
+ if ( !dataFile.open( QIODevice::ReadOnly ) ) {
+ setDownloadAborted( tr("Could not open file for verification: %1").arg( dataFile.errorString() ) );
+ return;
+ }
+ const QByteArray dataHash = calculateHash(&dataFile, QCryptographicHash::Sha1);
+
+ //const QString sigPath = d->sigDownloader->downloadedFileName();
+ d->result = d->verifier->verify( dataHash, signature );
+ if( ! d->result.isValid() ) {
+ setDownloadAborted( d->result.errorString() );
+ return;
+ }
+ setDownloadCompleted( d->downloadedFileName );
+
+#if 0
+ SignatureVerificationRunnable* runnable = new SignatureVerificationRunnable;
+ runnable->setSignature( signature );
+ runnable->setData( dataFile.release() );
+ runnable->setVerifier( d->verifier );
+ runnable->addResultListener( this, "verificationResult" );
+ QThreadPool::globalInstance()->start( runnable );
+#endif
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterfiledownloader.h b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterfiledownloader.h
new file mode 100644
index 000000000..754917aa8
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterfiledownloader.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef KD_UPDATER_FILE_DOWNLOADER_H
+#define KD_UPDATER_FILE_DOWNLOADER_H
+
+#include "kdupdater.h"
+#include <KDToolsCore/pimpl_ptr.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QUrl>
+#include <QtCore/QCryptographicHash>
+
+namespace KDUpdater
+{
+ KDTOOLS_UPDATER_EXPORT QByteArray calculateHash( QIODevice* device, QCryptographicHash::Algorithm algo );
+ KDTOOLS_UPDATER_EXPORT QByteArray calculateHash( const QString& path, QCryptographicHash::Algorithm algo );
+
+ class HashVerificationJob;
+
+ class KDTOOLS_UPDATER_EXPORT FileDownloader : public QObject
+ {
+ Q_OBJECT
+ Q_PROPERTY( bool autoRemoveDownloadedFile READ isAutoRemoveDownloadedFile WRITE setAutoRemoveDownloadedFile )
+ Q_PROPERTY( QUrl url READ url WRITE setUrl )
+ Q_PROPERTY( QString scheme READ scheme )
+
+ public:
+ explicit FileDownloader(const QString& scheme, QObject* parent=0);
+ ~FileDownloader();
+
+ void setUrl(const QUrl& url);
+ QUrl url() const;
+
+ void setSha1Sum( const QByteArray& sha1 );
+ QByteArray sha1Sum() const;
+
+ QString errorString() const;
+ QString scheme() const;
+
+ virtual bool canDownload() const = 0;
+ virtual bool isDownloaded() const = 0;
+ virtual QString downloadedFileName() const = 0;
+ virtual FileDownloader* clone( QObject* parent=0 ) const = 0;
+
+ void download();
+
+ void setAutoRemoveDownloadedFile(bool val);
+ bool isAutoRemoveDownloadedFile() const;
+
+ void setFollowRedirects( bool val );
+ bool followRedirects() const;
+
+ public Q_SLOTS:
+ virtual void cancelDownload();
+ void sha1SumVerified( KDUpdater::HashVerificationJob* job );
+
+ protected:
+ virtual void onError() = 0;
+ virtual void onSuccess() = 0;
+
+ Q_SIGNALS:
+ void downloadProgress(double);
+ void downloadStarted();
+ void downloadCanceled();
+
+#ifndef Q_MOC_RUN
+ private:
+#endif
+ void downloadCompleted();
+ void downloadAborted(const QString& errorMessage);
+
+ protected:
+ void setDownloadCompleted( const QString& filepath );
+ void setDownloadAborted( const QString& error );
+
+ private Q_SLOTS:
+ virtual void doDownload() = 0;
+
+ private:
+ struct FileDownloaderData;
+ kdtools::pimpl_ptr<FileDownloaderData> d;
+ };
+}
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterfiledownloader_p.h b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterfiledownloader_p.h
new file mode 100644
index 000000000..516bc3c3d
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterfiledownloader_p.h
@@ -0,0 +1,243 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef KD_UPDATER_FILE_DOWNLOADER_P_H
+#define KD_UPDATER_FILE_DOWNLOADER_P_H
+
+#include "kdupdaterfiledownloader.h"
+#include <KDToolsCore/pimpl_ptr.h>
+
+#include <QtCore/QCryptographicHash>
+#include <QtNetwork/QNetworkReply>
+
+class QIODevice;
+
+// these classes are not a part of the public API
+
+namespace KDUpdater
+{
+
+ //TODO make it a KDJob once merged
+ class HashVerificationJob : public QObject
+ {
+ Q_OBJECT
+ public:
+ enum Error {
+ NoError=0,
+ ReadError=128,
+ SumsDifferError
+ };
+
+ explicit HashVerificationJob( QObject* parent=0 );
+ ~HashVerificationJob();
+
+ void setDevice( QIODevice* dev );
+ void setSha1Sum( const QByteArray& data );
+
+ bool hasError() const;
+ int error() const;
+
+ void start();
+
+ Q_SIGNALS:
+ void finished( KDUpdater::HashVerificationJob* );
+
+ private:
+ void emitFinished();
+ /* reimp */ void timerEvent( QTimerEvent* te );
+
+ private:
+ class Private;
+ kdtools::pimpl_ptr<Private> d;
+ };
+
+ class LocalFileDownloader : public FileDownloader
+ {
+ Q_OBJECT
+
+ public:
+ explicit LocalFileDownloader(QObject* parent=0);
+ ~LocalFileDownloader();
+
+ bool canDownload() const;
+ bool isDownloaded() const;
+ QString downloadedFileName() const;
+ /* reimp */ LocalFileDownloader* clone( QObject* parent=0 ) const;
+
+ public Q_SLOTS:
+ void cancelDownload();
+
+ protected:
+ void timerEvent(QTimerEvent* te);
+ /* reimp */ void onError();
+ /* reimp */ void onSuccess();
+
+ private Q_SLOTS:
+ /* reimp */ void doDownload();
+
+ private:
+ struct LocalFileDownloaderData;
+ LocalFileDownloaderData* d;
+ };
+
+ class ResourceFileDownloader : public FileDownloader
+ {
+ Q_OBJECT
+
+ public:
+ explicit ResourceFileDownloader(QObject* parent=0);
+ ~ResourceFileDownloader();
+
+ bool canDownload() const;
+ bool isDownloaded() const;
+ QString downloadedFileName() const;
+ /* reimp */ ResourceFileDownloader* clone( QObject* parent=0 ) const;
+
+ public Q_SLOTS:
+ void cancelDownload();
+
+ protected:
+ void timerEvent(QTimerEvent* te);
+ /* reimp */ void onError();
+ /* reimp */ void onSuccess();
+
+ private Q_SLOTS:
+ /* reimp */ void doDownload();
+
+ private:
+ struct ResourceFileDownloaderData;
+ ResourceFileDownloaderData* d;
+ };
+
+ class FtpDownloader : public FileDownloader
+ {
+ Q_OBJECT
+
+ public:
+ explicit FtpDownloader(QObject* parent=0);
+ ~FtpDownloader();
+
+ bool canDownload() const;
+ bool isDownloaded() const;
+ QString downloadedFileName() const;
+ /* reimp */ FtpDownloader* clone( QObject* parent=0 ) const;
+
+ public Q_SLOTS:
+ void cancelDownload();
+
+ protected:
+ /* reimp */ void onError();
+ /* reimp */ void onSuccess();
+
+ private Q_SLOTS:
+ /* reimp */ void doDownload();
+ void ftpDone(bool error);
+ void ftpCmdStarted(int id);
+ void ftpCmdFinished(int id, bool error);
+ void ftpStateChanged(int state);
+ void ftpDataTransferProgress(qint64 done, qint64 total);
+
+ private:
+ struct FtpDownloaderData;
+ FtpDownloaderData* d;
+ };
+
+ class HttpDownloader : public FileDownloader
+ {
+ Q_OBJECT
+
+ public:
+ explicit HttpDownloader(QObject* parent=0);
+ ~HttpDownloader();
+
+ bool canDownload() const;
+ bool isDownloaded() const;
+ QString downloadedFileName() const;
+ /* reimp */ HttpDownloader* clone( QObject* parent=0 ) const;
+
+ public Q_SLOTS:
+ void cancelDownload();
+
+ protected:
+ /* reimp */ void onError();
+ /* reimp */ void onSuccess();
+
+ private Q_SLOTS:
+ /* reimp */ void doDownload();
+ void httpReadyRead();
+ void httpReadProgress( qint64 done, qint64 total );
+ void httpError( QNetworkReply::NetworkError );
+ void httpDone( bool error );
+ void httpReqFinished();
+
+ private:
+ struct HttpDownloaderData;
+ HttpDownloaderData* d;
+ };
+
+ class SignatureVerificationResult;
+ class SignatureVerifier;
+
+ class SignatureVerificationDownloader : public FileDownloader
+ {
+ Q_OBJECT
+ public:
+ explicit SignatureVerificationDownloader( FileDownloader* downloader, QObject* parent=0 );
+ ~SignatureVerificationDownloader();
+
+ QUrl signatureUrl() const;
+ void setSignatureUrl( const QUrl& url );
+
+ const SignatureVerifier* signatureVerifier() const;
+ void setSignatureVerifier( const SignatureVerifier* verifier );
+
+ SignatureVerificationResult result() const;
+
+ /* reimp */ bool canDownload() const;
+ /* reimp */ bool isDownloaded() const;
+ /* reimp */ QString downloadedFileName() const;
+ /* reimp */ FileDownloader* clone( QObject* parent=0 ) const;
+
+ public Q_SLOTS:
+ /* reimp */ void cancelDownload();
+
+ protected:
+ /* reimp */ void onError();
+ /* reimp */ void onSuccess();
+
+ private Q_SLOTS:
+ /* reimp */ void doDownload();
+ void dataDownloadStarted();
+ void dataDownloadCanceled();
+ void dataDownloadCompleted();
+ void dataDownloadAborted(const QString& errorMessage);
+ void signatureDownloadCanceled();
+ void signatureDownloadCompleted();
+ void signatureDownloadAborted(const QString& errorMessage);
+
+ private:
+ class Private;
+ kdtools::pimpl_ptr<Private> d;
+ };
+}
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterfiledownloaderfactory.cpp b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterfiledownloaderfactory.cpp
new file mode 100644
index 000000000..cba271e96
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterfiledownloaderfactory.cpp
@@ -0,0 +1,129 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdupdaterfiledownloaderfactory.h"
+#include "kdupdaterfiledownloader_p.h"
+
+#include <cassert>
+
+/*!
+ \internal
+ \ingroup kdupdater
+ \class KDUpdater::FileDownloaderFactory kdupdaterfiledownloaderfactory.h
+ \brief Factory for \ref KDUpdater::FileDownloader
+
+ This class acts as a factory for \ref KDUpdater::FileDownloader. You can register
+ one or more file downloaders with this factory and query them based on their scheme.
+
+ This class follows the singleton design pattern. Only one instance of this class can
+ be created and its reference can be fetched from the \ref instance() method.
+*/
+
+using namespace KDUpdater;
+
+struct FileDownloaderFactory::FileDownloaderFactoryData
+{
+ bool m_followRedirects;
+};
+
+FileDownloaderFactory& FileDownloaderFactory::instance()
+{
+ static KDUpdater::FileDownloaderFactory theFactory;
+ return theFactory;
+}
+
+/*!
+ Constructor
+*/
+FileDownloaderFactory::FileDownloaderFactory()
+ : d ( new FileDownloaderFactoryData )
+{
+ // Register the default file downloader set
+ registerFileDownloader< LocalFileDownloader >( QLatin1String( "file" ) );
+ registerFileDownloader< FtpDownloader >( QLatin1String( "ftp" ) );
+ registerFileDownloader< HttpDownloader >( QLatin1String( "http" ) );
+ registerFileDownloader< ResourceFileDownloader >( QLatin1String( "resource" ) );
+ d->m_followRedirects = false;
+}
+
+void FileDownloaderFactory::setFollowRedirects( bool val )
+{
+ FileDownloaderFactory::instance().d->m_followRedirects = val;
+}
+
+bool FileDownloaderFactory::followRedirects()
+{
+ return FileDownloaderFactory::instance().d->m_followRedirects;
+}
+
+FileDownloaderFactory::~FileDownloaderFactory()
+{
+}
+
+/*!
+ Returns a new instance to the \ref KDUpdater::FileDownloader based whose scheme is equal to the string
+ passed as parameter to this function.
+ \note Ownership of this object remains to the programmer.
+*/
+FileDownloader* FileDownloaderFactory::create( const QString& scheme, QObject* parent ) const
+{
+ return create( scheme, 0, QUrl(), parent );
+}
+
+FileDownloader* FileDownloaderFactory::create( const QString& scheme, const SignatureVerifier* verifier, const QUrl& signatureUrl, QObject* parent ) const
+{
+ FileDownloader* const downloader = KDGenericFactory< FileDownloader >::create( scheme );
+ if( downloader != 0 ) {
+ downloader->setFollowRedirects( d->m_followRedirects );
+ downloader->setParent( parent );
+ }
+ if( !verifier )
+ return downloader;
+
+ SignatureVerificationDownloader* const svdl = new SignatureVerificationDownloader( downloader, parent );
+ svdl->setSignatureVerifier( verifier );
+ svdl->setSignatureUrl( signatureUrl );
+ return svdl;
+}
+
+/*!
+ KDUpdater::FileDownloaderFactory::registerFileDownlooader
+ Registers a new file downloader with the factory. If there is already a downloader with the same scheme,
+ the downloader is replaced. The ownership of the downloader is transfered to the factory.
+*/
+
+/*!
+ Returns the number of file downloaders in the factory.
+*/
+int FileDownloaderFactory::fileDownloaderCount() const
+{
+ return productCount();
+}
+
+/*!
+ Returns a list of schemes supported by this factory, i.e. for which a
+ FileDownloader was registered.
+*/
+QStringList FileDownloaderFactory::supportedSchemes() const
+{
+ return availableProducts();
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterfiledownloaderfactory.h b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterfiledownloaderfactory.h
new file mode 100644
index 000000000..b4c284640
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterfiledownloaderfactory.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef KD_UPDATER_FILE_DOWNLOADER_FACTORY_H
+#define KD_UPDATER_FILE_DOWNLOADER_FACTORY_H
+
+#include "kdupdater.h"
+#include <KDToolsCore/pimpl_ptr.h>
+#include <KDToolsCore/kdgenericfactory.h>
+
+#include <QtCore/QStringList>
+#include <QtCore/QUrl>
+
+class QObject;
+
+namespace KDUpdater
+{
+ class FileDownloader;
+ class SignatureVerifier;
+
+ class KDTOOLS_UPDATER_EXPORT FileDownloaderFactory : public KDGenericFactory< FileDownloader >
+ {
+ Q_DISABLE_COPY( FileDownloaderFactory )
+ public:
+ static FileDownloaderFactory& instance();
+ ~FileDownloaderFactory();
+
+ template< typename T >
+ void registerFileDownloader( const QString& scheme )
+ {
+ registerProduct< T >( scheme );
+ }
+ QStringList supportedSchemes() const;
+
+ int fileDownloaderCount() const;
+ FileDownloader* create( const QString& scheme, QObject* parent ) const;
+ FileDownloader* create( const QString& scheme, const SignatureVerifier* verifier = 0, const QUrl& signatureUrl = QUrl(), QObject* parent = 0 ) const;
+ static void setFollowRedirects( bool val );
+ static bool followRedirects();
+
+ private:
+ FileDownloaderFactory();
+
+ private:
+ struct FileDownloaderFactoryData;
+ kdtools::pimpl_ptr<FileDownloaderFactoryData> d;
+ };
+}
+
+
+#endif
+
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterpackagesinfo.cpp b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterpackagesinfo.cpp
new file mode 100644
index 000000000..c6ce195ea
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterpackagesinfo.cpp
@@ -0,0 +1,566 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdupdaterpackagesinfo.h"
+#include "kdupdaterapplication.h"
+
+#include <QFileInfo>
+#include <QDomDocument>
+#include <QDomElement>
+#include <QVector>
+
+using namespace KDUpdater;
+
+/*!
+ \ingroup kdupdater
+ \class KDUpdater::PackagesInfo kdupdaterpackagesinfo.h KDUpdaterPackagesInfo
+ \brief Provides access to information about packages installed on the application side.
+
+ This class parses the XML package file specified via the setFileName() method and
+ provides access to the the information defined within the package file through an
+ easy to use API. You can:
+ \li get application name via the \ref applicationName() method
+ \li get application version via the \ref applicationVersion() method
+ \li get information about the number of packages installed and their meta-data via the
+ \ref packageInfoCount() and \ref packageInfo() methods.
+
+ Instances of this class cannot be created. Each instance of \ref KDUpdater::Application
+ has one instance of this class associated with it. You can fetch a pointer to an instance
+ of this class for an application via the \ref KDUpdater::Application::packagesInfo()
+ method.
+*/
+
+/*! \enum UpdatePackagesInfo::Error
+ * Error codes related to retrieving update sources
+ */
+
+/*! \var UpdatePackagesInfo::Error UpdatePackagesInfo::NoError
+ * No error occurred
+ */
+
+/*! \var UpdatePackagesInfo::Error UpdatePackagesInfo::NotYetReadError
+ * The package information was not parsed yet from the XML file
+ */
+
+/*! \var UpdatePackagesInfo::Error UpdatePackagesInfo::CouldNotReadPackageFileError
+ * the specified update source file could not be read (does not exist or not readable)
+ */
+
+/*! \var UpdatePackagesInfo::Error UpdatePackagesInfo::InvalidXmlError
+ * The source file contains invalid XML.
+ */
+
+/*! \var UpdatePackagesInfo::Error UpdatePackagesInfo::InvalidContentError
+ * The source file contains valid XML, but does not match the expected format for package descriptions
+ */
+
+struct PackagesInfo::PackagesInfoData
+{
+ PackagesInfoData( PackagesInfo* qq ) :
+ q( qq ),
+ application(0),
+ error(PackagesInfo::NotYetReadError),
+ compatLevel(-1),
+ modified( false )
+ {}
+ PackagesInfo* q;
+ Application* application;
+ QString errorMessage;
+ PackagesInfo::Error error;
+ QString fileName;
+ QString applicationName;
+ QString applicationVersion;
+ int compatLevel;
+ bool modified;
+
+ QVector<PackageInfo> packageInfoList;
+
+ void addPackageFrom(const QDomElement& packageE);
+ void setInvalidContentError( const QString& detail );
+};
+
+void PackagesInfo::PackagesInfoData::setInvalidContentError(const QString& detail)
+{
+ error = PackagesInfo::InvalidContentError;
+ errorMessage = tr("%1 contains invalid content: %2").arg(fileName, detail);
+}
+
+/*!
+ \internal
+*/
+PackagesInfo::PackagesInfo(Application* application)
+ : QObject(application),
+ d( new PackagesInfoData( this ) )
+{
+ d->application = application;
+}
+
+/*!
+ \internal
+*/
+PackagesInfo::~PackagesInfo()
+{
+ writeToDisk();
+ delete d;
+}
+
+/*!
+ Returns a pointer to the application, whose package information this class provides
+ access to.
+*/
+Application* PackagesInfo::application() const
+{
+ return d->application;
+}
+
+/*!
+ Returns true if the PackagesInfo are valid else false is returned in which case
+ the \a errorString() method can be used to receive a describing error message.
+*/
+bool PackagesInfo::isValid() const
+{
+ return d->error == NoError;
+}
+
+/*!
+ Returns a human-readable error message.
+*/
+QString PackagesInfo::errorString() const
+{
+ return d->errorMessage;
+}
+
+PackagesInfo::Error PackagesInfo::error() const
+{
+ return d->error;
+}
+
+/*!
+ Sets the complete file name of the Packages.xml file. The function also issues a call to
+ \ref refresh() to reload package information from the XML file.
+
+ \sa KDUpdater::Application::setPackagesXMLFileName()
+*/
+void PackagesInfo::setFileName(const QString& fileName)
+{
+ if( d->fileName == fileName )
+ return;
+
+ d->fileName = fileName;
+ refresh();
+}
+
+/*!
+ Returns the name of the Packages.xml file that this class referred to.
+*/
+QString PackagesInfo::fileName() const
+{
+ return d->fileName;
+}
+
+/*!
+ Sets the application name. By default this is the name specified in
+ the ApplicationName XML element of the Packages.xml file.
+*/
+void PackagesInfo::setApplicationName(const QString& name)
+{
+ d->applicationName = name;
+ d->modified = true;
+}
+
+/*!
+ Returns the application name.
+*/
+QString PackagesInfo::applicationName() const
+{
+ return d->applicationName;
+}
+
+/*!
+ Sets the application version. By default this is the version specified
+ in the ApplicationVersion XML element of Packages.xml.
+*/
+void PackagesInfo::setApplicationVersion(const QString& version)
+{
+ d->applicationVersion = version;
+ d->modified = true;
+}
+
+/*!
+ Returns the application version.
+*/
+QString PackagesInfo::applicationVersion() const
+{
+ return d->applicationVersion;
+}
+
+/*!
+ Returns the number of \ref KDUpdater::PackageInfo objects contained in this class.
+*/
+int PackagesInfo::packageInfoCount() const
+{
+ return d->packageInfoList.count();
+}
+
+/*!
+ Returns the package info structure (\ref KDUpdater::PackageInfo) at index. If index is
+ out of range then an empty package info structure is returned.
+*/
+PackageInfo PackagesInfo::packageInfo(int index) const
+{
+ if( index < 0 || index >= d->packageInfoList.count() )
+ return PackageInfo();
+
+ return d->packageInfoList[index];
+}
+
+/*!
+ Returns the compat level of the application.
+*/
+int PackagesInfo::compatLevel() const
+{
+ return d->compatLevel;
+}
+
+/*!
+ This function returns the index of the package whose name is \c pkgName. If no such
+ package was found, this function returns -1.
+*/
+int PackagesInfo::findPackageInfo(const QString& pkgName) const
+{
+ for(int i=0; i<d->packageInfoList.count(); i++)
+ {
+ if( d->packageInfoList[i].name == pkgName )
+ return i;
+ }
+
+ return -1;
+}
+
+/*!
+ Returns all package info structures.
+*/
+QVector<PackageInfo> PackagesInfo::packageInfos() const
+{
+ return d->packageInfoList;
+}
+
+/*!
+ This function re-reads the Packages.xml file and updates itself. Changes to \ref applicationName()
+ and \ref applicationVersion() are lost after this function returns. The function emits a reset()
+ signal after completion.
+*/
+void PackagesInfo::refresh()
+{
+ // First clear internal variables
+ d->applicationName.clear();
+ d->applicationVersion.clear();
+ d->packageInfoList.clear();
+ d->modified = false;
+
+ QFile file( d->fileName );
+
+ // if the file does not exist then we just skip the reading
+ if( !file.exists() )
+ {
+ d->error = NoError;
+ d->errorMessage.clear();
+ emit reset();
+ return;
+ }
+
+ // Open Packages.xml
+ if( !file.open(QFile::ReadOnly) )
+ {
+ d->error = CouldNotReadPackageFileError;
+ d->errorMessage = tr("Could not read \"%1\"").arg(d->fileName);
+ emit reset();
+ return;
+ }
+
+ // Parse the XML document
+ QDomDocument doc;
+ QString parseErrorMessage;
+ int parseErrorLine;
+ int parseErrorColumn;
+ if( !doc.setContent( &file, &parseErrorMessage, &parseErrorLine, &parseErrorColumn ) )
+ {
+ d->error = InvalidXmlError;
+ d->errorMessage = tr("Parse error in %1 at %2, %3: %4")
+ .arg(d->fileName,
+ QString::number(parseErrorLine),
+ QString::number(parseErrorColumn),
+ parseErrorMessage);
+ emit reset();
+ return;
+ }
+ file.close();
+
+ // Now populate information from the XML file.
+ QDomElement rootE = doc.documentElement();
+ if( rootE.tagName() != QLatin1String( "Packages" ) )
+ {
+ d->setInvalidContentError(tr("root element %1 unexpected, should be \"Packages\"").arg(rootE.tagName()));
+ emit reset();
+ return;
+ }
+
+ QDomNodeList childNodes = rootE.childNodes();
+ for(int i=0; i<childNodes.count(); i++)
+ {
+ QDomNode childNode = childNodes.item(i);
+ QDomElement childNodeE = childNode.toElement();
+ if( childNodeE.isNull() )
+ continue;
+
+ if( childNodeE.tagName() == QLatin1String( "ApplicationName" ) )
+ d->applicationName = childNodeE.text();
+ else if( childNodeE.tagName() == QLatin1String( "ApplicationVersion" ) )
+ d->applicationVersion = childNodeE.text();
+ else if( childNodeE.tagName() == QLatin1String( "Package" ) )
+ d->addPackageFrom( childNodeE );
+ else if( childNodeE.tagName() == QLatin1String( "CompatLevel" ) )
+ d->compatLevel = childNodeE.text().toInt();
+ }
+
+ d->error = NoError;
+ d->errorMessage.clear();
+ emit reset();
+}
+
+/*!
+ Sets the application compat level.
+*/
+void PackagesInfo::setCompatLevel(int level)
+{
+ d->compatLevel = level;
+ d->modified = true;
+}
+
+/*!
+ Marks the package with \a name as installed in \a version.
+ */
+bool PackagesInfo::installPackage( const QString& name, const QString& version, const QString& title, const QString& description
+ , const QStringList& dependencies, bool forcedInstallation, bool virtualComp, quint64 uncompressedSize )
+{
+ if( findPackageInfo( name ) != -1 )
+ return updatePackage( name, version, QDate::currentDate() );
+
+ PackageInfo info;
+ info.name = name;
+ info.version = version;
+ info.installDate = QDate::currentDate();
+ info.title = title;
+ info.description = description;
+ info.dependencies = dependencies;
+ info.forcedInstallation = forcedInstallation;
+ info.virtualComp = virtualComp;
+ info.uncompressedSize = uncompressedSize;
+ d->packageInfoList.push_back( info );
+ d->modified = true;
+ return true;
+}
+
+/*!
+ Update the package.
+*/
+bool PackagesInfo::updatePackage(const QString &name,
+ const QString &version,
+ const QDate &date)
+{
+ int index = findPackageInfo(name);
+
+ if (index==-1) return false;
+
+ d->packageInfoList[index].version = version;
+ d->packageInfoList[index].lastUpdateDate = date;
+ d->modified = true;
+ return true;
+}
+
+/*!
+ Remove the package with \a name.
+ */
+bool PackagesInfo::removePackage( const QString& name )
+{
+ const int index = findPackageInfo( name );
+ if( index == -1 )
+ return false;
+
+ d->packageInfoList.remove( index );
+ d->modified = true;
+ return true;
+}
+
+static void addTextChildHelper(QDomNode *node,
+ const QString &tag,
+ const QString &text)
+{
+ QDomElement domElement = node->ownerDocument().createElement(tag);
+ QDomText domText = node->ownerDocument().createTextNode(text);
+
+ domElement.appendChild(domText);
+ node->appendChild(domElement);
+}
+
+void PackagesInfo::writeToDisk()
+{
+ if( d->modified && ( !d->packageInfoList.isEmpty() || QFile::exists( d->fileName ) ) )
+ {
+ QDomDocument doc;
+ QDomElement root = doc.createElement(QLatin1String( "Packages") ) ;
+ doc.appendChild(root);
+
+ addTextChildHelper(&root, QLatin1String( "ApplicationName" ), d->applicationName);
+ addTextChildHelper(&root, QLatin1String( "ApplicationVersion" ), d->applicationVersion);
+ if (d->compatLevel!=-1) {
+ addTextChildHelper(&root, QLatin1String( "CompatLevel" ), QString::number(d->compatLevel));
+ }
+
+ Q_FOREACH (const PackageInfo &info, d->packageInfoList) {
+ QDomElement package = doc.createElement( QLatin1String( "Package" ) );
+
+ addTextChildHelper( &package, QLatin1String( "Name" ), info.name );
+ addTextChildHelper( &package, QLatin1String( "Pixmap" ), info.pixmap );
+ addTextChildHelper( &package, QLatin1String( "Title" ), info.title );
+ addTextChildHelper( &package, QLatin1String( "Description" ), info.description );
+ addTextChildHelper( &package, QLatin1String( "Version" ), info.version );
+ addTextChildHelper( &package, QLatin1String( "LastUpdateDate" ), info.lastUpdateDate.toString( Qt::ISODate ) );
+ addTextChildHelper( &package, QLatin1String( "InstallDate" ), info.installDate.toString( Qt::ISODate) );
+ addTextChildHelper( &package, QLatin1String( "Size" ), QString::number( info.uncompressedSize ) );
+ QString assembledDependencies = QLatin1String( "" );
+ Q_FOREACH( const QString & val, info.dependencies ){
+ assembledDependencies += val + QLatin1String( "," );
+ }
+ if ( info.dependencies.count() > 0 )
+ assembledDependencies.chop( 1 );
+ addTextChildHelper( &package, QLatin1String( "Dependencies" ), assembledDependencies );
+ if ( info.forcedInstallation )
+ addTextChildHelper( &package, QLatin1String( "ForcedInstallation" ), QLatin1String( "true" ) );
+ if ( info.virtualComp )
+ addTextChildHelper( &package, QLatin1String( "Virtual" ), QLatin1String( "true" ) );
+
+ root.appendChild(package);
+ }
+
+ // Open Packages.xml
+ QFile file( d->fileName );
+ if( !file.open(QFile::WriteOnly) ) {
+ return;
+ }
+
+ file.write(doc.toByteArray(4));
+ file.close();
+ d->modified = false;
+ }
+}
+
+void PackagesInfo::PackagesInfoData::addPackageFrom(const QDomElement& packageE)
+{
+ if( packageE.isNull() )
+ return;
+
+ QDomNodeList childNodes = packageE.childNodes();
+ if(childNodes.count() == 0)
+ return;
+
+ PackageInfo info;
+ info.forcedInstallation = false;
+ info.virtualComp = false;
+ for(int i=0; i<childNodes.count(); i++)
+ {
+ QDomNode childNode = childNodes.item(i);
+ QDomElement childNodeE = childNode.toElement();
+ if( childNodeE.isNull() )
+ continue;
+
+ if( childNodeE.tagName() == QLatin1String( "Name" ) )
+ info.name = childNodeE.text();
+ else if( childNodeE.tagName() == QLatin1String( "Pixmap" ) )
+ info.pixmap = childNodeE.text();
+ else if( childNodeE.tagName() == QLatin1String( "Title" ) )
+ info.title = childNodeE.text();
+ else if( childNodeE.tagName() == QLatin1String( "Description" ) )
+ info.description = childNodeE.text();
+ else if( childNodeE.tagName() == QLatin1String( "Version" ) )
+ info.version = childNodeE.text();
+ else if( childNodeE.tagName() == QLatin1String( "Virtual" ) )
+ info.virtualComp = childNodeE.text().toLower() == QLatin1String( "true" ) ? true : false;
+ else if( childNodeE.tagName() == QLatin1String( "Size" ) )
+ info.uncompressedSize = childNodeE.text().toULongLong();
+ else if( childNodeE.tagName() == QLatin1String( "Dependencies" ) )
+ info.dependencies = childNodeE.text().split( QLatin1String( "," ) );
+ else if( childNodeE.tagName() == QLatin1String( "ForcedInstallation" ) )
+ info.forcedInstallation = childNodeE.text().toLower() == QLatin1String( "true" ) ? true : false;
+ else if( childNodeE.tagName() == QLatin1String( "LastUpdateDate" ) )
+ info.lastUpdateDate = QDate::fromString(childNodeE.text(), Qt::ISODate);
+ else if( childNodeE.tagName() == QLatin1String( "InstallDate" ) )
+ info.installDate = QDate::fromString(childNodeE.text(), Qt::ISODate);
+ }
+
+ this->packageInfoList.append( info );
+}
+
+/*!
+ \fn void KDUpdater::PackagesInfo::reset()
+
+ This signal is emitted whenever the contents of this class is refreshed, usually from within
+ the \ref refresh() slot.
+*/
+
+/*!
+ \ingroup kdupdater
+ \struct KDUpdater::PackageInfo kdupdaterpackagesinfo.h KDUpdaterPackageInfo
+ \brief Describes a single installed package in the application.
+
+ This structure contains information about a single installed package in the application.
+ The information contained in this structure corresponds to the information described
+ by the Package XML element in Packages.xml
+*/
+
+/*!
+ \var QString KDUpdater::PackageInfo::name
+*/
+
+/*!
+ \var QString KDUpdater::PackageInfo::pixmap
+*/
+
+/*!
+ \var QString KDUpdater::PackageInfo::title
+*/
+
+/*!
+ \var QString KDUpdater::PackageInfo::description
+*/
+
+/*!
+ \var QString KDUpdater::PackageInfo::version
+*/
+
+/*!
+ \var QDate KDUpdater::PackageInfo::lastUpdateDate
+*/
+
+/*!
+ \var QDate KDUpdater::PackageInfo::installDate
+*/
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterpackagesinfo.h b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterpackagesinfo.h
new file mode 100644
index 000000000..8b38dd8d2
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterpackagesinfo.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef KD_UPDATER_PACKAGES_INFO_H
+#define KD_UPDATER_PACKAGES_INFO_H
+
+#include "kdupdater.h"
+#include <QObject>
+#include <QDate>
+#include <QString>
+#include <QStringList>
+#include <QVariant>
+
+namespace KDUpdater
+{
+ class Application;
+ class UpdateInstaller;
+
+ struct KDTOOLS_UPDATER_EXPORT PackageInfo
+ {
+ QString name;
+ QString pixmap;
+ QString title;
+ QString description;
+ QString version;
+ QStringList dependencies;
+ QStringList translations;
+ QDate lastUpdateDate;
+ QDate installDate;
+ bool forcedInstallation;
+ bool virtualComp;
+ quint64 uncompressedSize;
+ };
+
+ class KDTOOLS_UPDATER_EXPORT PackagesInfo : public QObject
+ {
+ Q_OBJECT
+
+ public:
+ ~PackagesInfo();
+
+ enum Error
+ {
+ NoError=0,
+ NotYetReadError,
+ CouldNotReadPackageFileError,
+ InvalidXmlError,
+ InvalidContentError
+ };
+
+ Application* application() const;
+
+ bool isValid() const;
+ QString errorString() const;
+ Error error() const;
+
+ void setFileName(const QString& fileName);
+ QString fileName() const;
+
+ void setApplicationName(const QString& name);
+ QString applicationName() const;
+
+ void setApplicationVersion(const QString& version);
+ QString applicationVersion() const;
+
+ int packageInfoCount() const;
+ PackageInfo packageInfo(int index) const;
+ int findPackageInfo(const QString& pkgName) const;
+ QVector<KDUpdater::PackageInfo> packageInfos() const;
+ void writeToDisk();
+
+ int compatLevel() const;
+ void setCompatLevel(int level);
+
+ bool installPackage( const QString& pkgName, const QString& version, const QString& title = QString(), const QString& description = QString()
+ , const QStringList& dependencies = QStringList(), bool forcedInstallation = false, bool virtualComp = false, quint64 uncompressedSize = 0 );
+ bool updatePackage(const QString &pkgName, const QString &version, const QDate &date );
+ bool removePackage( const QString& pkgName );
+
+ public Q_SLOTS:
+ void refresh();
+
+ Q_SIGNALS:
+ void reset();
+
+ protected:
+ explicit PackagesInfo( Application * application=0 );
+
+ private:
+ friend class Application;
+ friend class UpdateInstaller;
+ struct PackagesInfoData;
+ PackagesInfoData* d;
+ };
+
+}
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterpackagesview.cpp b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterpackagesview.cpp
new file mode 100644
index 000000000..4943c7b72
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterpackagesview.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdupdaterpackagesview.h"
+#include "kdupdaterpackagesinfo.h"
+
+/*!
+ \ingroup kdupdater
+ \class KDUpdater::PackagesView kdupdaterpackagesview.h KDUpdaterPackagesView
+ \brief A widget that can show packages contained in \ref KDUpdater::PackagesInfo
+
+ \ref KDUpdater::PackagesInfo, associated with \ref KDUpdater::Application, contains
+ information about all the packages installed in the application. This widget helps view the packages
+ in a list.
+
+ \image html packagesview.jpg
+
+ To use this widget, just create an instance and pass to \ref setPackageInfo() a pointer to
+ \ref KDUpdater::PackagesInfo whose information you want this widget to show.
+*/
+
+struct KDUpdater::PackagesView::PackagesViewData
+{
+ PackagesViewData( PackagesView* qq ) :
+ q( qq ),
+ packagesInfo(0)
+ {}
+
+ PackagesView* q;
+ PackagesInfo* packagesInfo;
+};
+
+/*!
+ Constructor.
+*/
+KDUpdater::PackagesView::PackagesView(QWidget* parent)
+ : QTreeWidget(parent),
+ d ( new PackagesViewData( this ) )
+{
+
+ setColumnCount(5);
+ setHeaderLabels( QStringList() << tr("Name") << tr("Title")
+ << tr("Description") << tr("Version")
+ << tr("Last Updated") );
+ setRootIsDecorated(false);
+}
+
+/*!
+ Destructor
+*/
+KDUpdater::PackagesView::~PackagesView()
+{
+ delete d;
+}
+
+/*!
+ Sets the package info whose information this widget should show.
+
+ \code
+ KDUpdater::Application application;
+
+ KDUpdater::PackagesView packageView;
+ packageView.setPackageInfo( application.packagesInfo() );
+ packageView.show();
+ \endcode
+
+*/
+void KDUpdater::PackagesView::setPackageInfo(KDUpdater::PackagesInfo* packagesInfo)
+{
+ if( d->packagesInfo == packagesInfo )
+ return;
+
+ if(d->packagesInfo)
+ disconnect(d->packagesInfo, 0, this, 0);
+
+ d->packagesInfo = packagesInfo;
+ if(d->packagesInfo)
+ connect(d->packagesInfo, SIGNAL(reset()), this, SLOT(refresh()));
+
+ refresh();
+}
+
+/*!
+ Returns a pointer to the package info whose information this widget is showing.
+*/
+KDUpdater::PackagesInfo* KDUpdater::PackagesView::packagesInfo() const
+{
+ return d->packagesInfo;
+}
+
+/*!
+ This slot reloads package information from the \ref KDUpdater::PackagesInfo associated
+ with this widget.
+
+ \note By default, this slot is connected to the \ref KDUpdater::PackagesInfo::reset()
+ signal in \ref setPackageInfo()
+*/
+void KDUpdater::PackagesView::refresh()
+{
+ this->clear();
+ if( !d->packagesInfo )
+ return;
+
+ Q_FOREACH(const KDUpdater::PackageInfo& info, d->packagesInfo->packageInfos())
+ {
+ QTreeWidgetItem* item = new QTreeWidgetItem(this);
+ item->setText(0, info.name);
+ item->setText(1, info.title);
+ item->setText(2, info.description);
+ item->setText(3, info.version);
+ item->setText(4, info.lastUpdateDate.toString());
+ }
+
+ resizeColumnToContents(0);
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterpackagesview.h b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterpackagesview.h
new file mode 100644
index 000000000..8f42b1e19
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterpackagesview.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef KD_UPDATER_PACKAGES_VIEW_H
+#define KD_UPDATER_PACKAGES_VIEW_H
+
+#include "kdupdater.h"
+#include <QTreeWidget>
+
+namespace KDUpdater
+{
+ class PackagesInfo;
+
+ class KDTOOLS_UPDATER_EXPORT PackagesView : public QTreeWidget
+ {
+ Q_OBJECT
+
+ public:
+ explicit PackagesView(QWidget* parent=0);
+ ~PackagesView();
+
+ void setPackageInfo(PackagesInfo* packageInfo);
+ PackagesInfo* packagesInfo() const;
+
+ public Q_SLOTS:
+ void refresh();
+
+ private:
+ struct PackagesViewData;
+ PackagesViewData* d;
+ };
+}
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatersignatureverificationresult.cpp b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatersignatureverificationresult.cpp
new file mode 100644
index 000000000..0b1f61a57
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatersignatureverificationresult.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdupdatersignatureverificationresult.h"
+
+#include <QSharedData>
+#include <QString>
+
+#include <algorithm>
+
+using namespace KDUpdater;
+
+class SignatureVerificationResult::Private : public QSharedData {
+public:
+ Private() : QSharedData(), validity( SignatureVerificationResult::UnknownValidity ) {
+ }
+ Private( const Private& other ) : QSharedData( other ), validity( other.validity ), errorString( other.errorString ) {
+ }
+
+ bool operator==( const Private& other ) const {
+ return validity == other.validity && errorString == other.errorString;
+ }
+
+ SignatureVerificationResult::Validity validity;
+ QString errorString;
+};
+
+SignatureVerificationResult::SignatureVerificationResult( Validity validity )
+ : d( new Private )
+{
+ setValidity( validity );
+}
+
+SignatureVerificationResult::SignatureVerificationResult( const SignatureVerificationResult& other ) : d( other.d ) {
+}
+
+SignatureVerificationResult::~SignatureVerificationResult() {
+}
+
+SignatureVerificationResult& SignatureVerificationResult::operator=( const SignatureVerificationResult& other ) {
+ SignatureVerificationResult copy( other );
+ std::swap( d, copy.d );
+ return *this;
+}
+
+bool SignatureVerificationResult::operator==( const SignatureVerificationResult& other ) const {
+ return *d == *other.d;
+}
+
+bool SignatureVerificationResult::isValid() const {
+ return d->validity == ValidSignature;
+}
+
+SignatureVerificationResult::Validity SignatureVerificationResult::validity() const {
+ return d->validity;
+}
+
+void SignatureVerificationResult::setValidity( Validity validity ) {
+ d->validity = validity;
+}
+
+QString SignatureVerificationResult::errorString() const {
+ return d->errorString;
+}
+
+void SignatureVerificationResult::setErrorString( const QString& errorString ) {
+ d->errorString = errorString;
+}
+
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatersignatureverificationresult.h b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatersignatureverificationresult.h
new file mode 100644
index 000000000..5319d35f3
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatersignatureverificationresult.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef KD_UPDATER_SIGNATUREVERIFICATIONRESULT_H
+#define KD_UPDATER_SIGNATUREVERIFICATIONRESULT_H
+
+#include "kdupdater.h"
+
+#include <QtCore/QMetaType>
+#include <QtCore/QSharedDataPointer>
+
+class QString;
+
+namespace KDUpdater {
+ class KDTOOLS_UPDATER_EXPORT SignatureVerificationResult {
+ public:
+ enum Validity {
+ ValidSignature=0,
+ UnknownValidity,
+ InvalidSignature,
+ BadSignature
+ };
+
+ explicit SignatureVerificationResult( Validity validity = UnknownValidity );
+ SignatureVerificationResult( const SignatureVerificationResult& other );
+ ~SignatureVerificationResult();
+
+ SignatureVerificationResult& operator=( const SignatureVerificationResult& other );
+ bool operator==( const SignatureVerificationResult& other ) const;
+
+ bool isValid() const;
+ Validity validity() const;
+ void setValidity( Validity validity );
+
+ QString errorString() const;
+ void setErrorString( const QString& errorString );
+
+ private:
+ class Private;
+ QSharedDataPointer<Private> d;
+ };
+}
+
+Q_DECLARE_METATYPE( KDUpdater::SignatureVerificationResult )
+
+#endif // KD_UPDATER_SIGNATUREVERIFICATIONRESULT_H
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatersignatureverificationrunnable.cpp b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatersignatureverificationrunnable.cpp
new file mode 100644
index 000000000..19c6337e4
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatersignatureverificationrunnable.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdupdatersignatureverificationrunnable.h"
+#include "kdupdatersignatureverifier.h"
+#include "kdupdatersignatureverificationresult.h"
+
+#include <QByteArray>
+#include <QIODevice>
+#include <QMetaObject>
+#include <QObject>
+#include <QPointer>
+#include <QThreadPool>
+#include <QVariant>
+#include <QVector>
+
+#include <cassert>
+
+using namespace KDUpdater;
+
+class Runnable::Private {
+public:
+ QVector<QObject*> receivers;
+ QVector<QByteArray> methods;
+};
+
+Runnable::Runnable() : QRunnable(), d( new Private ) {
+}
+
+Runnable::~Runnable() {
+}
+
+
+void Runnable::addResultListener( QObject* receiver, const char* method ) {
+ d->receivers.push_back( receiver );
+ d->methods.push_back( QByteArray( method ) );
+}
+
+void Runnable::emitResult( const QGenericArgument& arg0,
+ const QGenericArgument& arg1,
+ const QGenericArgument& arg2,
+ const QGenericArgument& arg3,
+ const QGenericArgument& arg4,
+ const QGenericArgument& arg5,
+ const QGenericArgument& arg6,
+ const QGenericArgument& arg7,
+ const QGenericArgument& arg8,
+ const QGenericArgument& arg9 ) {
+ assert( d->receivers.size() == d->methods.size() );
+ for ( int i = 0; i < d->receivers.size(); ++i ) {
+ QMetaObject::invokeMethod( d->receivers[i],
+ d->methods[i].constData(),
+ Qt::QueuedConnection,
+ arg0,
+ arg1,
+ arg2,
+ arg3,
+ arg4,
+ arg5,
+ arg6,
+ arg7,
+ arg8,
+ arg9 );
+ }
+}
+
+class SignatureVerificationRunnable::Private {
+public:
+ Private() : verifier( 0 ) {}
+ const SignatureVerifier* verifier;
+ QPointer<QIODevice> device;
+ QByteArray signature;
+};
+
+SignatureVerificationRunnable::SignatureVerificationRunnable() : Runnable(), d( new Private ) {
+}
+
+SignatureVerificationRunnable::~SignatureVerificationRunnable() {
+}
+
+const SignatureVerifier* SignatureVerificationRunnable::verifier() const {
+ return d->verifier;
+}
+
+void SignatureVerificationRunnable::setVerifier( const SignatureVerifier* verifier ) {
+ delete d->verifier;
+ d->verifier = verifier ? verifier->clone() : 0;
+}
+
+QByteArray SignatureVerificationRunnable::signature() const {
+ return d->signature;
+}
+
+void SignatureVerificationRunnable::setSignature( const QByteArray& sig ) {
+ d->signature = sig;
+}
+
+QIODevice* SignatureVerificationRunnable::data() const {
+ return d->device;
+}
+
+void SignatureVerificationRunnable::setData( QIODevice* device ) {
+ d->device = device;
+}
+
+
+void SignatureVerificationRunnable::run() {
+ QThreadPool::globalInstance()->releaseThread();
+ const SignatureVerificationResult result = d->verifier->verify( d->device->readAll(), d->signature );
+ QThreadPool::globalInstance()->reserveThread();
+ delete d->verifier;
+ delete d->device;
+ emitResult( Q_ARG( KDUpdater::SignatureVerificationResult, result ) );
+}
+
+
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatersignatureverificationrunnable.h b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatersignatureverificationrunnable.h
new file mode 100644
index 000000000..afc201bea
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatersignatureverificationrunnable.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef KDUPDATERSIGNATUREVERIFICATIONJOB_H
+#define KDUPDATERSIGNATUREVERIFICATIONJOB_H
+
+#include <KDToolsCore/pimpl_ptr.h>
+#include <QtCore/QGenericArgument>
+#include <QtCore/QRunnable>
+
+class QByteArray;
+class QIODevice;
+class QObject;
+template <typename T> class QVector;
+
+namespace KDUpdater {
+ class SignatureVerifier;
+ class SignatureVerificationResult;
+
+ class Runnable : public QRunnable {
+ public:
+ Runnable();
+ ~Runnable();
+
+ void addResultListener( QObject* receiver, const char* method );
+
+ protected:
+ void emitResult( const QGenericArgument& arg0=QGenericArgument( 0 ),
+ const QGenericArgument& arg1=QGenericArgument(),
+ const QGenericArgument& arg2=QGenericArgument(),
+ const QGenericArgument& arg3=QGenericArgument(),
+ const QGenericArgument& arg4=QGenericArgument(),
+ const QGenericArgument& arg5=QGenericArgument(),
+ const QGenericArgument& arg6=QGenericArgument(),
+ const QGenericArgument& arg7=QGenericArgument(),
+ const QGenericArgument& arg8=QGenericArgument(),
+ const QGenericArgument& arg9=QGenericArgument() );
+
+ private:
+ class Private;
+ kdtools::pimpl_ptr<Private> d;
+ };
+
+ class SignatureVerificationRunnable : public Runnable {
+ public:
+ explicit SignatureVerificationRunnable();
+ ~SignatureVerificationRunnable();
+
+ const SignatureVerifier* verifier() const;
+ void setVerifier( const SignatureVerifier* verifier );
+
+ QByteArray signature() const;
+ void setSignature( const QByteArray& sig );
+
+ QIODevice* data() const;
+ void setData( QIODevice* device );
+
+ /* reimp */ void run();
+
+ private:
+ class Private;
+ kdtools::pimpl_ptr<Private> d;
+ };
+}
+
+#endif // KDUPDATERSIGNATUREVERIFICATIONJOB_H
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatersignatureverifier.cpp b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatersignatureverifier.cpp
new file mode 100644
index 000000000..28cba7098
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatersignatureverifier.cpp
@@ -0,0 +1,46 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdupdatersignatureverifier.h"
+#include "kdupdatersignatureverificationresult.h"
+
+#include <QFile>
+
+using namespace KDUpdater;
+
+SignatureVerifier::~SignatureVerifier()
+{
+}
+
+SignatureVerificationResult SignatureVerifier::verify( const QString& dataFile, const QString& signatureFile ) const
+{
+ QFile dFile( dataFile );
+ QFile sFile( signatureFile );
+
+ if( !dFile.open( QIODevice::ReadOnly ) )
+ return SignatureVerificationResult();
+
+ if( !sFile.open( QIODevice::ReadOnly ) )
+ return SignatureVerificationResult( SignatureVerificationResult::BadSignature );
+
+ return verify( dFile.readAll(), sFile.readAll() );
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatersignatureverifier.h b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatersignatureverifier.h
new file mode 100644
index 000000000..dfb8cbddb
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatersignatureverifier.h
@@ -0,0 +1,46 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef KD_UPDATER_SIGNATUREVERIFIER_H
+#define KD_UPDATER_SIGNATUREVERIFIER_H
+
+#include "kdupdater.h"
+
+class QByteArray;
+class QIODevice;
+class QString;
+
+namespace KDUpdater {
+
+ class SignatureVerificationResult;
+
+ class KDTOOLS_UPDATER_EXPORT SignatureVerifier {
+ public:
+ virtual ~SignatureVerifier();
+ virtual SignatureVerifier* clone() const = 0;
+ virtual SignatureVerificationResult verify( const QByteArray &data, const QByteArray& signature ) const = 0;
+ virtual SignatureVerificationResult verify( const QString& dataFile, const QString& signatureFile ) const;
+ virtual QString type() const = 0;
+ };
+}
+
+#endif // KD_UPDATER_SIGNATUREVERIFIER_H
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatertask.cpp b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatertask.cpp
new file mode 100644
index 000000000..ee8d5aca8
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatertask.cpp
@@ -0,0 +1,440 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdupdatertask.h"
+
+/*!
+ \ingroup kdupdater
+ \class KDUpdater::Task kdupdatertask.h KDUpdaterTask
+ \brief Base class for all task classes in KDUpdater
+
+ This class is the base class for all task classes in KDUpdater. Task is an activity that
+ occupies certain amount of execution time. It can be started, stopped (or canceled), paused and
+ resumed. Tasks can report progress and error messages which an application can show in any
+ sort of UI. The KDUpdater::Task class provides a common interface for dealing with all kinds of
+ tasks in KDUpdater. The class diagram show in this class documentation will help in pointing out
+ the task classes in KDUpdater.
+
+ User should be carefull of these points:
+ \li Instances of this class cannot be created. Only instance of the subclasses can be created
+ \li Task classes can be started only once.
+*/
+
+struct KDUpdater::Task::TaskData
+{
+ TaskData( Task* qq) :
+ q( qq )
+ {
+ caps = KDUpdater::Task::NoCapability;
+ errorCode = 0;
+ started = false;
+ finished = false;
+ paused = false;
+ stopped = false;
+ progressPc = 0;
+ }
+
+ Task* q;
+ int caps;
+ QString name;
+ int errorCode;
+ QString errorText;
+ bool started;
+ bool finished;
+ bool paused;
+ bool stopped;
+ int progressPc;
+ QString progressText;
+};
+
+/*!
+ \internal
+*/
+KDUpdater::Task::Task(const QString& name, int caps, QObject* parent)
+ : QObject(parent),
+ d( new TaskData( this ) )
+{
+ d->caps = caps;
+ d->name = name;
+};
+
+/*!
+ \internal
+*/
+KDUpdater::Task::~Task()
+{
+ delete d;
+}
+
+/*!
+ Returns the name of the task.
+*/
+QString KDUpdater::Task::name() const
+{
+ return d->name;
+}
+
+/*!
+ Returns the capabilities of the task. It is a combination of one or more
+ Capability flags. Defined as follows
+ \code
+ enum KDUpdater::Task::Capability
+ {
+ NoCapability = 0,
+ Pausable = 1,
+ Stoppable = 2
+ };
+ \endcode
+*/
+int KDUpdater::Task::capabilities() const
+{
+ return d->caps;
+}
+
+/*!
+ Returns the last reported error code.
+*/
+int KDUpdater::Task::error() const
+{
+ return d->errorCode;
+}
+
+/*!
+ Returns the last reported error message text.
+*/
+QString KDUpdater::Task::errorString() const
+{
+ return d->errorText;
+}
+
+/*!
+ Returns whether the task has started and is running or not.
+*/
+bool KDUpdater::Task::isRunning() const
+{
+ return d->started;
+}
+
+/*!
+ Returns whether the task has finished or not.
+
+ \note Stopped (or canceled) tasks are not finished tasks.
+*/
+bool KDUpdater::Task::isFinished() const
+{
+ return d->finished;
+}
+
+/*!
+ Returns whether the task is paused or not.
+*/
+bool KDUpdater::Task::isPaused() const
+{
+ return d->paused;
+}
+
+/*!
+ Returns whether the task is stopped or not.
+
+ \note Finished tasks are not stopped classes.
+*/
+bool KDUpdater::Task::isStopped() const
+{
+ return d->stopped;
+}
+
+/*!
+ Returns the progress in percentage made by this task.
+*/
+int KDUpdater::Task::progressPercent() const
+{
+ return d->progressPc;
+}
+
+/*!
+ Returns a string that describes the progress made by this task as a string.
+*/
+QString KDUpdater::Task::progressText() const
+{
+ return d->progressText;
+}
+
+/*!
+ Starts the task.
+*/
+void KDUpdater::Task::run()
+{
+ if(d->started)
+ {
+ qDebug("Trying to start an already started task");
+ return;
+ }
+
+ if(d->finished || d->stopped)
+ {
+ qDebug("Trying to start a finished or canceled task");
+ return;
+ }
+
+ d->stopped = false;
+ d->finished = false; // for the sake of completeness
+ d->started = true;
+ emit started();
+ reportProgress(0, tr("%1 started").arg(d->name));
+
+ doRun();
+}
+
+/*!
+ Stops the task, provided the task has \ref Stoppable capability.
+
+ \note Once the task is stopped, it cannot be restarted.
+*/
+void KDUpdater::Task::stop()
+{
+ if( !(d->caps & Stoppable) )
+ {
+ const QString errorMsg = tr("'%1' cannot be stopped").arg(d->name);
+ reportError(KDUpdater::ECannotStopTask, errorMsg);
+ return;
+ }
+
+ if(!d->started)
+ {
+ qDebug("Trying to stop an unstarted task");
+ return;
+ }
+
+ if(d->finished || d->stopped)
+ {
+ qDebug("Trying to stop a finished or canceled task");
+ return;
+ }
+
+ d->stopped = doStop();
+ if(!d->stopped)
+ {
+ const QString errorMsg = tr("Cannot stop task '%1'").arg(d->name);
+ reportError(KDUpdater::ECannotStopTask, errorMsg);
+ return;
+ }
+
+ d->started = false; // the task is not running
+ d->finished = false; // the task is not finished, but was canceled half-way through
+
+ emit stopped();
+ deleteLater();
+}
+
+/*!
+ Paused the task, provided the task has \ref Pausable capability.
+*/
+void KDUpdater::Task::pause()
+{
+ if( !(d->caps & Pausable) )
+ {
+ const QString errorMsg = tr("'%1' cannot be paused").arg(d->name);
+ reportError(KDUpdater::ECannotPauseTask, errorMsg);
+ return;
+ }
+
+ if(!d->started)
+ {
+ qDebug("Trying to pause an unstarted task");
+ return;
+ }
+
+ if(d->finished || d->stopped)
+ {
+ qDebug("Trying to pause a finished or canceled task");
+ return;
+ }
+
+ d->paused = doPause();
+ if(!d->paused)
+ {
+ const QString errorMsg = tr("Cannot pause task '%1'").arg(d->name);
+ reportError(KDUpdater::ECannotPauseTask, errorMsg);
+ return;
+ }
+
+ // The task state has to be started, paused but not finished or stopped.
+ // We need not set the flags below, but just in case.
+ // Perhaps we should do Q_ASSERT() ???
+ d->started = true;
+ d->finished = false;
+ d->stopped = false;
+
+ emit paused();
+}
+
+/*!
+ Resumes the task if it was paused.
+*/
+void KDUpdater::Task::resume()
+{
+ if(!d->paused)
+ {
+ qDebug("Trying to resume an unpaused task");
+ return;
+ }
+
+ const bool val = doResume();
+ if(!val)
+ {
+ const QString errorMsg = tr("Cannot resume task '%1'").arg(d->name);
+ reportError(KDUpdater::ECannotResumeTask, errorMsg);
+ return;
+ }
+
+ // The task state should be started, but not paused, finished or stopped.
+ // We need not set the flags below, but just in case.
+ // Perhaps we should do Q_ASSERT() ???
+ d->started = true;
+ d->paused = false;
+ d->finished = false;
+ d->stopped = false;
+
+ emit resumed();
+}
+
+/*!
+ \internal
+*/
+void KDUpdater::Task::reportProgress(int percent, const QString& text)
+{
+ if(d->progressPc == percent)
+ return;
+
+ d->progressPc = percent;
+ d->progressText = text;
+ emit progressValue( d->progressPc );
+ emit progressText( d->progressText );
+}
+
+/*!
+ \internal
+*/
+void KDUpdater::Task::reportError(int errorCode, const QString& errorText)
+{
+ d->errorCode = errorCode;
+ d->errorText = errorText;
+
+ emit error(d->errorCode, d->errorText);
+ deleteLater();
+}
+
+/*!
+ \internal
+*/
+void KDUpdater::Task::reportDone()
+{
+ QString msg = tr("%1 done");
+ reportProgress(100, msg);
+
+ // State should be finished, but not started, paused or stopped.
+ d->finished = true;
+ d->started = false;
+ d->paused = false;
+ d->stopped = false;
+ d->errorCode = 0;
+ d->errorText.clear();
+
+ emit finished();
+ deleteLater();
+}
+
+/*!
+ \fn virtual bool KDUpdater::Task::doStart() = 0;
+*/
+
+/*!
+ \fn virtual bool KDUpdater::Task::doStop() = 0;
+*/
+
+/*!
+ \fn virtual bool KDUpdater::Task::doPause() = 0;
+*/
+
+/*!
+ \fn virtual bool KDUpdater::Task::doResume() = 0;
+*/
+
+/*!
+ \signal void KDUpdater::Task::error(int code, const QString& errorText)
+
+ This signal is emitted to notify an error during the execution of this task.
+ \param code Error code
+ \param errorText A string describing the error.
+
+ Error codes are just integers, there are however built in errors represented
+ by the KDUpdater::Error enumeration
+ \code
+ enum Error
+ {
+ ECannotStartTask,
+ ECannotPauseTask,
+ ECannotResumeTask,
+ ECannotStopTask,
+ EUnknown
+ };
+ \endcode
+*/
+
+/*!
+ \signal void KDUpdater::Task::progress(int percent, const QString& progressText)
+
+ This signal is emitted to nofity progress made by the task.
+
+ \param percent Percentage of progress made
+ \param progressText A string describing the progress made
+*/
+
+/*!
+ \signal void KDUpdater::Task::started()
+
+ This signal is emitted when the task has started.
+*/
+
+/*!
+ \signal void KDUpdater::Task::paused()
+
+ This signal is emitted when the task has paused.
+*/
+
+/*!
+ \signal void KDUpdater::Task::resumed()
+
+ This signal is emitted when the task has resumed.
+*/
+
+/*!
+ \signal void KDUpdater::Task::stopped()
+
+ This signal is emitted when the task has stopped (or canceled).
+*/
+
+/*!
+ \signal void KDUpdater::Task::finished()
+
+ This signal is emitted when the task has finished.
+*/
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatertask.h b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatertask.h
new file mode 100644
index 000000000..84dada516
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdatertask.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef KD_UPDATER_TASK_H
+#define KD_UPDATER_TASK_H
+
+#include "kdupdater.h"
+#include <QObject>
+
+namespace KDUpdater
+{
+ class KDTOOLS_UPDATER_EXPORT Task : public QObject
+ {
+ Q_OBJECT
+
+ public:
+ enum Capability
+ {
+ NoCapability = 0,
+ Pausable = 1,
+ Stoppable = 2
+ };
+
+ virtual ~Task();
+
+ QString name() const;
+ int capabilities() const;
+
+ int error() const;
+ QString errorString() const;
+
+ bool isRunning() const;
+ bool isFinished() const;
+ bool isPaused() const;
+ bool isStopped() const;
+
+ int progressPercent() const;
+ QString progressText() const;
+
+ public Q_SLOTS:
+ void run();
+ void stop();
+ void pause();
+ void resume();
+
+ Q_SIGNALS:
+ void error(int code, const QString& errorText);
+ void progressValue(int percent);
+ void progressText(const QString& progressText);
+ void started();
+ void paused();
+ void resumed();
+ void stopped();
+ void finished();
+
+ protected:
+ explicit Task(const QString& name, int caps=NoCapability, QObject* parent=0);
+ void reportProgress(int percent, const QString& progressText);
+ void reportError(int errorCode, const QString& errorText);
+ void reportDone();
+
+ void reportError(const QString& errorText)
+ {
+ reportError(EUnknown, errorText);
+ }
+
+ protected:
+ // Task interface
+ virtual void doRun() = 0;
+ virtual bool doStop() = 0;
+ virtual bool doPause() = 0;
+ virtual bool doResume() = 0;
+
+ private:
+ struct TaskData;
+ TaskData* d;
+ };
+}
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterufcompresscommon.cpp b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterufcompresscommon.cpp
new file mode 100644
index 000000000..4a93b92c2
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterufcompresscommon.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdupdaterufcompresscommon_p.h"
+
+#include <QCryptographicHash>
+#include <QDataStream>
+
+using namespace KDUpdater;
+
+bool UFHeader::isValid() const
+{
+ return magic == QLatin1String( KD_UPDATER_UF_HEADER_MAGIC ) &&
+ fileList.count() == permList.count() &&
+ fileList.count() == isDirList.count();
+}
+
+void UFHeader::addToHash(QCryptographicHash& hash) const
+{
+ QByteArray data;
+ QDataStream stream( &data, QIODevice::WriteOnly );
+ stream << *this;
+ hash.addData(data);
+}
+
+UFEntry::UFEntry()
+ : permissions( 0 )
+{
+}
+
+bool UFEntry::isValid() const
+{
+ return !fileName.isEmpty();
+}
+
+void UFEntry::addToHash(QCryptographicHash& hash) const
+{
+ QByteArray data;
+ QDataStream stream( &data, QIODevice::WriteOnly );
+ stream.setVersion( QDataStream::Qt_4_2 );
+ stream << *this;
+ hash.addData(data);
+}
+
+namespace KDUpdater
+{
+
+QDataStream& operator<<( QDataStream& stream, const UFHeader& hdr )
+{
+ stream << hdr.magic;
+ stream << hdr.fileList;
+ stream << hdr.permList;
+ stream << hdr.isDirList;
+ return stream;
+}
+
+QDataStream& operator>>( QDataStream& stream, UFHeader& hdr )
+{
+ const QDataStream::Status oldStatus = stream.status();
+ stream >> hdr.magic;
+ if( stream.status() == QDataStream::Ok && hdr.magic != QLatin1String( KD_UPDATER_UF_HEADER_MAGIC ) )
+ stream.setStatus( QDataStream::ReadCorruptData );
+
+ if( stream.status() == QDataStream::Ok )
+ stream >> hdr.fileList;
+
+ if( stream.status() == QDataStream::Ok )
+ stream >> hdr.permList;
+
+ if( stream.status() == QDataStream::Ok )
+ stream >> hdr.isDirList;
+
+ if( stream.status() == QDataStream::Ok && ( hdr.fileList.count() != hdr.permList.count() || hdr.permList.count() != hdr.isDirList.count() ) )
+ stream.setStatus( QDataStream::ReadCorruptData );
+
+ if( stream.status() != QDataStream::Ok )
+ hdr = UFHeader();
+
+ if( oldStatus != QDataStream::Ok )
+ stream.setStatus( oldStatus );
+
+ return stream;
+}
+
+QDataStream& operator<<( QDataStream& stream, const UFEntry& entry )
+{
+ stream << entry.fileName;
+ stream << entry.permissions;
+ stream << entry.fileData;
+ return stream;
+}
+
+QDataStream& operator>>( QDataStream& stream, UFEntry& entry )
+{
+ const QDataStream::Status oldStatus = stream.status();
+ if( stream.status() == QDataStream::Ok )
+ stream >> entry.fileName;
+ if( stream.status() == QDataStream::Ok )
+ stream >> entry.permissions;
+ if( stream.status() == QDataStream::Ok )
+ stream >> entry.fileData;
+
+ if( stream.status() != QDataStream::Ok )
+ entry = UFEntry();
+
+ if( oldStatus != QDataStream::Ok )
+ stream.setStatus( oldStatus );
+
+ return stream;
+}
+
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterufcompresscommon_p.h b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterufcompresscommon_p.h
new file mode 100644
index 000000000..65f6ea5cb
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterufcompresscommon_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef __KDTOOLS_KDUPDATE_UFCOMPRESSCOMMON_P_H__
+#define __KDTOOLS_KDUPDATE_UFCOMPRESSCOMMON_P_H__
+
+#define KD_UPDATER_UF_HEADER_MAGIC "KDVCLZ"
+
+#include <KDToolsCore/kdtoolsglobal.h>
+
+#include <QtCore/QStringList>
+#include <QtCore/QByteArray>
+#include <QtCore/QVector>
+
+class QCryptographicHash;
+class QDataStream;
+
+namespace KDUpdater
+{
+ struct KDTOOLS_UPDATER_EXPORT UFHeader
+ {
+ QString magic;
+ QStringList fileList;
+ QVector<quint64> permList;
+ QList<bool> isDirList;
+
+ bool isValid() const;
+
+ void addToHash( QCryptographicHash& hash ) const;
+ };
+
+ struct KDTOOLS_UPDATER_EXPORT UFEntry
+ {
+ QString fileName;
+ quint64 permissions;
+ QByteArray fileData;
+
+ UFEntry();
+
+ bool isValid() const;
+
+ void addToHash(QCryptographicHash& hash) const;
+ };
+
+ KDTOOLS_UPDATER_EXPORT QDataStream& operator<<( QDataStream& stream, const UFHeader& hdr );
+ KDTOOLS_UPDATER_EXPORT QDataStream& operator>>( QDataStream& stream, UFHeader& hdr );
+
+ KDTOOLS_UPDATER_EXPORT QDataStream& operator<<( QDataStream& stream, const UFEntry& entry );
+ KDTOOLS_UPDATER_EXPORT QDataStream& operator>>( QDataStream& stream, UFEntry& entry );
+}
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterufuncompressor.cpp b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterufuncompressor.cpp
new file mode 100644
index 000000000..f5c36e44f
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterufuncompressor.cpp
@@ -0,0 +1,220 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdupdaterufuncompressor_p.h"
+#include "kdupdaterufcompresscommon_p.h"
+
+#include <QCryptographicHash>
+#include <QDir>
+#include <QFile>
+#include <QFileInfo>
+#include <QFSFileEngine>
+#include <QDebug>
+
+using namespace KDUpdater;
+
+class UFUncompressor::Private
+{
+public:
+ QString ufFileName;
+ QString destination;
+ QString errorMessage;
+
+ void setError(const QString& msg);
+};
+
+void UFUncompressor::Private::setError(const QString& msg)
+{
+ errorMessage = msg;
+}
+
+UFUncompressor::UFUncompressor()
+{
+}
+
+UFUncompressor::~UFUncompressor()
+{
+}
+
+QString UFUncompressor::errorString() const
+{
+ return d->errorMessage;
+}
+
+void UFUncompressor::setFileName(const QString& fileName)
+{
+ d->ufFileName = fileName;
+}
+
+QString UFUncompressor::fileName() const
+{
+ return d->ufFileName;
+}
+
+void UFUncompressor::setDestination(const QString& dest)
+{
+ d->destination = dest;
+}
+
+QString UFUncompressor::destination() const
+{
+ return d->destination;
+}
+
+bool UFUncompressor::uncompress()
+{
+ d->errorMessage.clear();
+
+ // First open the uf file for reading
+ QFile ufFile( d->ufFileName );
+ if( !ufFile.open(QFile::ReadOnly) ) {
+ d->setError(tr("Couldn't open file for reading: %1").arg( ufFile.errorString() ));
+ return false;
+ }
+
+ QDataStream ufDS( &ufFile );
+ ufDS.setVersion( QDataStream::Qt_4_2 );
+ QCryptographicHash hash( QCryptographicHash::Md5 );
+
+ // Now read the header.
+ UFHeader header;
+ ufDS >> header;
+ if( ufDS.status() != QDataStream::Ok || !header.isValid() )
+ {
+ d->setError( tr( "Couldn't read the file header." ) );
+ return false;
+ }
+ header.addToHash(hash);
+
+ // Some basic checks.
+ if( header.magic != QLatin1String( KD_UPDATER_UF_HEADER_MAGIC ) ) {
+ d->setError(tr("Wrong file format (magic number not found)"));
+ return false;
+ }
+
+ // Lets get to the destination directory
+ const QDir dir(d->destination);
+ QFSFileEngine fileEngine;
+
+ // Lets create the required directory structure
+ int numExpectedFiles = 0;
+ for(int i=0; i<header.fileList.count(); i++)
+ {
+ const QString fileName = header.fileList[i];
+ // qDebug("ToUncompress %s", qPrintable(fileName));
+ if( header.isDirList[i] )
+ {
+ if ( !dir.mkpath( fileName ) )
+ {
+ d->setError(tr("Could not create folder: %1/%2").arg( d->destination, fileName ));
+ return false;
+ }
+ fileEngine.setFileName( QString(QLatin1String( "%1/%2" )).arg(d->destination, fileName) );
+ fileEngine.setPermissions( header.permList[i] | QAbstractFileEngine::ExeOwnerPerm );
+ } else {
+ ++numExpectedFiles;
+ }
+ }
+
+ // Lets now create files within these directories
+ int numActualFiles = 0;
+ while( !ufDS.atEnd() && numActualFiles < numExpectedFiles )
+ {
+ UFEntry ufEntry;
+ ufDS >> ufEntry;
+ if( ufDS.status() != QDataStream::Ok || !ufEntry.isValid() )
+ {
+ d->setError( tr( "Could not read information for entry %1." ).arg( numActualFiles ) );
+ return false;
+ }
+ ufEntry.addToHash(hash);
+
+ const QString completeFileName = QString(QLatin1String( "%1/%2" )).arg(d->destination, ufEntry.fileName);
+
+ const QByteArray ba = qUncompress( ufEntry.fileData );
+ // check the size
+ QDataStream stream( ufEntry.fileData );
+ stream.setVersion( QDataStream::Qt_4_2 );
+ qint32 length = 0;
+ stream >> length;
+ if( ba.length() != length ) // uncompress failed
+ {
+ d->setError(tr("Could not uncompress entry %1, corrupt data").arg( ufEntry.fileName ) );
+ return false;
+
+ }
+
+
+ QFile ufeFile( completeFileName );
+ if ( !ufeFile.open( QFile::WriteOnly ) )
+ {
+ d->setError(tr("Could not open file %1 for writing: %2").arg( completeFileName, ufeFile.errorString() ));
+ return false;
+ }
+
+
+ const char* const data = ba.constData();
+ const qint64 total = ba.size();
+ qint64 written = 0;
+
+ while ( written < total )
+ {
+ const qint64 num = ufeFile.write( data+written, total-written );
+ if ( num == -1 )
+ {
+ d->setError( tr("Failed writing uncompressed data to %1: %2").arg( completeFileName, ufeFile.errorString() ) );
+ return false;
+ }
+ written += num;
+ }
+
+ ufeFile.close();
+
+ const QFile::Permissions perm = static_cast< QFile::Permissions >( ufEntry.permissions );
+ ufeFile.setPermissions( perm );
+
+ if ( ufeFile.error() != QFile::NoError )
+ {
+ ufeFile.remove();
+ d->setError( tr("Failed writing uncompressed data to %1: %2").arg( completeFileName, ufeFile.errorString() ) );
+ return false;
+ }
+
+ qDebug("Uncompressed %s", qPrintable(completeFileName));
+ ++numActualFiles;
+ }
+
+ if( numExpectedFiles != numActualFiles ) {
+ d->errorMessage = tr("Corrupt file (wrong number of files)");
+ return false;
+ }
+
+ QByteArray hashdata;
+ ufDS >> hashdata;
+
+ if( hashdata != hash.result() ) {
+ d->errorMessage = tr("Corrupt file (wrong hash)");
+ return false;
+ }
+
+ return true;
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterufuncompressor_p.h b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterufuncompressor_p.h
new file mode 100644
index 000000000..5800887fc
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterufuncompressor_p.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef __KDTOOLS_KDUPDATERUFUNCOMPRESSOR_P_H__
+#define __KDTOOLS_KDUPDATERUFUNCOMPRESSOR_P_H__
+
+#include <KDToolsCore/pimpl_ptr.h>
+
+#include <QtCore/QCoreApplication>
+
+class QString;
+
+namespace KDUpdater
+{
+ class KDTOOLS_UPDATER_EXPORT UFUncompressor
+ {
+ Q_DECLARE_TR_FUNCTIONS(KDUpdater::UFUncompressor)
+
+ public:
+ UFUncompressor();
+ ~UFUncompressor();
+
+ QString errorString() const;
+
+ void setFileName(const QString& fileName);
+ QString fileName() const;
+
+ void setDestination(const QString& dest);
+ QString destination() const;
+
+ bool uncompress();
+
+ private:
+ class Private;
+ kdtools::pimpl_ptr< Private > d;
+ };
+}
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdate.cpp b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdate.cpp
new file mode 100644
index 000000000..a84f3799c
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdate.cpp
@@ -0,0 +1,313 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdupdaterupdate.h"
+#include "kdupdaterapplication.h"
+#include "kdupdaterupdatesourcesinfo.h"
+#include "kdupdaterfiledownloader_p.h"
+#include "kdupdaterfiledownloaderfactory.h"
+#include "kdupdaterupdateoperations.h"
+#include "kdupdaterupdateoperationfactory.h"
+
+#include <QFile>
+
+/*!
+ \ingroup kdupdater
+ \class KDUpdater::Update kdupdaterupdate.h KDUpdaterUpdate
+ \brief Represents a single update
+
+ The KDUpdater::Update class contains information and mechanisms to download one update. It is
+ created by KDUpdater::UpdateFinder and is used by KDUpdater::UpdateInstaller to download the UpdateFile
+ corresponding to the update.
+
+ The class makes use of appropriate network protocols (HTTP, HTTPS, FTP, or Local File Copy) to
+ download the UpdateFile.
+
+ The constructor of the KDUpdater::Update class is made protected, because it can be instantiated only by
+ KDUpdater::UpdateFinder (which is a friend class). The destructor however is public.
+*/
+
+struct KDUpdater::Update::UpdateData
+{
+ UpdateData( Update* qq ) :
+ q( qq ),
+ application( 0 ),
+ compressedSize( 0 ),
+ uncompressedSize( 0 )
+ {}
+
+ Update* q;
+ Application* application;
+ KDUpdater::UpdateSourceInfo sourceInfo;
+ QMap<QString, QVariant> data;
+ QUrl updateUrl;
+ UpdateType type;
+ QList<UpdateOperation*> operations;
+ QByteArray sha1sum;
+
+ quint64 compressedSize;
+ quint64 uncompressedSize;
+
+ KDUpdater::FileDownloader* fileDownloader;
+};
+
+
+/*!
+ \internal
+*/
+KDUpdater::Update::Update(KDUpdater::Application* application, const KDUpdater::UpdateSourceInfo& sourceInfo,
+ UpdateType type, const QUrl& updateUrl, const QMap<QString, QVariant>& data, quint64 compressedSize, quint64 uncompressedSize, const QByteArray& sha1sum )
+ : KDUpdater::Task(QLatin1String( "Update" ), Stoppable, application),
+ d( new UpdateData( this ) )
+{
+ d->application = application;
+ d->sourceInfo = sourceInfo;
+ d->data = data;
+ d->updateUrl = updateUrl;
+ d->type = type;
+
+ d->compressedSize = compressedSize;
+ d->uncompressedSize = uncompressedSize;
+ d->sha1sum = sha1sum;
+
+ const SignatureVerifier* verifier = d->application->signatureVerifier( Application::Packages );
+
+ d->fileDownloader = FileDownloaderFactory::instance().create( updateUrl.scheme(), verifier, QUrl(), this);
+ if(d->fileDownloader)
+ {
+ d->fileDownloader->setUrl(d->updateUrl);
+ d->fileDownloader->setSha1Sum( d->sha1sum );
+ connect(d->fileDownloader, SIGNAL(downloadProgress(double)), this, SLOT(downloadProgress(double)));
+ connect(d->fileDownloader, SIGNAL(downloadCanceled()), this, SIGNAL(stopped()));
+ connect(d->fileDownloader, SIGNAL(downloadCompleted()), this, SIGNAL(finished()));
+ }
+
+ switch( type ) {
+ case NewPackage:
+ case PackageUpdate:
+ {
+ KDUpdater::UpdateOperation* packageOperation = UpdateOperationFactory::instance().create( QLatin1String( "UpdatePackage" ) );
+ QStringList args;
+ args << data.value( QLatin1String( "Name" ) ).toString()
+ << data.value( QLatin1String( "Version" ) ).toString()
+ << data.value( QLatin1String( "ReleaseDate" ) ).toString();
+ packageOperation->setArguments(args);
+ packageOperation->setApplication( application );
+ d->operations.append( packageOperation );
+ break;
+ }
+ case CompatUpdate:
+ {
+ KDUpdater::UpdateOperation* compatOperation = UpdateOperationFactory::instance().create( QLatin1String( "UpdateCompatLevel" ) );
+ QStringList args;
+ args << data.value( QLatin1String( "CompatLevel" ) ).toString();
+ compatOperation->setArguments(args);
+ compatOperation->setApplication( application );
+ d->operations.append( compatOperation );
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+/*!
+ Destructor
+*/
+KDUpdater::Update::~Update()
+{
+ const QString fileName = this->downloadedFileName();
+ if( !fileName.isEmpty() )
+ QFile::remove( fileName );
+ qDeleteAll( d->operations );
+ d->operations.clear();
+ delete d;
+}
+
+/*!
+ Returns the application for which this class is downloading the UpdateFile
+*/
+KDUpdater::Application* KDUpdater::Update::application() const
+{
+ return d->application;
+}
+
+/*!
+ Returns the release date of the update downloaded by this class
+*/
+QDate KDUpdater::Update::releaseDate() const
+{
+ return d->data.value( QLatin1String( "ReleaseDate" ) ).toDate();
+}
+
+/*!
+ Returns data whose name is given in parameter, or an invalid QVariant if the data doesn't exist.
+*/
+QVariant KDUpdater::Update::data( const QString& name ) const
+{
+ if ( d->data.contains( name ) )
+ return d->data.value( name );
+ return QVariant();
+}
+
+/*!
+ Returns the complete URL of the UpdateFile downloaded by this class.
+*/
+QUrl KDUpdater::Update::updateUrl() const
+{
+ return d->updateUrl;
+}
+
+/*!
+ Returns the update source info on which this update was created.
+*/
+KDUpdater::UpdateSourceInfo KDUpdater::Update::sourceInfo() const
+{
+ return d->sourceInfo;
+}
+
+/*!
+ * Returns the type of update
+ */
+KDUpdater::UpdateType KDUpdater::Update::type() const
+{
+ return d->type;
+}
+
+/*!
+ Returns true of the update can be downloaded, false otherwise. The function
+ returns false if the URL scheme is not supported by this class.
+*/
+bool KDUpdater::Update::canDownload() const
+{
+ return d->fileDownloader && d->fileDownloader->canDownload();
+}
+
+/*!
+ Returns true of the update has been downloaded. If this function returns true
+ the you can use the \ref downloadedFileName() method to get the complete name
+ of the downloaded UpdateFile.
+
+ \note: The downloaded UpdateFile will be deleted when this class is destroyed
+*/
+bool KDUpdater::Update::isDownloaded() const
+{
+ return d->fileDownloader && d->fileDownloader->isDownloaded();
+}
+
+/*!
+ Returns the name of the downloaded UpdateFile after the download is complete, ie
+ when \ref isDownloaded() returns true.
+*/
+QString KDUpdater::Update::downloadedFileName() const
+{
+ if(d->fileDownloader)
+ return d->fileDownloader->downloadedFileName();
+
+ return QString();
+}
+
+/*!
+ \internal
+*/
+void KDUpdater::Update::downloadProgress(double value)
+{
+ Q_ASSERT(value <= 1);
+ reportProgress(value * 100, tr("Downloading update..."));
+}
+
+/*!
+ \internal
+*/
+void KDUpdater::Update::downloadCompleted()
+{
+ reportProgress(100, tr("Update downloaded"));
+ reportDone();
+}
+
+/*!
+ \internal
+*/
+void KDUpdater::Update::downloadAborted(const QString& msg)
+{
+ reportError(msg);
+}
+
+/*!
+ \internal
+*/
+void KDUpdater::Update::doRun()
+{
+ if(d->fileDownloader)
+ d->fileDownloader->download();
+}
+
+/*!
+ \internal
+*/
+bool KDUpdater::Update::doStop()
+{
+ if(d->fileDownloader)
+ d->fileDownloader->cancelDownload();
+ return true;
+}
+
+/*!
+ \internal
+*/
+bool KDUpdater::Update::doPause()
+{
+ return false;
+}
+
+/*!
+ \internal
+*/
+bool KDUpdater::Update::doResume()
+{
+ return false;
+}
+
+/*!
+ Returns a list of operations needed by this update. For example, package update needs to change
+ the package version, compat update needs to change the compat level...
+ */
+QList<KDUpdater::UpdateOperation*> KDUpdater::Update::operations() const
+{
+ return d->operations;
+}
+
+/*!
+ * Returns the compressed size of this update's data file.
+ */
+quint64 KDUpdater::Update::compressedSize() const
+{
+ return d->compressedSize;
+}
+
+/*!
+ * Returns the uncompressed size of this update's data file.
+ */
+quint64 KDUpdater::Update::uncompressedSize() const
+{
+ return d->uncompressedSize;
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdate.h b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdate.h
new file mode 100644
index 000000000..8ea4728b9
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdate.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef KD_UPDATER_UPDATE_H
+#define KD_UPDATER_UPDATE_H
+
+#include "kdupdater.h"
+#include "kdupdatertask.h"
+#include <QUrl>
+#include <QDate>
+#include <QMap>
+#include <QVariant>
+#include <QList>
+
+namespace KDUpdater
+{
+ class Application;
+ struct UpdateSourceInfo;
+ class UpdateFinder;
+ class UpdateOperation;
+
+ class KDTOOLS_UPDATER_EXPORT Update : public Task
+ {
+ Q_OBJECT
+
+ public:
+ ~Update();
+
+ Application* application() const;
+
+ UpdateType type() const;
+ QUrl updateUrl() const;
+ QDate releaseDate() const;
+ QVariant data( const QString& name ) const;
+ UpdateSourceInfo sourceInfo() const;
+
+ bool canDownload() const;
+ bool isDownloaded() const;
+ void download() { run(); }
+ QString downloadedFileName() const;
+
+ QList<UpdateOperation*> operations() const;
+
+ quint64 compressedSize() const;
+ quint64 uncompressedSize() const;
+
+ private Q_SLOTS:
+ void downloadProgress(double);
+ void downloadAborted(const QString& msg);
+ void downloadCompleted();
+
+ private:
+ friend class UpdateFinder;
+ struct UpdateData;
+ UpdateData* d;
+
+ void doRun();
+ bool doStop();
+ bool doPause();
+ bool doResume();
+
+ Update(Application* application, const UpdateSourceInfo& sourceInfo,
+ UpdateType type, const QUrl& updateUrl, const QMap<QString, QVariant>& data, quint64 compressedSize, quint64 uncompressedSize, const QByteArray& sha1sum );
+ };
+}
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatefinder.cpp b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatefinder.cpp
new file mode 100644
index 000000000..8d34586e8
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatefinder.cpp
@@ -0,0 +1,892 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdupdaterupdatefinder.h"
+#include "kdupdaterapplication.h"
+#include "kdupdaterupdatesourcesinfo.h"
+#include "kdupdaterpackagesinfo.h"
+#include "kdupdaterupdate.h"
+#include "kdupdaterfiledownloader_p.h"
+#include "kdupdaterfiledownloaderfactory.h"
+#include "kdupdaterupdatesinfo_p.h"
+#include "kdupdatersignatureverifier.h"
+
+#include <QCoreApplication>
+#include <QDebug>
+
+using namespace KDUpdater;
+
+/*!
+ \ingroup kdupdater
+ \class KDUpdater::UpdateFinder kdupdaterupdatefinder KDUpdaterUpdateFinder
+ \brief Finds updates applicable for a \ref KDUpdater::Application
+
+ The KDUpdater::UpdateFinder class helps in searching for updates and installing it on the application. The
+ class basically processes the application's \ref KDUpdater::PackagesInfo and the UpdateXMLs it aggregates
+ from all the update sources described in KDUpdater::UpdateSourcesInfo and populates a list of
+ \ref KDUpdater::Update objects. This list can then be passed to \ref KDUpdater::UpdateInstaller for
+ actually downloading and installing the updates.
+
+
+ Usage:
+ \code
+ KDUpdater::UpdateFinder updateFinder( application );
+ QProgressDialog finderProgressDlg;
+
+ QObject::connect( &updateFinder, SIGNAL(progressValue(int)),
+ &finderProgressDlg, SLOT(setValue(int)));
+ QObject::connect( &updateFinder, SIGNAL(computeUpdatesCompleted()),
+ &finderProgressDlg, SLOT(accept()));
+ QObject::connect( &updateFinder, SIGNAL(computeUpdatesCanceled()),
+ &finderProgressDlg, SLOT(reject()));
+
+ QObject::connect( &finderProgressDlg, SIGNAL(canceled()),
+ &updateFinder, SLOT(cancelComputeUpdates()));
+
+ updateFinder.run();
+ finderProgressDlg.exec();
+
+// Control comes here after update finding is done or canceled.
+
+QList<KDUpdater::Update*> updates = updateFinder.updates();
+KDUpdater::UpdateInstaller updateInstaller;
+updateInstaller.installUpdates( updates );
+
+\endcode
+*/
+
+
+//
+// Private
+//
+class KDUpdater::UpdateFinder::Private
+{
+public:
+ Private( UpdateFinder* qq ) :
+ q( qq ),
+ application(0),
+ updateType(KDUpdater::PackageUpdate)
+ {}
+
+ ~Private()
+ {
+ qDeleteAll( updates );
+ qDeleteAll( updatesInfoList );
+ qDeleteAll( updateXmlFDList );
+ }
+
+ UpdateFinder* q;
+ KDUpdater::Application* application;
+ QList<KDUpdater::Update*> updates;
+ UpdateTypes updateType;
+
+ // Temporary structure that notes down information about updates.
+ bool cancel;
+ int downloadCompleteCount;
+ QList<KDUpdater::UpdateSourceInfo> updateSourceInfoList;
+ QList<KDUpdater::UpdatesInfo*> updatesInfoList;
+ QList<KDUpdater::FileDownloader*> updateXmlFDList;
+
+ void clear();
+ void computeUpdates();
+ void cancelComputeUpdates();
+ bool downloadUpdateXMLFiles();
+ bool computeApplicableUpdates();
+
+ QList<KDUpdater::UpdateInfo> applicableUpdates(KDUpdater::UpdatesInfo* updatesInfo, bool addNewPackages = false );
+ void createUpdateObjects(const KDUpdater::UpdateSourceInfo& sourceInfo,
+ const QList<KDUpdater::UpdateInfo>& updateInfoList);
+ bool checkForUpdatePriority(const KDUpdater::UpdateSourceInfo& sourceInfo,
+ const KDUpdater::UpdateInfo& updateInfo);
+ int pickUpdateFileInfo(const QList<KDUpdater::UpdateFileInfo>& updateFiles);
+ void slotDownloadDone();
+};
+
+
+static int computeProgressPercentage(int min, int max, int percent)
+{
+ return min + qint64(max-min) * percent / 100;
+}
+
+static int computePercent(int done, int total)
+{
+ return total ? done * Q_INT64_C(100) / total : 0 ;
+}
+
+/*!
+ \internal
+
+ Releases all internal resources consumed while downloading and computing updates.
+*/
+void KDUpdater::UpdateFinder::Private::clear()
+{
+ qDeleteAll( updates );
+ updates.clear();
+ qDeleteAll( updatesInfoList );
+ updatesInfoList.clear();
+ qDeleteAll( updateXmlFDList );
+ updateXmlFDList.clear();
+ updateSourceInfoList.clear();
+
+ downloadCompleteCount = 0;
+}
+
+/*!
+ \internal
+
+ This method computes the updates that can be applied on the application by
+ studying the application's \ref KDUpdater::PackagesInfo object and the UpdateXML files
+ from each of the update sources described in \ref KDUpdater::UpdateSourcesInfo.
+
+ This function can take a long time to complete. The following signals are emitted
+ during the execution of this function
+
+ The function creates \ref KDUpdater::Update objects on the stack. All KDUpdater::Update objects
+ are made children of the application associated with this finder.
+
+ The update sources are fetched from the \ref KDUpdater::UpdateSourcesInfo object associated with
+ the application. Package information is extracted from the \ref KDUpdater::PackagesInfo object
+ associated with the application.
+
+ \note Each time this function is called, all the previously computed updates are discarded
+and its resources are freed.
+*/
+void KDUpdater::UpdateFinder::Private::computeUpdates()
+{
+ // Computing updates is done in two stages
+ // 1. Downloading Update XML files from all the update sources
+ // 2. Matching updates with Package XML and figuring out available updates
+
+ cancel = false;
+ clear();
+
+ // First do some quick sanity checks on the packages info
+ KDUpdater::PackagesInfo* packages = application->packagesInfo();
+ if( !packages ) {
+ q->reportError(tr("Could not access the package information of this application"));
+ return;
+ }
+ if( !packages->isValid() ) {
+ q->reportError(packages->errorString());
+ return;
+ }
+
+ // Now do some quick sanity checks on the update sources info
+ KDUpdater::UpdateSourcesInfo* sources = application->updateSourcesInfo();
+ if( !sources ) {
+ q->reportError(tr("Could not access the update sources information of this application"));
+ return;
+ }
+ if( !sources->isValid() ) {
+ q->reportError(sources->errorString());
+ return;
+ }
+
+ // Now we can start...
+
+ // Step 1: 0 - 49 percent
+ if(!downloadUpdateXMLFiles() || cancel)
+ {
+ clear();
+ return;
+ }
+
+ // Step 2: 50 - 100 percent
+ if(!computeApplicableUpdates() || cancel)
+ {
+ clear();
+ return;
+ }
+
+ // All done
+ q->reportProgress( 100, tr("%1 updates found").arg(updates.count()) );
+ q->reportDone();
+}
+
+/*!
+ \internal
+
+ Cancels the computation of updates.
+
+ \sa \ref computeUpdates()
+*/
+void KDUpdater::UpdateFinder::Private::cancelComputeUpdates()
+{
+ cancel = true;
+}
+
+/*!
+ \internal
+
+ This function downloads Updates.xml from all the update sources. A single application can potentially
+ have several update sources, hence we need to be asynchronous in downloading updates from different
+ sources.
+
+ The function basically does this for each update source
+ a) Create a KDUpdater::FileDownloader and KDUpdater::UpdatesInfo for each update
+ b) Triggers the download of Updates.xml from each file downloader.
+ c) The downloadCompleted(), downloadCanceled() and downloadAborted() signals are connected
+ in each of the downloaders. Once all the downloads are complete and/or aborted, the next stage
+ would be done.
+
+ The function gets into an event loop until all the downloads are complete.
+*/
+bool KDUpdater::UpdateFinder::Private::downloadUpdateXMLFiles()
+{
+ if( !application )
+ return false;
+
+ KDUpdater::UpdateSourcesInfo* updateSources = application->updateSourcesInfo();
+ if( !updateSources )
+ return false;
+
+ // Create KDUpdater::FileDownloader and KDUpdater::UpdatesInfo for each update
+ for(int i=0; i<updateSources->updateSourceInfoCount(); i++)
+ {
+ KDUpdater::UpdateSourceInfo info = updateSources->updateSourceInfo(i);
+ QUrl updateXmlUrl = QString::fromLatin1("%1/Updates.xml").arg(info.url.toString());
+
+ const SignatureVerifier* verifier = application->signatureVerifier( Application::Metadata );
+ KDUpdater::FileDownloader* downloader = FileDownloaderFactory::instance().create(updateXmlUrl.scheme(), verifier, QUrl(), q);
+ if( !downloader )
+ continue;
+
+ downloader->setUrl(updateXmlUrl);
+ downloader->setAutoRemoveDownloadedFile(true);
+
+ KDUpdater::UpdatesInfo* updatesInfo = new KDUpdater::UpdatesInfo;
+ updateSourceInfoList.append(info);
+ updateXmlFDList.append(downloader);
+ updatesInfoList.append(updatesInfo);
+
+ connect(downloader, SIGNAL(downloadCompleted()),
+ q, SLOT(slotDownloadDone()));
+ connect(downloader, SIGNAL(downloadCanceled()),
+ q, SLOT(slotDownloadDone()));
+ connect(downloader, SIGNAL(downloadAborted(QString)),
+ q, SLOT(slotDownloadDone()));
+ }
+
+ // Trigger download of Updates.xml file
+ downloadCompleteCount = 0;
+ for(int i=0; i<updateXmlFDList.count(); i++)
+ {
+ KDUpdater::FileDownloader* downloader = updateXmlFDList[i];
+ downloader->download();
+ }
+
+ // Wait until all downloaders have completed their downloads.
+ while(1)
+ {
+ QCoreApplication::processEvents();
+ if( cancel )
+ return false;
+ if( downloadCompleteCount == updateXmlFDList.count())
+ break;
+
+ int pc = computePercent(downloadCompleteCount, updateXmlFDList.count());
+ q->reportProgress(pc, tr("Downloading Updates.xml from update-sources"));
+ }
+
+ // All the downloaders have now either downloaded or aborted the
+ // donwload of update XML files.
+
+ // Lets now get rid of update sources whose Updates.xml could not be downloaded
+ for(int i=0; i<updateXmlFDList.count(); i++)
+ {
+ KDUpdater::FileDownloader* downloader = updateXmlFDList[i];
+ if( downloader->isDownloaded() )
+ continue;
+
+ KDUpdater::UpdateSourceInfo info = updateSourceInfoList[i];
+ QString msg = tr("Could not download updates from %1 ('%2')").arg(info.name, info.url.toString());
+ q->reportError(msg);
+
+ delete updatesInfoList[i];
+ delete downloader;
+ updateXmlFDList.removeAt(i);
+ updatesInfoList.removeAt(i);
+ updateSourceInfoList.removeAt(i);
+ --i;
+ }
+
+ if (updatesInfoList.isEmpty()) {
+ return false;
+ }
+
+ // Lets parse the downloaded update XML files and get rid of the downloaders.
+ for(int i=0; i<updateXmlFDList.count(); i++)
+ {
+ KDUpdater::FileDownloader* downloader = updateXmlFDList[i];
+ KDUpdater::UpdatesInfo* updatesInfo = updatesInfoList[i];
+
+ updatesInfo->setFileName( downloader->downloadedFileName() );
+
+ if (!updatesInfo->isValid()) {
+ QString msg = updatesInfo->errorString();
+ q->reportError(msg);
+
+ delete updatesInfoList[i];
+ delete downloader;
+ updateXmlFDList.removeAt(i);
+ updatesInfoList.removeAt(i);
+ --i;
+ }
+ }
+ qDeleteAll( updateXmlFDList );
+ updateXmlFDList.clear();
+
+ if (updatesInfoList.isEmpty()) {
+ return false;
+ }
+
+ q->reportProgress( 49, tr("Updates.xml file(s) downloaded from update sources") );
+ return true;
+}
+
+/*!
+ \internal
+
+ This function runs through all the KDUpdater::UpdatesInfo objects created during
+ the downloadUpdateXMLFiles() method and compares it with the data contained in
+ KDUpdater::PackagesInfo. There by figures out whether an update is applicable for
+ this application or not.
+*/
+bool KDUpdater::UpdateFinder::Private::computeApplicableUpdates()
+{
+ if( updateType & KDUpdater::CompatUpdate )
+ {
+ KDUpdater::UpdateInfo compatUpdateInfo;
+ KDUpdater::UpdateSourceInfo compatUpdateSourceInfo;
+
+ // Required compat level
+ int reqCompatLevel = application->compatLevel()+1;
+
+ q->reportProgress(60, tr("Looking for compatibility update..."));
+
+ // We are only interested in compat updates.
+ for(int i=0; i<updatesInfoList.count(); i++)
+ {
+ KDUpdater::UpdatesInfo* info = updatesInfoList[i];
+ KDUpdater::UpdateSourceInfo updateSource = updateSourceInfoList[i];
+
+ // If we already have a compat update, just check if the source currently being
+ // considered has a higher priority or not.
+ if(compatUpdateInfo.data.contains( QLatin1String( "CompatLevel" ) ) && updateSource.priority < compatUpdateSourceInfo.priority)
+ continue;
+
+ // Lets look for comapt updates that provide compat level one-higher than
+ // the application's current compat level.
+ QList<KDUpdater::UpdateInfo> updatesInfo = info->updatesInfo( KDUpdater::CompatUpdate, reqCompatLevel );
+
+ if( updatesInfo.count() == 0 )
+ continue;
+
+ compatUpdateInfo = updatesInfo.at( 0 );
+ compatUpdateSourceInfo = updateSource;
+ }
+
+ bool found = (compatUpdateInfo.data.contains( QLatin1String( "CompatLevel" ) ));
+ if(found)
+ {
+ q->reportProgress(80, tr("Found compatibility update.."));
+
+ // Lets create an update for this compat update.
+ QString updateName = tr("Compatibility level %1 update").arg(reqCompatLevel);
+ QUrl url;
+
+ // Pick a update file based on arch and OS.
+ int pickUpdateFileIndex = pickUpdateFileInfo(compatUpdateInfo.updateFiles);
+ if(pickUpdateFileIndex < 0)
+ {
+ q->reportError(tr("Compatibility update for the required architecture and hardware configuration was not found"));
+ q->reportProgress(100, tr("Compatibility update not found"));
+ return false;
+ }
+
+ KDUpdater::UpdateFileInfo fileInfo = compatUpdateInfo.updateFiles.at( pickUpdateFileIndex );
+
+ // Create an update for this entry
+ url = QString::fromLatin1( "%1/%2" ).arg( compatUpdateSourceInfo.url.toString(), fileInfo.fileName );
+ KDUpdater::Update* update = q->constructUpdate(application,
+ compatUpdateSourceInfo,
+ KDUpdater::CompatUpdate, url,
+ compatUpdateInfo.data, fileInfo.compressedSize, fileInfo.uncompressedSize, fileInfo.sha1sum );
+
+ // Register the update
+ updates.append(update);
+
+ // Done
+ q->reportProgress(100, tr("Compatibility update found"));
+ }
+ else
+ q->reportProgress(100, tr("No compatibility updates found"));
+ }
+ if ( updateType & PackageUpdate )
+ {
+ // We are not looking for normal updates, not compat ones.
+ for(int i=0; i<updatesInfoList.count(); i++)
+ {
+ // Fetch updates applicable to this application.
+ KDUpdater::UpdatesInfo* info = updatesInfoList[i];
+ QList<KDUpdater::UpdateInfo> updates = applicableUpdates(info , updateType & NewPackage );
+ if( !updates.count() )
+ continue;
+
+ if( cancel )
+ return false;
+ KDUpdater::UpdateSourceInfo updateSource = updateSourceInfoList[i];
+
+ // Create KDUpdater::Update objects for updates that have a valid
+ // UpdateFile
+ createUpdateObjects(updateSource, updates);
+ if( cancel )
+ return false;
+
+ // Report progress
+ int pc = computePercent(i, updatesInfoList.count());
+ pc = computeProgressPercentage(51, 100, pc);
+ q->reportProgress( pc, tr("Computing applicable updates") );
+ }
+ }
+
+ q->reportProgress( 99, tr("Application updates computed") );
+ return true;
+}
+
+QList<KDUpdater::UpdateInfo> KDUpdater::UpdateFinder::Private::applicableUpdates( KDUpdater::UpdatesInfo* updatesInfo, bool addNewPackages )
+{
+ QList<KDUpdater::UpdateInfo> retList;
+
+ if( !updatesInfo || updatesInfo->updateInfoCount( PackageUpdate ) == 0 )
+ return retList;
+
+ KDUpdater::PackagesInfo* packages = this->application->packagesInfo();
+ if( !packages )
+ return retList;
+
+ // Check to see if the updates info contains updates for any application
+ bool anyApp = updatesInfo->applicationName() == QLatin1String( "{AnyApplication}" );
+ int appNameIndex = -1;
+
+ if( !anyApp )
+ {
+ // updatesInfo->applicationName() describes one application or a series of
+ // application names separated by commas.
+ QString appName = updatesInfo->applicationName();
+ appName = appName.replace(QLatin1String( ", " ),
+ QLatin1String( "," ));
+ appName = appName.replace(QLatin1String( " ," ),
+ QLatin1String( "," ));
+
+ // Catch hold of app names contained updatesInfo->applicationName()
+ QStringList apps = appName.split(QLatin1String( "," ), QString::SkipEmptyParts);
+ appNameIndex = apps.indexOf(this->application->applicationName());
+
+ // If the application appName isnt one of the app names, then
+ // the updates are not applicable.
+ if( appNameIndex < 0 )
+ return retList;
+ }
+
+#if 0 //Nokia-SDK: ignore ApplicationVersion, it has no purpose and just causes problems if someone bumps the config.xml application version accidentally
+ // Check to see if the update repository versions match with app version
+ if( !anyApp )
+ {
+ QString appVersion = updatesInfo->applicationVersion();
+ appVersion = appVersion.replace(QLatin1String( ", " ), QLatin1String( "," ));
+ appVersion = appVersion.replace(QLatin1String( " ," ), QLatin1String( "," ));
+ QStringList versions = appVersion.split(QLatin1String( "," ), QString::SkipEmptyParts);
+
+ if( appNameIndex >= versions.count() )
+ return retList; // please give us well formatted Updates.xml files.
+
+ QString version = versions[appNameIndex];
+ if( KDUpdater::compareVersion(this->application->applicationVersion(), version) != 0 )
+ return retList;
+ }
+#endif
+
+ // Check to see if version numbers match. This means that the version
+ // number of the update should be greater than the version number of
+ // the package that is currently installed.
+ QList<KDUpdater::UpdateInfo> updateList = updatesInfo->updatesInfo( KDUpdater::PackageUpdate );
+ for(int i=0; i<updatesInfo->updateInfoCount( PackageUpdate ); i++)
+ {
+ KDUpdater::UpdateInfo updateInfo = updateList.at( i );
+ if( !addNewPackages )
+ {
+ int pkgInfoIdx = packages->findPackageInfo( updateInfo.data.value( QLatin1String( "Name" ) ).toString() );
+ if( pkgInfoIdx < 0 )
+ continue;
+
+ KDUpdater::PackageInfo pkgInfo = packages->packageInfo( pkgInfoIdx );
+
+ // First check to see if the update version is more than package version
+ QString updateVersion = updateInfo.data.value( QLatin1String( "Version" ) ).toString();
+ QString pkgVersion = pkgInfo.version;
+ if( KDUpdater::compareVersion(updateVersion, pkgVersion) <= 0 )
+ continue;
+
+ // It is quite possible that we may have already installed the update.
+ // Lets check the last update date of the package and the release date
+ // of the update. This way we can compare and figure out if the update
+ // has been installed or not.
+ QDate pkgDate = pkgInfo.lastUpdateDate;
+ QDate updateDate = updateInfo.data.value( QLatin1String( "ReleaseDate" ) ).toDate();
+ if( pkgDate > updateDate )
+ continue;
+ }
+
+ // Bingo!, we found an update :-)
+ retList.append(updateInfo);
+ }
+
+ return retList;
+}
+
+void KDUpdater::UpdateFinder::Private::createUpdateObjects(const KDUpdater::UpdateSourceInfo& sourceInfo, const QList<KDUpdater::UpdateInfo>& updateInfoList)
+{
+ for(int i=0; i<updateInfoList.count(); i++)
+ {
+ KDUpdater::UpdateInfo info = updateInfoList[i];
+ // Compat level checks
+ if( info.data.contains( QLatin1String( "RequiredCompatLevel" ) ) &&
+ info.data.value( QLatin1String( "RequiredCompatLevel" ) ).toInt() != application->compatLevel() )
+ {
+ qDebug() << "Update \"" << info.data.value( QLatin1String( "Name" ) ).toString() << "\" at \""
+ << sourceInfo.name << "\"(\"" << sourceInfo.url.toString() << "\") requires a different compat level";
+ continue; // Compatibility level mismatch
+ }
+
+ // If another update of the same name exists, then use the update coming from
+ // a higher priority.
+ if( !checkForUpdatePriority(sourceInfo, info) )
+ {
+ qDebug() << "Skipping Update \""
+ << info.data.value( QLatin1String( "Name" ) ).toString()
+ << "\" from \""
+ << sourceInfo.name
+ << "\"(\""
+ << sourceInfo.url.toString()
+ << "\") because an update with the same name was found from a higher priority location";
+
+ continue;
+ }
+
+ // Pick a update file based on arch and OS.
+ int pickUpdateFileIndex = this->pickUpdateFileInfo(info.updateFiles);
+ if(pickUpdateFileIndex < 0)
+ continue;
+
+ KDUpdater::UpdateFileInfo fileInfo = info.updateFiles.at( pickUpdateFileIndex );
+
+ // Create an update for this entry
+ QUrl url( QString::fromLatin1("%1/%2").arg( sourceInfo.url.toString(), fileInfo.fileName ) );
+ KDUpdater::Update* update = q->constructUpdate(application, sourceInfo, KDUpdater::PackageUpdate, url, info.data, fileInfo.compressedSize, fileInfo.uncompressedSize, fileInfo.sha1sum );
+
+ // Register the update
+ this->updates.append(update);
+ }
+}
+
+bool KDUpdater::UpdateFinder::Private::checkForUpdatePriority(const KDUpdater::UpdateSourceInfo& sourceInfo, const KDUpdater::UpdateInfo& updateInfo)
+{
+ for(int i=0; i<this->updates.count(); i++)
+ {
+ KDUpdater::Update* update = this->updates[i];
+ if( update->data( QLatin1String( "Name" ) ).toString() != updateInfo.data.value( QLatin1String( "Name" ) ).toString() )
+ continue;
+
+ // Bingo, update was previously found elsewhere.
+
+ // If the existing update comes from a higher priority server, then cool :)
+ if( update->sourceInfo().priority > sourceInfo.priority )
+ return false;
+
+ // If the existing update has a higher version number, keep it
+ if ( KDUpdater::compareVersion(update->data( QLatin1String( "Version" ) ).toString(),
+ updateInfo.data.value( QLatin1String( "Version" ) ).toString()) > 0)
+ return false;
+
+ // Otherwise the old update must be deleted.
+ this->updates.removeAll(update);
+ delete update;
+
+ return true;
+ }
+
+ // No update by that name was found, so what we have is a priority update.
+ return true;
+}
+
+int KDUpdater::UpdateFinder::Private::pickUpdateFileInfo(const QList<KDUpdater::UpdateFileInfo>& updateFiles)
+{
+#ifdef Q_WS_MAC
+ QString os = QLatin1String( "MacOSX" );
+#endif
+#ifdef Q_WS_WIN
+ QString os = QLatin1String( "Windows" );
+#endif
+#ifdef Q_WS_X11
+ QString os = QLatin1String( "Linux" );
+#endif
+
+ QString arch = QLatin1String( "i386" ); // only one architecture considered for now.
+
+ for(int i=0; i<updateFiles.count(); i++)
+ {
+ KDUpdater::UpdateFileInfo fileInfo = updateFiles[i];
+
+ if( fileInfo.arch != arch )
+ continue;
+
+ if( fileInfo.os != QLatin1String( "Any" ) && fileInfo.os != os )
+ continue;
+
+ return i;
+ }
+
+ return -1;
+}
+
+
+
+//
+// UpdateFinder
+//
+
+/*!
+ Constructs a update finder for a given \ref KDUpdater::Application.
+*/
+KDUpdater::UpdateFinder::UpdateFinder(KDUpdater::Application* application)
+ : KDUpdater::Task(QLatin1String( "UpdateFinder" ), Stoppable, application),
+ d( new Private( this ) )
+{
+ d->application = application;
+}
+
+/*!
+ Destructor
+*/
+KDUpdater::UpdateFinder::~UpdateFinder()
+{
+ delete d;
+}
+
+/*!
+ Returns a pointer to the update application for which this function computes all
+ the updates.
+*/
+KDUpdater::Application* KDUpdater::UpdateFinder::application() const
+{
+ return d->application;
+}
+
+/*!
+ Returns a list of KDUpdater::Update objects. The update objects returned in this list
+ are made children of the \ref KDUpdater::Application object associated with this class.
+*/
+QList<KDUpdater::Update*> KDUpdater::UpdateFinder::updates() const
+{
+ return d->updates;
+}
+
+/*!
+ Looks only for a certain type of update. By default, only package update
+*/
+void KDUpdater::UpdateFinder::setUpdateType(UpdateTypes type)
+{
+ d->updateType = type;
+}
+
+/*!
+ Returns the type of updates searched
+*/
+KDUpdater::UpdateTypes KDUpdater::UpdateFinder::updateType() const
+{
+ return d->updateType;
+}
+
+/*!
+ \internal
+
+ Implemented from \ref KDUpdater::Task::doStart().
+*/
+void KDUpdater::UpdateFinder::doRun()
+{
+ d->computeUpdates();
+}
+
+/*!
+ \internal
+
+ Implemented form \ref KDUpdater::Task::doStop()
+*/
+bool KDUpdater::UpdateFinder::doStop()
+{
+ d->cancelComputeUpdates();
+
+ // Wait until the cancel has actually happened, and then return.
+ // Thinking of using QMutex for this. Frank/Till any suggestions?
+
+ return true;
+}
+
+/*!
+ \internal
+
+ Implemented form \ref KDUpdater::Task::doStop()
+*/
+bool KDUpdater::UpdateFinder::doPause()
+{
+ // Not a pausable task
+ return false;
+}
+
+/*!
+ \internal
+
+ Implemented form \ref KDUpdater::Task::doStop()
+*/
+bool KDUpdater::UpdateFinder::doResume()
+{
+ // Not a pausable task, hence it is not resumable as well
+ return false;
+}
+
+/*!
+ \internal
+*/
+void KDUpdater::UpdateFinder::Private::slotDownloadDone()
+{
+ ++downloadCompleteCount;
+
+ int pc = computePercent(downloadCompleteCount, updateXmlFDList.count());
+ pc = computeProgressPercentage(0, 45, pc);
+ q->reportProgress( pc, tr("Downloading Updates.xml from update sources") );
+}
+
+/*!
+ \internal
+ */
+KDUpdater::Update* KDUpdater::UpdateFinder::constructUpdate( Application* application, const UpdateSourceInfo& sourceInfo,
+ UpdateType type, const QUrl& updateUrl, const QMap< QString, QVariant >& data, quint64 compressedSize, quint64 uncompressedSize, const QByteArray& sha1sum )
+{
+ return new Update( application, sourceInfo, type, updateUrl, data, compressedSize, uncompressedSize, sha1sum );
+}
+
+
+/*!
+ \ingroup kdupdater
+
+ This function compares two version strings \c v1 and \c v2 and returns
+ -1, 0 or +1 based on the following rule
+
+ \li Returns 0 if v1 == v2
+ \li Returns -1 if v1 < v2
+ \li Returns +1 if v1 > v2
+
+ The function is very similar to \c strcmp(), except that it works on version strings.
+
+ Example:
+ \code
+
+ KDUpdater::compareVersion("2.0", "2.1"); // Returns -1
+ KDUpdater::compareVersion("2.1", "2.0"); // Returns +1
+ KDUpdater::compareVersion("2.0", "2.0"); // Returns 0
+ KDUpdater::compareVersion("2.1", "2.1"); // Returns 0
+
+ KDUpdater::compareVersion("2.0", "2.x"); // Returns 0
+ KDUpdater::compareVersion("2.x", "2.0"); // Returns 0
+
+ KDUpdater::compareVersion("2.0.12.4", "2.1.10.4"); // Returns -1
+ KDUpdater::compareVersion("2.0.12.x", "2.0.x"); // Returns 0
+ KDUpdater::compareVersion("2.1.12.x", "2.0.x"); // Returns +1
+ KDUpdater::compareVersion("2.1.12.x", "2.x"); // Returns 0
+ KDUpdater::compareVersion("2.x", "2.1.12.x"); // Returns 0
+
+ \endcode
+*/
+int KDUpdater::compareVersion(const QString& v1, const QString& v2)
+{
+ // For tests refer VersionCompareFnTest testcase.
+
+ // Check for equality
+ if( v1 == v2 )
+ return 0;
+
+ // Split version numbers across .
+ const QStringList v1_comps = v1.split( QRegExp( QLatin1String( "\\.|-" ) ) );
+ const QStringList v2_comps = v2.split( QRegExp( QLatin1String( "\\.|-" ) ) );
+
+ // Check each component of the version
+ int index = 0;
+ while(1)
+ {
+ if( index == v1_comps.count() && index < v2_comps.count() )
+ return -1;
+ else if( index < v1_comps.count() && index == v2_comps.count() )
+ return +1;
+ else if( index >= v1_comps.count() || index >= v2_comps.count() )
+ break;
+
+ bool v1_ok, v2_ok;
+ int v1_comp = v1_comps[index].toInt(&v1_ok);
+ int v2_comp = v2_comps[index].toInt(&v2_ok);
+
+ if(!v1_ok)
+ {
+ if(v1_comps[index] == QLatin1String( "x" ) )
+ return 0;
+ }
+ if(!v2_ok)
+ {
+ if(v2_comps[index] == QLatin1String( "x") )
+ return 0;
+ }
+ if( !v1_ok && !v2_ok )
+ {
+ return v1_comps[ index ].compare( v2_comps[ index ] );
+ }
+
+ if( v1_comp < v2_comp )
+ return -1;
+
+ if( v1_comp > v2_comp )
+ return +1;
+
+ // v1_comp == v2_comp
+ ++index;
+ }
+
+ if( index < v2_comps.count() )
+ return +1;
+
+ if( index < v1_comps.count() )
+ return -1;
+
+ // Controversial return. I hope this never happens.
+ return 0;
+}
+
+#include "moc_kdupdaterupdatefinder.cpp"
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatefinder.h b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatefinder.h
new file mode 100644
index 000000000..14ebb9c97
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatefinder.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef KD_UPDATER_UPDATE_FINDER_H
+#define KD_UPDATER_UPDATE_FINDER_H
+
+#include "kdupdater.h"
+#include "kdupdatertask.h"
+#include <QList>
+#include <QMap>
+
+class QUrl;
+
+namespace KDUpdater
+{
+ class Application;
+ class Update;
+ struct UpdateSourceInfo;
+
+ class KDTOOLS_UPDATER_EXPORT UpdateFinder : public Task
+ {
+ Q_OBJECT
+
+ public:
+ explicit UpdateFinder(Application* application);
+ ~UpdateFinder();
+
+ Application* application() const;
+ QList<Update*> updates() const;
+
+ void setUpdateType( UpdateTypes type );
+ UpdateTypes updateType() const;
+
+ private:
+ void doRun();
+ bool doStop();
+ bool doPause();
+ bool doResume();
+
+ Update* constructUpdate( Application* application, const UpdateSourceInfo& sourceInfo,
+ UpdateType type, const QUrl& updateUrl, const QMap< QString, QVariant >& data, quint64 compressedSize, quint64 uncompressedSize, const QByteArray& sha1sum );
+
+
+ private:
+ class Private;
+ Private* const d;
+ Q_PRIVATE_SLOT( d, void slotDownloadDone() )
+ };
+};
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateinstaller.cpp b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateinstaller.cpp
new file mode 100644
index 000000000..3b8d2dbd4
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateinstaller.cpp
@@ -0,0 +1,481 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdupdaterupdateinstaller.h"
+#include "kdupdaterpackagesinfo.h"
+#include "kdupdaterapplication.h"
+#include "kdupdaterupdate.h"
+#include "kdupdaterupdateoperationfactory.h"
+#include "kdupdaterupdateoperation.h"
+#include "kdupdaterufuncompressor_p.h"
+
+#include <QCoreApplication>
+#include <QFileInfo>
+#include <QDir>
+#include <QDomDocument>
+#include <QDomElement>
+#include <QDate>
+
+/*!
+ \ingroup kdupdater
+ \class KDUpdater::UpdateInstaller kdupdaterupdateinstaller.h KDUpdaterUpdateInstaller
+ \brief Installs updates, given a list of \ref KDUpdater::Update objects
+
+ This class installs updates, given a list of \ref KDUpdater::Update objects via the
+ \ref installUpdates() method. To install the updates this class performs the following
+ for each update
+
+ \li Downloads the update files from its source
+ \li Unpacks update files into a temporary directory
+ \li Parses and executes UpdateInstructions.xml by making use of \ref KDUpdater::UpdateOperation
+ objects sourced via \ref KDUpdater::UpdateOperationFactory
+
+ \note All temporary files created during the installation of the update will be destroyed
+ immediately after the installation is complete.
+*/
+class KDUpdater::UpdateInstaller::Private
+{
+ public:
+ Private( UpdateInstaller* qq ) :
+ q( qq )
+ {}
+
+ UpdateInstaller* q;
+
+ KDUpdater::Application* application;
+ int updateDownloadDoneCount;
+ int updateDownloadProgress;
+ int totalUpdates;
+ QStringList toRemoveDirs;
+
+ int totalProgressPc;
+ int currentProgressPc;
+ QList<KDUpdater::Update*> updates;
+
+ void resolveArguments(QStringList& args);
+
+ void removeDirectory(const QDir & dir);
+ void slotUpdateDownloadProgress(int percent);
+ void slotUpdateDownloadDone();
+};
+
+// next two are duplicated from kdupdaterupdatefinder.cpp:
+
+static int computeProgressPercentage(int min, int max, int percent)
+{
+ return min + qint64(max-min) * percent / 100 ;
+}
+
+static int computePercent(int done, int total)
+{
+ return total ? done * Q_INT64_C(100) / total : 0 ;
+}
+
+/*!
+ Constructs an instance of this class for the \ref KDUpdater::Application passed as
+ parameter. Only updates meant for the specified application will be installed by this class.
+*/
+KDUpdater::UpdateInstaller::UpdateInstaller(KDUpdater::Application* application)
+ : KDUpdater::Task(QLatin1String( "UpdateInstaller" ), NoCapability, application),
+ d( new Private( this ) )
+{
+ d->application = application;
+}
+
+/*!
+ Destructor
+*/
+KDUpdater::UpdateInstaller::~UpdateInstaller()
+{
+ delete d;
+}
+
+/*!
+ Returns the update application for which the update is being installed
+*/
+KDUpdater::Application* KDUpdater::UpdateInstaller::application() const
+{
+ return d->application;
+}
+
+/*!
+ Use this function to let the installer know what updates are to be installed. The
+ updates are actually installed when the \ref start() method is called on this class.
+*/
+void KDUpdater::UpdateInstaller::setUpdatesToInstall(const QList<KDUpdater::Update*>& updates)
+{
+ d->updates = updates;
+}
+
+/*!
+ Returns the updates that would be installed when the next time \ref the start) method is called.
+*/
+QList<KDUpdater::Update*> KDUpdater::UpdateInstaller::updatesToInstall() const
+{
+ return d->updates;
+}
+
+/*!
+ \internal
+*/
+void KDUpdater::UpdateInstaller::doRun()
+{
+ QList<KDUpdater::Update*>& updates = d->updates;
+
+ // First download all the updates
+ d->updateDownloadDoneCount = 0;
+ d->totalUpdates = updates.count();
+
+ for(int i=0; i<updates.count(); i++)
+ {
+ KDUpdater::Update* update = updates[i];
+ if( update->application() != d->application )
+ continue;
+
+ update->setProperty("_ProgressPc_", 0);
+ connect(update, SIGNAL(progressValue(int)), this, SLOT(slotUpdateDownloadProgress(int)));
+ connect(update, SIGNAL(finished()), this, SLOT(slotUpdateDownloadDone()));
+ connect(update, SIGNAL(stopped()), this, SLOT(slotUpdateDownloadDone()));
+ update->download();
+ }
+
+ d->totalProgressPc = updates.count() * 100;
+ d->currentProgressPc = 0;
+
+ // Wait until all updates have been downloaded
+ while(d->updateDownloadDoneCount != updates.count())
+ {
+ QCoreApplication::processEvents();
+
+ // Normalized progress
+ int progressPc = computePercent(d->currentProgressPc, d->totalProgressPc);
+
+ // Bring the progress to within 50 percent
+ progressPc = (progressPc>>1);
+
+ // Report the progress
+ reportProgress(progressPc, tr("Downloading updates..."));
+ }
+
+ // Global progress
+ reportProgress(50, tr("Updates downloaded..."));
+
+ // Save the current working directory of the application
+ QDir oldCWD = QDir::current();
+
+ int pcDiff = computePercent(1, updates.count());
+ pcDiff = computeProgressPercentage(50, 95, pcDiff) - 50;
+
+ // Now install one update after another.
+ for(int i=0; i<updates.count(); i++)
+ {
+ KDUpdater::Update* update = updates[i];
+
+ // Global progress
+ QString msg = tr("Installing %1..").arg(update->name());
+ int minPc = pcDiff*i + 50;
+ int maxPc = minPc + pcDiff;
+ reportProgress(minPc, msg);
+
+ if( update->application() != d->application )
+ continue;
+
+ QDir::setCurrent(oldCWD.absolutePath());
+ if (!installUpdate(update, minPc, maxPc)) {
+ d->application->packagesInfo()->writeToDisk();
+ return;
+ }
+ }
+
+ d->application->packagesInfo()->writeToDisk();
+
+ // Global progress
+ reportProgress(95, tr("Finished installing updates. Now removing temporary files and directories.."));
+
+ // Restore the current working directory of the application
+ QDir::setCurrent(oldCWD.absolutePath());
+
+ // Remove all the toRemoveDirs
+ for(int i=0; i<d->toRemoveDirs.count(); i++)
+ {
+ QDir dir( d->toRemoveDirs[i] );
+ d->removeDirectory( dir );
+
+ QString dirName = dir.dirName();
+ dir.cdUp();
+ dir.rmdir( dirName );
+ }
+ d->toRemoveDirs.clear();
+
+ // Global progress
+ reportProgress(100, tr("Removed temporary files and directories"));
+ reportDone();
+}
+
+/*!
+ \internal
+*/
+bool KDUpdater::UpdateInstaller::doStop()
+{
+ return false;
+}
+
+/*!
+ \internal
+*/
+bool KDUpdater::UpdateInstaller::doPause()
+{
+ return false;
+}
+
+/*!
+ \internal
+*/
+bool KDUpdater::UpdateInstaller::doResume()
+{
+ return false;
+}
+
+bool KDUpdater::UpdateInstaller::installUpdate(KDUpdater::Update* update, int minPc, int maxPc)
+{
+ QString updateName( update->name() );
+
+ // Sanity checks
+ if( !update->isDownloaded() )
+ {
+ QString msg = tr("Could not download update '%1'").arg(update->name());
+ reportError(msg);
+ return false;
+ }
+
+ // Step 1: Prepare a directory into which the UpdateFile will be unpacked.
+ // If update file is C:/Users/PRASHA~1/AppData/Local/Temp/qt_temp.Hp1204 and
+ // the applicationn name "MyApplication"
+ // Then the directory would be %USERDIR%/AppData/Local/Temp/MyApplication_Update1
+ static int count = 0;
+ QString dirName = QString::fromLatin1("%1_Update%2").arg(d->application->applicationName(), QString::number(count++));
+ QString updateFile = update->downloadedFileName();
+ QFileInfo fi(updateFile);
+ QDir dir( fi.absolutePath() );
+ dir.mkdir( dirName );
+ dir.cd( dirName );
+ d->toRemoveDirs << dir.absolutePath();
+
+ // Step 2: Unpack the update file into the update directory
+ KDUpdater::UFUncompressor uncompressor;
+ uncompressor.setFileName( updateFile );
+ uncompressor.setDestination( dir.absolutePath() );
+
+ if (!uncompressor.uncompress()) {
+ reportError(tr("Couldn't uncompress update: %1")
+ .arg(uncompressor.errorString()));
+ return false;
+ }
+
+ // Step 3: Find out the directory in which UpdateInstructions.xml can be found
+ QDir updateDir = dir;
+ while( !updateDir.exists(QLatin1String( "UpdateInstructions.xml" )) )
+ {
+ QString path = updateDir.absolutePath();
+ QFileInfoList fiList = updateDir.entryInfoList(QDir::Dirs|QDir::NoDotAndDotDot);
+ if( !fiList.count() ) // || fiList.count() >= 2 )
+ {
+ QString msg = tr("Could not find UpdateInstructions.xml for %1").arg(update->name());
+ reportError(msg);
+ return false;
+ }
+
+ updateDir.cd(fiList.first().fileName());
+ }
+
+ // Set the application's current working directory as updateDir
+ QDir::setCurrent(updateDir.absolutePath());
+
+ // Step 4: Now load the UpdateInstructions.xml file
+ QDomDocument doc;
+ QFile file(updateDir.absoluteFilePath(QLatin1String( "UpdateInstructions.xml" )));
+ if( !file.open(QFile::ReadOnly) )
+ {
+ QString msg = tr("Could not read UpdateInstructions.xml of %1").arg(update->name());
+ reportError(msg);
+ return false;
+ }
+ if( !doc.setContent(&file) )
+ {
+ QString msg = tr("Could not read UpdateInstructions.xml of %1").arg(update->name());
+ reportError(msg);
+ return false;
+ }
+
+ // Now parse and execute update operations
+ QDomNodeList operEList = doc.elementsByTagName(QLatin1String( "UpdateOperation" ));
+ QString msg = tr("Installing %1").arg(updateName);
+
+ for(int i=0; i<operEList.count(); i++)
+ {
+ int pc = computePercent(i+1, operEList.count());
+ pc = computeProgressPercentage(minPc, maxPc, pc);
+ reportProgress(pc, msg);
+
+ // Fetch the important XML elements in UpdateOperation
+ QDomElement operE = operEList.at(i).toElement();
+ QDomElement nameE = operE.firstChildElement(QLatin1String( "Name" ));
+ QDomElement errorE = operE.firstChildElement(QLatin1String( "OnError" ));
+ QDomElement argE = operE.firstChildElement(QLatin1String( "Arg" ));
+
+ // Figure out information about the update operation to perform
+ QString operName = nameE.text();
+ QString onError = errorE.attribute(QLatin1String( "Action" ), QLatin1String( "Abort" ) );
+ QStringList args;
+ while( !argE.isNull() )
+ {
+ args << argE.text();
+ argE = argE.nextSiblingElement(QLatin1String( "Arg" ));
+ }
+
+ //QString operSignature = QString::fromLatin1("%1(%2)").arg(operName, args.join( QLatin1String( ", ") ) );
+
+ // Fetch update operation
+ KDUpdater::UpdateOperation* const updateOperation = KDUpdater::UpdateOperationFactory::instance().create(operName);
+ if( !updateOperation )
+ {
+ QString errMsg = tr("Update operation %1 not supported").arg(operName);
+ reportError(errMsg);
+
+ if( onError == QLatin1String( "Continue" ) )
+ continue;
+
+ if( onError == QLatin1String( "Abort" ) )
+ return false;
+
+ if( onError == QLatin1String( "AskUser" ) )
+ {
+ // TODO:
+ continue;
+ }
+ }
+
+ // Now resolve special fields in arguments
+ d->resolveArguments(args);
+
+ // Now set the arguments to the update operation and execute the update operation
+ updateOperation->setArguments(args);
+ updateOperation->setApplication( d->application );
+ const bool success = updateOperation->performOperation();
+
+ updateOperation->clear();
+
+ if( !success )
+ {
+ QString errMsg = tr("Cannot execute '%1'").arg(updateOperation->operationCommand());
+ reportError(errMsg);
+
+ if( onError == QLatin1String( "Continue" ) )
+ continue;
+
+ if( onError == QLatin1String( "Abort" ) )
+ return false;
+
+ if( onError == QLatin1String( "AskUser" ) )
+ {
+ // TODO:
+ continue;
+ }
+ }
+ delete updateOperation;
+ }
+
+ Q_FOREACH( UpdateOperation* updateOperation, update->operations() ) {
+ updateOperation->performOperation();
+ }
+
+ msg = tr("Finished installing update %1").arg(update->name());
+ reportProgress(maxPc, msg);
+ return true;
+}
+
+/*!
+ \internal
+*/
+void KDUpdater::UpdateInstaller::Private::slotUpdateDownloadProgress(int percent)
+{
+ // 0-49 percent progress is dedicated for the download of updates
+ KDUpdater::Update* update = qobject_cast<KDUpdater::Update*>(q->sender());
+ if( !update )
+ return;
+
+ int oldPc = update->property("_ProgressPc_").toInt();
+ int diffPc = percent-oldPc;
+ if(diffPc <= 0)
+ return;
+
+ currentProgressPc += diffPc;
+ update->setProperty("_ProgressPc_", percent);
+}
+
+/*!
+ \internal
+*/
+void KDUpdater::UpdateInstaller::Private::slotUpdateDownloadDone()
+{
+ ++updateDownloadDoneCount;
+}
+
+void KDUpdater::UpdateInstaller::Private::resolveArguments(QStringList& args)
+{
+ for(int i=0; i<args.count(); i++)
+ {
+ QString arg = args[i];
+
+ arg = arg.replace(QLatin1String( "{APPDIR}" ), application->applicationDirectory());
+ arg = arg.replace(QLatin1String( "{HOME}" ), QDir::homePath());
+ arg = arg.replace(QLatin1String( "{APPNAME}" ), application->applicationName());
+ arg = arg.replace(QLatin1String( "{APPVERSION}" ), application->applicationVersion());
+ arg = arg.replace(QLatin1String( "{CURPATH}" ), QDir::currentPath());
+ arg = arg.replace(QLatin1String( "{ROOT}" ), QDir::rootPath());
+ arg = arg.replace(QLatin1String( "{TEMP}" ), QDir::tempPath());
+
+ args[i] = arg;
+ }
+}
+
+void KDUpdater::UpdateInstaller::Private::removeDirectory(const QDir & dir)
+{
+ QFileInfoList fiList = dir.entryInfoList(QDir::Dirs|QDir::Files|QDir::NoDotAndDotDot);
+ if( !fiList.count() )
+ return;
+
+ for(int i=0; i<fiList.count(); i++)
+ {
+ QFileInfo fi = fiList[i];
+ if( fi.isDir() )
+ {
+ QDir childDir = fi.absoluteFilePath();
+ removeDirectory( childDir );
+ dir.rmdir( childDir.dirName() );
+ }
+ else if( fi.isFile() )
+ QFile::remove( fi.absoluteFilePath() );
+ }
+}
+
+#include "moc_kdupdaterupdateinstaller.cpp"
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateinstaller.h b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateinstaller.h
new file mode 100644
index 000000000..dc3e58e48
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateinstaller.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef KD_UPDATER_UPDATE_INSTALLER_H
+#define KD_UPDATER_UPDATE_INSTALLER_H
+
+#include "kdupdater.h"
+#include "kdupdatertask.h"
+#include <QList>
+
+namespace KDUpdater
+{
+ class Application;
+ class Update;
+
+ class KDTOOLS_UPDATER_EXPORT UpdateInstaller : public Task
+ {
+ Q_OBJECT
+
+ public:
+ explicit UpdateInstaller(Application* application);
+ ~UpdateInstaller();
+
+ Application* application() const;
+
+ void setUpdatesToInstall(const QList<Update*>& updates);
+ QList<Update*> updatesToInstall() const;
+
+ private:
+ void doRun();
+ bool doStop();
+ bool doPause();
+ bool doResume();
+
+ bool installUpdate(Update* update, int minPc, int maxPc);
+
+ class Private;
+ Private * const d;
+
+ Q_PRIVATE_SLOT( d, void slotUpdateDownloadProgress(int) )
+ Q_PRIVATE_SLOT( d, void slotUpdateDownloadDone() )
+ };
+};
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateoperation.cpp b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateoperation.cpp
new file mode 100644
index 000000000..7c4121e8e
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateoperation.cpp
@@ -0,0 +1,417 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdupdaterupdateoperation.h"
+
+#include "kdupdaterapplication.h"
+
+#include <QDebug>
+#include <QDir>
+#include <QFileInfo>
+#include <QTemporaryFile>
+
+/*!
+ \ingroup kdupdater
+ \class KDUpdater::UpdateOperation kdupdaterupdateoperation.h KDUpdaterUpdateOperation
+ \brief Abstract base class for update operations.
+
+ The \ref KDUpdater::UpdateOperation is an abstract class that specifies an interface for
+ update operations. Concrete implementations of this class must perform a single update
+ operation like copy, move, delete etc.
+
+ \note Two seperate threads cannot be using a single instance of KDUpdater::UpdateOperation
+ at the same time.
+*/
+
+/*
+ * \internal
+ * Returns a filename for a temporary file based on \a templateName
+ */
+static QString backupFileName( const QString& templateName = QString() )
+{
+ const QFileInfo templ( templateName );
+ QTemporaryFile file( QDir::temp().absoluteFilePath( templ.fileName() ) );
+ file.open();
+ const QString name = file.fileName();
+ file.close();
+ file.remove();
+ return name;
+}
+
+using namespace KDUpdater;
+
+struct UpdateOperation::UpdateOperationData
+{
+ UpdateOperationData( UpdateOperation* qq ) :
+ q( qq ),
+ error( 0 ),
+ application(0)
+ {}
+
+ UpdateOperation* q;
+ QString name;
+ QStringList args;
+ QString errorString;
+ int error;
+ Application* application;
+ QVariantMap values;
+ QStringList delayedDeletionFiles;
+};
+
+
+/*!
+ Constructor
+*/
+UpdateOperation::UpdateOperation()
+ : d ( new UpdateOperationData( this ) )
+{
+}
+
+/*!
+ Destructor
+*/
+UpdateOperation::~UpdateOperation()
+{
+ Application* const app = Application::instance();
+ if( app )
+ app->addFilesForDelayedDeletion( filesForDelayedDeletion() );
+ delete d;
+}
+
+/*!
+ Returns the update operation name.
+
+ \sa setName()
+*/
+QString UpdateOperation::name() const
+{
+ return d->name;
+}
+
+/*!
+ Returns a command line string that describes the update operation. The returned
+ string would be of the form
+
+ <name> <arg1> <arg2> <arg3> ....
+*/
+QString UpdateOperation::operationCommand() const
+{
+ QString argsStr = d->args.join(QLatin1String( " " ));
+ return QString::fromLatin1( "%1 %2" ).arg(d->name, argsStr);
+}
+
+/*!
+ Returns true if there exists a setting called \a name. Otherwise returns false.
+*/
+bool UpdateOperation::hasValue( const QString& name ) const
+{
+ return d->values.contains( name );
+}
+
+/*!
+ Clears the value of setting \a name and removes it.
+ \post hasValue( \a name ) returns false.
+*/
+void UpdateOperation::clearValue( const QString& name )
+{
+ d->values.remove( name );
+}
+
+/*!
+ Returns the value of setting \a name. If the setting does not exists,
+ this returns an empty QVariant.
+*/
+QVariant UpdateOperation::value( const QString& name ) const
+{
+ return hasValue( name ) ? d->values[ name ] : QVariant();
+}
+
+/*!
+ Sets the value of setting \a name to \a value.
+*/
+void UpdateOperation::setValue( const QString& name, const QVariant& value )
+{
+ d->values[ name ] = value;
+}
+
+/*!
+ Sets a update operation name. Subclasses will have to provide a unique
+ name to describe this operation.
+*/
+void UpdateOperation::setName(const QString& name)
+{
+ d->name = name;
+}
+
+/*!
+ Through this function, arguments to the update operation can be specified
+ to the update operation.
+*/
+void UpdateOperation::setArguments(const QStringList& args)
+{
+ d->args = args;
+}
+
+/*!
+ Sets the Application for this operation.
+ This may be used by some operations
+*/
+void UpdateOperation::setApplication( Application* application )
+{
+ d->application = application;
+}
+
+/*!
+ Returns the last set function arguments.
+*/
+QStringList UpdateOperation::arguments() const
+{
+ return d->args;
+}
+
+/*!
+ Returns error details in case performOperation() failed.
+*/
+QString UpdateOperation::errorString() const
+{
+ return d->errorString;
+}
+
+/*!
+ * Can be used by subclasses to report more detailed error codes (optional).
+ * To check if an operation was successful, use the return value of performOperation().
+ */
+int UpdateOperation::error() const
+{
+ return d->error;
+}
+
+/*!
+ * Used by subclasses to set the error string.
+ */
+void UpdateOperation::setErrorString( const QString& str )
+{
+ d->errorString = str;
+}
+
+/*!
+ * Used by subclasses to set the error code.
+ */
+void UpdateOperation::setError( int error, const QString& errorString )
+{
+ d->error = error;
+ if( !errorString.isNull() )
+ d->errorString = errorString;
+}
+
+/*!
+ Clears the previously set argument list and application
+*/
+void UpdateOperation::clear()
+{
+ d->args.clear();
+ d->application = 0;
+}
+
+QStringList UpdateOperation::filesForDelayedDeletion() const
+{
+ return d->delayedDeletionFiles;
+}
+
+/*!
+ Registers a file to be deleted later, once the application was restarted
+ (and the file isn't used anymore for sure).
+ @param files the files to be registered
+*/
+void UpdateOperation::registerForDelayedDeletion( const QStringList& files )
+{
+ d->delayedDeletionFiles << files;
+}
+
+/*!
+ Tries to delete \a file. If \a file can't be deleted, it gets registered for delayed deletion.
+*/
+bool UpdateOperation::deleteFileNowOrLater( const QString& file, QString* errorString )
+{
+ if( file.isEmpty() || QFile::remove( file ) )
+ return true;
+
+ if( !QFile::exists( file ) )
+ return true;
+
+ const QString backup = backupFileName( file );
+ QFile f( file );
+ if( !f.rename( backup ) )
+ {
+ if ( errorString )
+ *errorString = f.errorString();
+ return false;
+ }
+ registerForDelayedDeletion( QStringList( backup ) );
+ return true;
+}
+
+/*!
+ Returns a pointer to the current Application
+*/
+Application* UpdateOperation::application() const
+{
+ return d->application;
+}
+
+/*!
+ \fn virtual void KDUpdater::UpdateOperation::backup() = 0;
+
+ Subclasses must implement this function to backup any data before performing the action.
+*/
+
+/*!
+ \fn virtual bool KDUpdater::UpdateOperation::performOperation() = 0;
+
+ Subclasses must implement this function to perform the update operation
+*/
+
+/*!
+ \fn virtual bool KDUpdater::UpdateOperation::undoOperation() = 0;
+
+ Subclasses must implement this function to perform the reverse of the operation.
+*/
+
+/*!
+ \fn virtual bool KDUpdater::UpdateOperation::testOperation() = 0;
+
+ Subclasses must implement this function to perform the test operation.
+*/
+
+/*!
+ \fn virtual bool KDUpdater::UpdateOperation::clone() = 0;
+
+ Subclasses must implement this function to clone the current operation.
+*/
+
+/*!
+ Saves this UpdateOperation in XML. You can override this method to store your own extra-data.
+ The default implementation is taking care of arguments and values set via setValue.
+*/
+QDomDocument UpdateOperation::toXml() const
+{
+ QDomDocument doc;
+ QDomElement root = doc.createElement( QLatin1String("operation") );
+ doc.appendChild( root );
+ QDomElement args = doc.createElement( QLatin1String("arguments") );
+ Q_FOREACH( const QString &s, arguments() ) {
+ QDomElement arg = doc.createElement( QLatin1String("argument") );
+ arg.appendChild( doc.createTextNode(s) );
+ args.appendChild( arg );
+ }
+ root.appendChild( args );
+ if( d->values.isEmpty() )
+ return doc;
+
+ // append all values set with setValue
+ QDomElement values = doc.createElement( QLatin1String( "values" ) );
+ for( QVariantMap::const_iterator it = d->values.begin(); it != d->values.end(); ++it )
+ {
+ QDomElement value = doc.createElement( QLatin1String( "value" ) );
+ const QVariant& variant = it.value();
+ value.setAttribute( QLatin1String( "name" ), it.key() );
+ value.setAttribute( QLatin1String( "type" ), QLatin1String( QVariant::typeToName( variant.type() ) ) );
+
+ if( variant.type() != QVariant::List && variant.type() != QVariant::StringList && qVariantCanConvert< QString >( variant ) )
+ {
+ // it can convert to string? great!
+ value.appendChild( doc.createTextNode( variant.toString() ) );
+ }
+ else
+ {
+ // no? then we have to go the hard way...
+ QByteArray data;
+ QDataStream stream( &data, QIODevice::WriteOnly );
+ stream << variant;
+ value.appendChild( doc.createTextNode( QLatin1String( data.toBase64().data() ) ) );
+ }
+ values.appendChild( value );
+ }
+ root.appendChild( values );
+ return doc;
+}
+
+/*!
+ Restores UpdateOperation's arguments and values from the XML document \a doc.
+ Returns true on success, otherwise false.
+*/
+bool UpdateOperation::fromXml( const QDomDocument &doc )
+{
+ QStringList args;
+ const QDomElement root = doc.documentElement();
+ const QDomElement argsElem = root.firstChildElement( QLatin1String("arguments") );
+ Q_ASSERT( ! argsElem.isNull() );
+ for( QDomNode n = argsElem.firstChild(); ! n.isNull(); n = n.nextSibling() ) {
+ const QDomElement e = n.toElement();
+ if( !e.isNull() && e.tagName() == QLatin1String("argument") )
+ args << e.text();
+ }
+ setArguments(args);
+
+ d->values.clear();
+ const QDomElement values = root.firstChildElement( QLatin1String( "values" ) );
+ for( QDomNode n = values.firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ const QDomElement v = n.toElement();
+ if( v.isNull() || v.tagName() != QLatin1String( "value" ) )
+ continue;
+
+ const QString name = v.attribute( QLatin1String( "name" ) );
+ const QString type = v.attribute( QLatin1String( "type" ) );
+ const QString value = v.text();
+
+ const QVariant::Type t = QVariant::nameToType( type.toLatin1().data() );
+ QVariant var = qVariantFromValue( value );
+ if( t == QVariant::List || t == QVariant::StringList || !var.convert( t ) )
+ {
+ QDataStream stream( QByteArray::fromBase64( value.toLatin1() ) );
+ stream >> var;
+ }
+
+ d->values[ name ] = var;
+ }
+
+ return true;
+}
+
+/*!
+ Restores UpdateOperation's arguments and values from the XML document at path \a xml.
+ Returns true on success, otherwise false.
+ \overload
+*/
+bool UpdateOperation::fromXml( const QString &xml )
+{
+ QDomDocument doc;
+ QString errorMsg;
+ int errorLine;
+ int errorColumn;
+ if ( ! doc.setContent( xml, &errorMsg, &errorLine, &errorColumn ) ) {
+ qWarning() << "Error parsing xml error=" << errorMsg << "line=" << errorLine << "column=" << errorColumn;
+ return false;
+ }
+ return fromXml(doc);
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateoperation.h b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateoperation.h
new file mode 100644
index 000000000..53111d23a
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateoperation.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef KD_UPDATER_UPDATE_OPERATION_H
+#define KD_UPDATER_UPDATE_OPERATION_H
+
+#include "kdupdater.h"
+
+#include <QCoreApplication>
+#include <QStringList>
+#include <QVariant>
+#include <QDomDocument>
+
+namespace KDUpdater
+{
+ class Application;
+
+ class KDTOOLS_UPDATER_EXPORT UpdateOperation
+ {
+ Q_DECLARE_TR_FUNCTIONS(UpdateOperation)
+
+ public:
+ enum Error {
+ NoError=0,
+ InvalidArguments=1,
+ UserDefinedError=128
+ };
+
+ UpdateOperation();
+ virtual ~UpdateOperation();
+
+ QString name() const;
+ QString operationCommand() const;
+
+ bool hasValue( const QString& name ) const;
+ void clearValue( const QString& name );
+ QVariant value( const QString& name ) const;
+ void setValue( const QString& name, const QVariant &value );
+
+ void setArguments(const QStringList& args);
+ void setApplication( Application* application );
+ QStringList arguments() const;
+ void clear();
+ QString errorString() const;
+ int error() const;
+ QStringList filesForDelayedDeletion() const;
+
+ virtual void backup() = 0;
+ virtual bool performOperation() = 0;
+ virtual bool undoOperation() = 0;
+ virtual bool testOperation() = 0;
+ virtual UpdateOperation* clone() const = 0;
+
+ virtual QDomDocument toXml() const;
+ virtual bool fromXml( const QString &xml );
+ virtual bool fromXml( const QDomDocument &doc );
+
+ protected:
+ void setName(const QString& name);
+ Application* application() const;
+ void setErrorString( const QString& errorString );
+ void setError( int error, const QString& errorString = QString() );
+ void registerForDelayedDeletion( const QStringList& files );
+ bool deleteFileNowOrLater( const QString& file, QString* errorString=0 );
+
+ private:
+ struct UpdateOperationData;
+ UpdateOperationData* d;
+ };
+};
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateoperationfactory.cpp b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateoperationfactory.cpp
new file mode 100644
index 000000000..076af5273
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateoperationfactory.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdupdaterupdateoperationfactory.h"
+#include "kdupdaterupdateoperations.h"
+
+#include <QHash>
+
+/*!
+ \ingroup kdupdater
+ \class KDUpdater::UpdateOperationFactory kdupdaterupdateoperationfactory.h KDUpdaterUpdateOperationFactory
+ \brief Factory for \ref KDUpdater::UpdateOperation
+
+ This class acts as a factory for \ref KDUpdater::UpdateOperation. You can register
+ one or more update operations with this factory and query operations based on their name.
+
+ This class follows the singleton design pattern. Only one instance of this class can
+ be created and its reference can be fetched from the \ref instance() method.
+*/
+
+/*!
+ \fn KDUpdater::UpdateOperationFactory::registerUpdateOperation( const QString& name )
+
+ Registers T as new UpdateOperation with \a name. When create() is called with that \a name,
+ T is constructed using its default constructor.
+*/
+
+using namespace KDUpdater;
+
+struct UpdateOperationFactory::UpdateOperationFactoryData
+{
+};
+
+/*!
+ Returns the UpdateOperationFactory instance. The instance is created if needed.
+*/
+UpdateOperationFactory& UpdateOperationFactory::instance()
+{
+ static UpdateOperationFactory theFactory;
+ return theFactory;
+}
+
+/*!
+ Constructor
+*/
+UpdateOperationFactory::UpdateOperationFactory()
+ : d ( new UpdateOperationFactoryData )
+{
+ // Register the default update operation set
+ registerUpdateOperation< CopyOperation >( QLatin1String( "Copy" ) );
+ registerUpdateOperation< MoveOperation >( QLatin1String( "Move" ) );
+ registerUpdateOperation< DeleteOperation >( QLatin1String( "Delete" ) );
+ registerUpdateOperation< MkdirOperation >( QLatin1String( "Mkdir" ) );
+ registerUpdateOperation< RmdirOperation >( QLatin1String( "Rmdir" ) );
+ registerUpdateOperation< AppendFileOperation >( QLatin1String( "AppendFile" ) );
+ registerUpdateOperation< PrependFileOperation >( QLatin1String( "PrependFile" ) );
+ registerUpdateOperation< ExecuteOperation >( QLatin1String( "Execute" ) );
+ registerUpdateOperation< UpdatePackageOperation >( QLatin1String( "UpdatePackage" ) );
+ registerUpdateOperation< UpdateCompatOperation >( QLatin1String( "UpdateCompat" ) );
+}
+
+UpdateOperationFactory::~UpdateOperationFactory()
+{
+}
+
+/*!
+ Returns the number of update operations in the factory.
+*/
+int UpdateOperationFactory::updateOperationCount() const
+{
+ return productCount();
+}
+
+/*!
+ Returns a list containing the names of all available UpdateOperations.
+*/
+QStringList UpdateOperationFactory::availableUpdateOperations() const
+{
+ return availableProducts();
+}
+
+/*
+ Unregisters the update operation previously registered with \a name.
+*/
+void UpdateOperationFactory::unregisterUpdateOperation( const QString& name )
+{
+ unregisterProduct( name );
+}
+
+/*!
+ Registers \a create to be a factory function to create an UpdateOperation with \a name.
+ \sa registerUpdateOperation
+*/
+void UpdateOperationFactory::registerUpdateOperationFactory( const QString& name, UpdateOperationFactoryFunction create )
+{
+ registerProductionFunction( name, create );
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateoperationfactory.h b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateoperationfactory.h
new file mode 100644
index 000000000..d42a871c3
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateoperationfactory.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef KD_UPDATER_UPDATE_OPERATION_FACTORY_H
+#define KD_UPDATER_UPDATE_OPERATION_FACTORY_H
+
+#include <KDToolsCore/kdgenericfactory.h>
+
+#include "kdupdater.h"
+#include <KDToolsCore/pimpl_ptr.h>
+
+namespace KDUpdater
+{
+ class UpdateOperation;
+
+ typedef KDGenericFactory< UpdateOperation >::FactoryFunction UpdateOperationFactoryFunction;
+
+ class KDTOOLS_UPDATER_EXPORT UpdateOperationFactory : public KDGenericFactory< UpdateOperation >
+ {
+ Q_DISABLE_COPY( UpdateOperationFactory )
+ public:
+ static UpdateOperationFactory& instance();
+ ~UpdateOperationFactory();
+
+ template< class T >
+ void registerUpdateOperation( const QString& name )
+ {
+ registerProduct< T >( name );
+ }
+ void registerUpdateOperationFactory( const QString& name, UpdateOperationFactoryFunction create );
+
+ void unregisterUpdateOperation( const QString& name );
+
+ int updateOperationCount() const;
+ QStringList availableUpdateOperations() const;
+
+ protected:
+ UpdateOperationFactory();
+
+ private:
+ struct UpdateOperationFactoryData;
+ kdtools::pimpl_ptr<UpdateOperationFactoryData> d;
+ };
+}
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateoperations.cpp b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateoperations.cpp
new file mode 100644
index 000000000..a1486d34d
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateoperations.cpp
@@ -0,0 +1,1120 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdupdaterupdateoperations.h"
+#include "kdupdaterapplication.h"
+#include "kdupdaterpackagesinfo.h"
+#include "environment.h"
+
+#include <QFile>
+#include <QDir>
+#include <QDirIterator>
+#include <QProcess>
+#include <QTextStream>
+#include <QDebug>
+#include <QTemporaryFile>
+
+
+#include <cerrno>
+
+#define SUPPORT_DETACHED_PROCESS_EXECUTION
+
+#ifdef SUPPORT_DETACHED_PROCESS_EXECUTION
+#ifdef Q_WS_WIN
+#include <windows.h>
+#endif
+#endif
+
+using namespace KDUpdater;
+
+static bool removeDirectory( const QString& path, QString* errorString )
+{
+ Q_ASSERT( errorString );
+ const QFileInfoList entries = QDir( path ).entryInfoList( QDir::NoDotAndDotDot | QDir::AllEntries | QDir::Hidden );
+ for( QFileInfoList::const_iterator it = entries.constBegin(); it != entries.constEnd(); ++it )
+ {
+ if( it->isDir() && !it->isSymLink() )
+ {
+ removeDirectory( it->filePath(), errorString );
+ }
+ else
+ {
+ QFile f( it->filePath() );
+ if( !f.remove() )
+ return false;
+ }
+ }
+
+ errno = 0;
+ const bool success = QDir().rmdir( path );
+ if ( errno )
+ *errorString = QLatin1String( strerror(errno) );
+ return success;
+}
+/*
+ * \internal
+ * Returns a filename for a temporary file based on \a templateName
+ */
+static QString backupFileName( const QString& templateName = QString() )
+{
+ QTemporaryFile file( templateName );
+ file.open();
+ const QString name = file.fileName();
+ file.close();
+ file.remove();
+ return name;
+}
+
+////////////////////////////////////////////////////////////////////////////
+// KDUpdater::CopyOperation
+////////////////////////////////////////////////////////////////////////////
+
+CopyOperation::CopyOperation()
+{
+ setName(QLatin1String( "Copy" ));
+}
+
+CopyOperation::~CopyOperation()
+{
+ deleteFileNowOrLater( value( QLatin1String( "backupOfExistingDestination" ) ).toString() );
+}
+
+void CopyOperation::backup()
+{
+ const QString dest = arguments().last();
+ if( !QFile::exists( dest ) )
+ {
+ clearValue( QLatin1String( "backupOfExistingDestination" ) );
+ return;
+ }
+
+ setValue( QLatin1String( "backupOfExistingDestination" ), backupFileName( dest ) );
+
+ // race condition: The backup file could get created
+ // by another process right now. But this is the same
+ // in QFile::copy...
+ const bool success = QFile::rename( dest, value( QLatin1String( "backupOfExistingDestination" ) ).toString() );
+ if(!success)
+ setError( UserDefinedError, tr("Could not backup file %1").arg(dest) );
+}
+
+bool CopyOperation::performOperation()
+{
+ // We need two args to complete the copy operation.
+ // First arg provides the complete file name of source
+ // Second arg provides the complete file name of dest
+ QStringList args = this->arguments();
+ if( args.count() != 2 ) {
+ setError( InvalidArguments );
+ setErrorString( tr("Invalid arguments: %1 arguments given, 2 expected.").arg( args.count() ) );
+ return false;
+ }
+ QString source = args.first();
+ QString dest = args.last();
+
+ // If destination file exists, then we cannot use QFile::copy()
+ // because it does not overwrite an existing file. So we remove
+ // the destination file.
+ if( QFile::exists(dest) )
+ {
+ QFile file( dest );
+ if( !file.remove() ) {
+ setError( UserDefinedError );
+ setErrorString( tr("Could not remove destination file %1: %2.").arg( dest, file.errorString() ) );
+ return false;
+ }
+ }
+
+ QFile file( source );
+ const bool copied = file.copy( dest );
+ if ( !copied ) {
+ setError( UserDefinedError );
+ setErrorString( tr("Could not copy %1 to %2: %3.").arg( source, dest, file.errorString() ) );
+ }
+ return copied;
+}
+
+bool CopyOperation::undoOperation()
+{
+ const QString dest = arguments().last();
+
+ QFile destF( dest );
+ // first remove the dest
+ if( !destF.remove() )
+ {
+ setError( UserDefinedError, tr("Could not delete file %1: %2").arg(dest, destF.errorString()) );
+ return false;
+ }
+
+ // no backup was done:
+ // the copy destination file wasn't existing yet - that's no error
+ if( !hasValue( QLatin1String( "backupOfExistingDestination" ) ) )
+ return true;
+
+ QFile backupF( value( QLatin1String( "backupOfExistingDestination" ) ).toString() );
+ // otherwise we have to copy the backup back:
+ const bool success = backupF.rename( dest );
+ if(!success) {
+ setError( UserDefinedError, tr("Could not restore backup file into %1: %2").arg(dest, backupF.errorString()) );
+ }
+ return success;
+}
+
+/*!
+ \reimp
+ */
+QDomDocument CopyOperation::toXml() const
+{
+ // we don't want to save the backupOfExistingDestination
+ if( !hasValue( QLatin1String( "backupOfExistingDestination" ) ) )
+ return UpdateOperation::toXml();
+
+ CopyOperation* const me = const_cast< CopyOperation* >( this );
+
+ const QVariant v = value( QLatin1String( "backupOfExistingDestination" ) );
+ me->clearValue( QLatin1String( "backupOfExistingDestination" ) );
+ const QDomDocument xml = UpdateOperation::toXml();
+ me->setValue( QLatin1String( "backupOfExistingDestination" ), v );
+ return xml;
+}
+
+bool CopyOperation::testOperation()
+{
+ // TODO
+ return true;
+}
+
+CopyOperation* CopyOperation::clone() const
+{
+ return new CopyOperation();
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// KDUpdater::MoveOperation
+////////////////////////////////////////////////////////////////////////////
+
+MoveOperation::MoveOperation()
+{
+ setName(QLatin1String( "Move" ));
+}
+
+MoveOperation::~MoveOperation()
+{
+ deleteFileNowOrLater( value( QLatin1String( "backupOfExistingDestination" ) ).toString() );
+}
+
+void MoveOperation::backup()
+{
+ const QString dest = arguments().last();
+ if( !QFile::exists( dest ) )
+ {
+ clearValue( QLatin1String( "backupOfExistingDestination" ) );
+ return;
+ }
+
+ setValue( QLatin1String( "backupOfExistingDestination" ), backupFileName( dest ) );
+
+ // race condition: The backup file could get created
+ // by another process right now. But this is the same
+ // in QFile::copy...
+ const bool success = QFile::rename( dest, value( QLatin1String( "backupOfExistingDestination" ) ).toString() );
+ if(!success)
+ setError( UserDefinedError, tr("Could not backup file %1").arg(dest) );
+}
+
+bool MoveOperation::performOperation()
+{
+ // We need two args to complete the copy operation.
+ // First arg provides the complete file name of source
+ // Second arg provides the complete file name of dest
+ QStringList args = this->arguments();
+ if( args.count() != 2 ) {
+ setError( InvalidArguments );
+ setErrorString( tr("Invalid arguments: %1 arguments given, 2 expected.").arg( args.count() ) );
+ return false;
+ }
+
+ QString source = args.first();
+ QString dest = args.last();
+
+ // If destination file exists, then we cannot use QFile::copy()
+ // because it does not overwrite an existing file. So we remove
+ // the destination file.
+ if( QFile::exists(dest) )
+ {
+ QFile file( dest );
+ if( !file.remove(dest) ) {
+ setError( UserDefinedError );
+ setErrorString( tr("Could not remove destination file %1: %2.").arg( dest, file.errorString() ) );
+ return false;
+ }
+ }
+
+ // Copy source to destination.
+ QFile file( source );
+ const bool copied = file.copy( source, dest );
+ if ( !copied ) {
+ setError( UserDefinedError );
+ setErrorString( tr("Could not copy %1 to %2: %3.").arg( source, dest, file.errorString() ) );
+ return false;
+ }
+
+ return deleteFileNowOrLater( source );
+}
+
+bool MoveOperation::undoOperation()
+{
+ const QStringList args = arguments();
+ const QString& source = args.first();
+ const QString& dest = args.last();
+
+ // first: copy back the destination to source
+ QFile destF( dest );
+ if( !destF.copy( source ) )
+ {
+ setError( UserDefinedError, tr("Cannot copy %1 to %2: %3").arg( dest, source, destF.errorString() ) );
+ return false;
+ }
+
+ // second: delete the move destination
+ if( !deleteFileNowOrLater( dest ) )
+ {
+ setError( UserDefinedError, tr( "Cannot remove file %1" ) );
+ return false;
+ }
+
+ // no backup was done:
+ // the move destination file wasn't existing yet - that's no error
+ if( !hasValue( QLatin1String( "backupOfExistingDestination" ) ) )
+ return true;
+
+ // otherwise we have to copy the backup back:
+ QFile backupF( value( QLatin1String( "backupOfExistingDestination" ) ).toString() );
+ const bool success = backupF.rename( dest );
+ if(!success)
+ setError( UserDefinedError, tr("Cannot restore backup file for %1: %2").arg(dest, backupF.errorString()) );
+
+ return success;
+}
+
+bool MoveOperation::testOperation()
+{
+ // TODO
+ return true;
+}
+
+MoveOperation* MoveOperation::clone() const
+{
+ return new MoveOperation;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// KDUpdater::DeleteOperation
+////////////////////////////////////////////////////////////////////////////
+
+DeleteOperation::DeleteOperation()
+{
+ setName(QLatin1String( "Delete" ));
+}
+
+DeleteOperation::~DeleteOperation()
+{
+ deleteFileNowOrLater( value( QLatin1String( "backupOfExistingFile" ) ).toString() );
+}
+
+void DeleteOperation::backup()
+{
+ const QString fileName = arguments().first();
+ setValue( QLatin1String( "backupOfExistingFile" ), backupFileName( fileName ) );
+ QFile file( fileName );
+ const bool success = file.copy( value( QLatin1String( "backupOfExistingFile" ) ).toString() );
+ if(!success)
+ setError( UserDefinedError, tr("Cannot create backup of %1: %2").arg(fileName, file.errorString()) );
+}
+
+bool DeleteOperation::performOperation()
+{
+ // Requires only one parameter. That is the name of
+ // the file to remove.
+ QStringList args = this->arguments();
+ if( args.count() != 1 ) {
+ setError( InvalidArguments );
+ setErrorString( tr("Invalid arguments: %1 arguments given, 1 expected.").arg( args.count() ) );
+ return false;
+ }
+
+ const QString fName = args.first();
+ return deleteFileNowOrLater( fName );
+}
+
+bool DeleteOperation::undoOperation()
+{
+ if( !hasValue( QLatin1String( "backupOfExistingFile" ) ) )
+ return true;
+
+ const QString fileName = arguments().first();
+ QFile backupF( value( QLatin1String( "backupOfExistingFile" ) ).toString() );
+ const bool success = backupF.copy( fileName ) && deleteFileNowOrLater( backupF.fileName() );
+ if(!success)
+ setError( UserDefinedError, tr("Cannot restore backup file for %1: %2").arg(fileName, backupF.errorString()) );
+
+ return success;
+}
+
+bool DeleteOperation::testOperation()
+{
+ // TODO
+ return true;
+}
+
+DeleteOperation* DeleteOperation::clone() const
+{
+ return new DeleteOperation;
+}
+
+/*!
+ \reimp
+ */
+QDomDocument DeleteOperation::toXml() const
+{
+ // we don't want to save the backupOfExistingFile
+ if( !hasValue( QLatin1String( "backupOfExistingFile" ) ) )
+ return UpdateOperation::toXml();
+
+ DeleteOperation* const me = const_cast< DeleteOperation* >( this );
+
+ const QVariant v = value( QLatin1String( "backupOfExistingFile" ) );
+ me->clearValue( QLatin1String( "backupOfExistingFile" ) );
+ const QDomDocument xml = UpdateOperation::toXml();
+ me->setValue( QLatin1String( "backupOfExistingFile" ), v );
+ return xml;
+}
+
+////////////////////////////////////////////////////////////////////////////
+// KDUpdater::MkdirOperation
+////////////////////////////////////////////////////////////////////////////
+
+MkdirOperation::MkdirOperation()
+{
+ setName(QLatin1String( "Mkdir" ));
+}
+
+MkdirOperation::~MkdirOperation()
+{
+
+}
+
+void MkdirOperation::backup()
+{
+ static const QRegExp re( QLatin1String( "\\\\|/" ) );
+ static const QLatin1String sep( "/" );
+
+ QString path = arguments().first();
+ path.replace( re, sep );
+
+ QDir createdDir = QDir::root();
+
+ // find out, which part of the path is the first one we actually need to create
+ int end = 0;
+ while( true )
+ {
+ QString p = path.section( sep, 0, ++end );
+ createdDir = QDir( p );
+ if( !createdDir.exists() )
+ break;
+ else if( p == path )
+ {
+ // everything did already exist -> nothing to do for us (nothing to revert then, either)
+ createdDir = QDir::root();
+ break;
+ }
+ }
+
+ setValue( QLatin1String( "createddir" ), createdDir.absolutePath() );
+}
+
+bool MkdirOperation::performOperation()
+{
+ // Requires only one parameter. That is the name of
+ // the file to remove.
+ QStringList args = this->arguments();
+ if( args.count() != 1 ) {
+ setError( InvalidArguments );
+ setErrorString( tr("Invalid arguments: %1 arguments given, 1 expected.").arg( args.count() ) );
+ return false;
+ }
+ QString dirName = args.first();
+ const bool created = QDir::root().mkpath(dirName);
+ if ( !created ) {
+ setError( UserDefinedError );
+ setErrorString( tr("Could not create folder %1: Unknown error.").arg( dirName ) );
+ }
+ return created;
+}
+
+bool MkdirOperation::undoOperation()
+{
+ Q_ASSERT( arguments().count() == 1 );
+ QString dirName = arguments().first();
+
+ const QDir createdDir = QDir( value( QLatin1String( "createddir" ) ).toString() );
+ const bool forceremoval = QVariant( value( QLatin1String( "forceremoval" ) ) ).toBool();
+
+ if( createdDir == QDir::root() )
+ return true;
+
+ QString errorString;
+ if( forceremoval )
+ {
+ return removeDirectory( createdDir.path(), &errorString );
+ }
+
+ // even remove some hidden, OS-created files in there
+#if defined Q_WS_MAC
+ QFile::remove( createdDir.path() + QLatin1String( "/.DS_Store" ) );
+#elif defined Q_WS_WIN
+ QFile::remove( createdDir.path() + QLatin1String( "/Thumbs.db" ) );
+#endif
+
+ errno = 0;
+ const bool result = QDir::root().rmdir( createdDir.path() );
+ if ( !result ) {
+ if ( errorString.isEmpty() )
+ setError( UserDefinedError, tr("Cannot remove directory %1: %2").arg( createdDir.path(), errorString ) );
+ else
+ setError( UserDefinedError, tr("Cannot remove directory %1: %2").arg( createdDir.path(), QLatin1String(strerror(errno)) ) );
+ }
+ return result;
+}
+
+bool KDUpdater::MkdirOperation::testOperation()
+{
+ // TODO
+ return true;
+}
+
+MkdirOperation* MkdirOperation::clone() const
+{
+ return new MkdirOperation;
+}
+
+////////////////////////////////////////////////////////////////////////////
+// KDUpdater::RmdirOperation
+////////////////////////////////////////////////////////////////////////////
+
+RmdirOperation::RmdirOperation()
+{
+ setValue( QLatin1String( "removed" ), false );
+ setName(QLatin1String( "Rmdir" ));
+}
+
+RmdirOperation::~RmdirOperation()
+{
+
+}
+
+void RmdirOperation::backup()
+{
+ // nothing to backup - rollback will just create the directory
+}
+
+bool RmdirOperation::performOperation()
+{
+ // Requires only one parameter. That is the name of
+ // the file to remove.
+ QStringList args = this->arguments();
+ if( args.count() != 1 ) {
+ setError( InvalidArguments );
+ setErrorString( tr("Invalid arguments: %1 arguments given, 1 expected.").arg( args.count() ) );
+ return false;
+ }
+
+ QString dirName = args.first();
+ QDir dir( dirName );
+ if( !dir.exists() ) {
+ setError( UserDefinedError );
+ setErrorString( tr("Could not remove folder %1: The folder does not exist.").arg( dirName ) );
+ return false;
+ }
+
+ errno = 0;
+ const bool removed = dir.rmdir( dirName );
+ setValue( QLatin1String( "removed" ), removed );
+ if ( !removed ) {
+ setError( UserDefinedError );
+ setErrorString( tr("Could not remove folder %1: %2.").arg( dirName, QLatin1String(strerror(errno)) ) );
+ }
+ return removed;
+}
+
+bool RmdirOperation::undoOperation()
+{
+ if( !value( QLatin1String( "removed" ) ).toBool() )
+ return true;
+
+ const QFileInfo fi( arguments().first() );
+ errno = 0;
+ const bool success = fi.dir().mkdir( fi.fileName() );
+ if(!success)
+ setError( UserDefinedError, tr("Cannot recreate directory %1: %2").arg( fi.fileName(), QLatin1String(strerror(errno)) ) );
+
+ return success;
+}
+
+bool RmdirOperation::testOperation()
+{
+ // TODO
+ return true;
+}
+
+RmdirOperation* RmdirOperation::clone() const
+{
+ return new RmdirOperation;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// KDUpdater::AppendFileOperation
+////////////////////////////////////////////////////////////////////////////
+
+AppendFileOperation::AppendFileOperation()
+{
+ setName(QLatin1String( "AppendFile" ));
+}
+
+AppendFileOperation::~AppendFileOperation()
+{
+
+}
+
+void AppendFileOperation::backup()
+{
+ const QString filename = arguments().first();
+
+ QFile file( filename );
+ if( !file.exists() )
+ return; // nothing to backup
+
+ setValue( QLatin1String( "backupOfFile" ), backupFileName( filename ) );
+ if( !file.copy( value( QLatin1String( "backupOfFile" ) ).toString() ) )
+ {
+ setError( UserDefinedError, tr("Cannot backup file %1: %2").arg(filename, file.errorString()) );
+ clearValue( QLatin1String( "backupOfFile" ) );
+ }
+}
+
+bool AppendFileOperation::performOperation()
+{
+ // This operation takes two arguments. First argument is the name
+ // of the file into which a text has to be appended. Second argument
+ // is the text to append.
+ QStringList args = this->arguments();
+ if( args.count() != 2 ) {
+ setError( InvalidArguments );
+ setErrorString( tr("Invalid arguments: %1 arguments given, 2 expected.").arg( args.count() ) );
+ return false;
+ }
+
+ QString fName = args.first();
+ QString text = args.last();
+
+ QFile file(fName);
+ if( !file.open(QFile::Append) )
+ {
+ // first we rename the file, then we copy it to the real target and open the copy - the renamed original is then marked for deletion
+ const QString newName = backupFileName( fName );
+ if( !QFile::rename( fName, newName ) && QFile::copy( newName, fName ) && file.open( QFile::Append ) )
+ {
+ QFile::rename( newName, fName );
+ setError( UserDefinedError );
+ setErrorString( tr("Could not open file %1 for writing: %2.").arg( file.fileName(), file.errorString() ) );
+ return false;
+ }
+ deleteFileNowOrLater( newName );
+ }
+
+ QTextStream ts(&file);
+ ts << text;
+ file.close();
+
+ return true;
+}
+
+bool AppendFileOperation::undoOperation()
+{
+ // backupOfFile being empty -> file didn't exist before -> no error
+ const QString filename = arguments().first();
+ const QString backupOfFile = value( QLatin1String( "backupOfFile" ) ).toString();
+ if( !backupOfFile.isEmpty() && !QFile::exists( backupOfFile ) )
+ {
+ setError( UserDefinedError, tr("Cannot find backup file for %1").arg(filename) );
+ return false;
+ }
+
+ const bool removed = deleteFileNowOrLater( filename );
+ if ( !removed ) {
+ setError( UserDefinedError, tr("Could not restore backup file for %1.").arg( filename ) );
+ return false;
+ }
+
+ // got deleted? We might be done, if it didn't exist before
+ if( backupOfFile.isEmpty() )
+ return true;
+
+ QFile backupFile( backupOfFile );
+ const bool success = backupFile.rename( filename );
+ if ( !success )
+ setError( UserDefinedError, tr("Could not restore backup file for %1: %2").arg(filename, backupFile.errorString()) );
+ return success;
+}
+
+bool AppendFileOperation::testOperation()
+{
+ // TODO
+ return true;
+}
+
+AppendFileOperation* AppendFileOperation::clone() const
+{
+ return new AppendFileOperation;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// KDUpdater::PrependFileOperation
+////////////////////////////////////////////////////////////////////////////
+
+PrependFileOperation::PrependFileOperation()
+{
+ setName(QLatin1String( "PrependFile" ));
+}
+
+PrependFileOperation::~PrependFileOperation()
+{
+
+}
+
+void PrependFileOperation::backup()
+{
+ const QString filename = arguments().first();
+
+ QFile file( filename );
+ if( !file.exists() )
+ return; // nothing to backup
+
+ setValue( QLatin1String( "backupOfFile" ), backupFileName( filename ) );
+ if( !file.copy( value( QLatin1String( "backupOfFile" ) ).toString() ) )
+ {
+ setError( UserDefinedError, tr("Cannot backup file %1: %2").arg(filename, file.errorString()) );
+ clearValue( QLatin1String( "backupOfFile" ) );
+ }
+}
+
+bool PrependFileOperation::performOperation()
+{
+ // This operation takes two arguments. First argument is the name
+ // of the file into which a text has to be appended. Second argument
+ // is the text to append.
+ QStringList args = this->arguments();
+ if( args.count() != 2 ) {\
+ setError( InvalidArguments );
+ setErrorString( tr("Invalid arguments: %1 arguments given, 2 expected.").arg( args.count() ) );
+ return false;
+ }
+
+ QString fName = args.first();
+ QString text = args.last();
+
+ // Load the file first.
+ QFile file(fName);
+ if( !file.open(QFile::ReadOnly) ) {
+ setError( UserDefinedError );
+ setErrorString( tr("Could not open file %1 for reading: %2.").arg( file.fileName(), file.errorString() ) );
+ return false;
+ }
+ QString fContents( QLatin1String( file.readAll() ) );
+ file.close();
+
+ // Prepend text to the file text
+ fContents = text + fContents;
+
+ // Now re-open the file in write only mode.
+ if( !file.open(QFile::WriteOnly) ) {
+ // first we rename the file, then we copy it to the real target and open the copy - the renamed original is then marked for deletion
+ const QString newName = backupFileName( fName );
+ if( !QFile::rename( fName, newName ) && QFile::copy( newName, fName ) && file.open( QFile::WriteOnly ) )
+ {
+ QFile::rename( newName, fName );
+ setError( UserDefinedError );
+ setErrorString( tr("Could not open file %1 for writing: %2.").arg( file.fileName(), file.errorString() ) );
+ return false;
+ }
+ deleteFileNowOrLater( newName );
+ }
+ QTextStream ts(&file);
+ ts << fContents;
+ file.close();
+
+ return true;
+}
+
+bool PrependFileOperation::undoOperation()
+{
+ // bockupOfFile being empty -> file didn't exist before -> no error
+ const QString filename = arguments().first();
+ const QString backupOfFile = value( QLatin1String( "backupOfFile" ) ).toString();
+ if( !backupOfFile.isEmpty() && !QFile::exists( backupOfFile ) )
+ {
+ setError( UserDefinedError, tr("Cannot find backup file for %1").arg(filename) );
+ return false;
+ }
+
+ if( !deleteFileNowOrLater( filename ) )
+ {
+ setError( UserDefinedError, tr("Cannot restore backup file for %1").arg( filename ) );
+ return false;
+ }
+
+ // got deleted? We might be done, if it didn't exist before
+ if( backupOfFile.isEmpty() )
+ return true;
+
+ QFile backupF( backupOfFile );
+ const bool success = backupF.rename( filename );
+ if(!success)
+ setError( UserDefinedError, tr("Cannot restore backup file for %1: %2").arg(filename, backupF.errorString()) );
+
+ return success;
+}
+
+bool PrependFileOperation::testOperation()
+{
+ // TODO
+ return true;
+}
+
+PrependFileOperation* PrependFileOperation::clone() const
+{
+ return new PrependFileOperation;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// KDUpdater::ExecuteOperation
+////////////////////////////////////////////////////////////////////////////
+
+ExecuteOperation::ExecuteOperation()
+ : QObject()
+{
+ setName(QLatin1String( "Execute" ));
+}
+
+ExecuteOperation::~ExecuteOperation()
+{
+
+}
+
+void ExecuteOperation::backup()
+{
+ // this is not possible, since the process can do whatever...
+}
+
+#if defined( SUPPORT_DETACHED_PROCESS_EXECUTION ) && defined( Q_WS_WIN )
+// stolen 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;
+}
+#endif
+
+bool ExecuteOperation::performOperation()
+{
+ // This operation receives only one argument. It is the complete
+ // command line of the external program to execute.
+ QStringList args = this->arguments();
+ if( args.isEmpty() )
+ {
+ setError( InvalidArguments );
+ setErrorString( tr("Invalid arguments: %1 arguments given, 2 expected.").arg( args.count() ) );
+ return false;
+ }
+
+ QList< int > allowedExitCodes;
+
+ QRegExp re( QLatin1String( "^\\{((-?\\d+,)*-?\\d+)\\}$" ) );
+ if( re.exactMatch( args.first() ) )
+ {
+ const QStringList numbers = re.cap( 1 ).split( QLatin1Char( ',' ) );
+ for( QStringList::const_iterator it = numbers.begin(); it != numbers.end(); ++it )
+ allowedExitCodes.push_back( it->toInt() );
+ args.pop_front();
+ }
+ else
+ {
+ allowedExitCodes.push_back( 0 );
+ }
+
+ bool success = false;
+#ifdef SUPPORT_DETACHED_PROCESS_EXECUTION
+ // unix style: when there's an ampersand after the command, it's started detached
+ if( args.count() >= 2 && args.last() == QLatin1String( "&" ) )
+ {
+ args.pop_back();
+#ifdef Q_WS_WIN
+ QString arguments = qt_create_commandline( args.front(), args.mid( 1 ) );
+
+ PROCESS_INFORMATION pinfo;
+
+ STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0,
+ static_cast< ulong >( CW_USEDEFAULT ), static_cast< ulong >( CW_USEDEFAULT ),
+ static_cast< ulong >( CW_USEDEFAULT ), static_cast< ulong >( CW_USEDEFAULT ),
+ 0, 0, 0, STARTF_USESHOWWINDOW, SW_HIDE, 0, 0, 0, 0, 0
+ };
+ success = CreateProcess( 0, const_cast< wchar_t* >( static_cast< const wchar_t* >( arguments.utf16() ) ),
+ 0, 0, FALSE, CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE, 0,
+ 0,
+ &startupInfo, &pinfo );
+
+#else
+ success = QProcess::startDetached( args.front(), args.mid( 1 ) );
+#endif
+ }
+ else
+#endif
+ {
+ Environment::instance()->applyTo( &process ); //apply non-persistent variables
+ process.start( args.front(), args.mid( 1 ) );
+
+ QEventLoop loop;
+ QObject::connect( &process, SIGNAL( finished( int, QProcess::ExitStatus ) ), &loop, SLOT( quit() ) );
+ QObject::connect( &process, SIGNAL(readyRead()), this, SLOT(readProcessOutput()));
+ success = process.waitForStarted( -1 );
+ if( success )
+ {
+ loop.exec();
+ setValue( QLatin1String( "ExitCode" ), process.exitCode() );
+ success = allowedExitCodes.contains( process.exitCode() );
+ }
+ }
+ if(!success)
+ {
+ setError( UserDefinedError );
+ setErrorString( tr("Execution failed: \"%1\"").arg( args.join( QLatin1String( " " ) ) ) );
+ }
+
+ return success;
+}
+
+/*!
+ Cancels the ExecuteOperation. This methods tries to terminate the process
+ gracefully by calling QProcess::terminate. After 10 seconds, the process gets killed.
+ */
+void ExecuteOperation::cancelOperation()
+{
+ if( process.state() == QProcess::Running )
+ process.terminate();
+ if( !process.waitForFinished( 10000 ) )
+ process.kill();
+}
+
+void ExecuteOperation::readProcessOutput()
+{
+ QByteArray output = process.readAll();
+ if (!output.isEmpty())
+ emit outputTextChanged(QString::fromLocal8Bit(output));
+}
+
+bool ExecuteOperation::undoOperation()
+{
+ // this is not possible, since the process can do whatever...
+ return false;
+}
+
+bool ExecuteOperation::testOperation()
+{
+ // TODO
+ return true;
+}
+
+ExecuteOperation* ExecuteOperation::clone() const
+{
+ return new ExecuteOperation;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// KDUpdater::UpdatePackageOperation
+////////////////////////////////////////////////////////////////////////////
+
+UpdatePackageOperation::UpdatePackageOperation()
+{
+ setName(QLatin1String( "UpdatePackage" ));
+}
+
+UpdatePackageOperation::~UpdatePackageOperation()
+{
+
+}
+
+void UpdatePackageOperation::backup()
+{
+ const PackageInfo info = application()->packagesInfo()->packageInfo( application()->packagesInfo()->findPackageInfo( arguments().first() ) );
+ setValue( QLatin1String( "oldVersion" ), info.version );
+ setValue( QLatin1String( "oldDate" ), info.lastUpdateDate );
+}
+
+bool UpdatePackageOperation::performOperation()
+{
+ // This operation receives three arguments : the name of the package
+ // the new version and the release date
+ const QStringList args = this->arguments();
+ if( args.count() != 3 )
+ {
+ setError( InvalidArguments, tr("Invalid arguments: %1 arguments given, 3 expected.").arg( args.count() ) );
+ return false;
+ }
+
+ const QString& packageName = args.at( 0 );
+ const QString& version = args.at( 1 );
+ const QDate date = QDate::fromString( args.at( 2 ) );
+ const bool success = application()->packagesInfo()->updatePackage( packageName, version, date );
+ if(!success)
+ setError( UserDefinedError, tr("Cannot update %1-%2").arg( packageName, version ) );
+
+ return success;
+}
+
+bool UpdatePackageOperation::undoOperation()
+{
+ const QString packageName = arguments().first();
+ const QString version = arguments().at( 1 );
+ const QString oldVersion = value( QLatin1String( "oldVersion" ) ).toString();
+ const QDate oldDate = value( QLatin1String( "oldDate" ) ).toDate();
+ const bool success = application()->packagesInfo()->updatePackage( packageName, oldVersion, oldDate );
+ if(!success)
+ setError( UserDefinedError, tr("Cannot restore %1-%2").arg( packageName, version ) );
+
+ return success;
+}
+
+bool UpdatePackageOperation::testOperation()
+{
+ // TODO
+ return true;
+}
+
+UpdatePackageOperation* UpdatePackageOperation::clone() const
+{
+ return new UpdatePackageOperation;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// KDUpdater::UpdateCompatOperation
+////////////////////////////////////////////////////////////////////////////
+
+UpdateCompatOperation::UpdateCompatOperation()
+{
+ setName(QLatin1String( "UpdateCompatLevel" ));
+}
+
+UpdateCompatOperation::~UpdateCompatOperation()
+{
+
+}
+
+void UpdateCompatOperation::backup()
+{
+ setValue( QLatin1String( "oldCompatLevel" ), application()->packagesInfo()->compatLevel() );
+}
+
+bool UpdateCompatOperation::performOperation()
+{
+ // This operation receives one argument : the new compat level
+ const QStringList args = this->arguments();
+ if( args.count() != 1 )
+ {
+ setError( InvalidArguments, tr("Invalid arguments: %1 arguments given, 1 expected.").arg( args.count() ) );
+ return false;
+ }
+
+ const int level = args.first().toInt();
+ application()->packagesInfo()->setCompatLevel( level );
+ return true;
+}
+
+bool UpdateCompatOperation::undoOperation()
+{
+ if( !hasValue( QLatin1String( "oldCompatLevel" ) ) )
+ {
+ setError( UserDefinedError, tr("Cannot restore previous compat-level") );
+ return false;
+ }
+
+ application()->packagesInfo()->setCompatLevel( value( QLatin1String( "oldCompatLevel" ) ).toInt() );
+ return true;
+}
+
+bool UpdateCompatOperation::testOperation()
+{
+ // TODO
+ return true;
+}
+
+UpdateCompatOperation* UpdateCompatOperation::clone() const
+{
+ return new UpdateCompatOperation;
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateoperations.h b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateoperations.h
new file mode 100644
index 000000000..4f1a2563e
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdateoperations.h
@@ -0,0 +1,184 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef KD_UPDATER_UPDATE_OPERATIONS_H
+#define KD_UPDATER_UPDATE_OPERATIONS_H
+
+#include "kdupdaterupdateoperation.h"
+
+#include <QDir>
+#include <QObject>
+#include <QProcess>
+
+namespace KDUpdater
+{
+
+ class KDTOOLS_UPDATER_EXPORT CopyOperation : public UpdateOperation
+ {
+ public:
+ CopyOperation();
+ ~CopyOperation();
+
+ void backup();
+ bool performOperation();
+ bool undoOperation();
+ bool testOperation();
+ CopyOperation* clone() const;
+
+ QDomDocument toXml() const;
+ };
+
+ class KDTOOLS_UPDATER_EXPORT MoveOperation : public UpdateOperation
+ {
+ public:
+ MoveOperation();
+ ~MoveOperation();
+
+ void backup();
+ bool performOperation();
+ bool undoOperation();
+ bool testOperation();
+ MoveOperation* clone() const;
+ };
+
+ class KDTOOLS_UPDATER_EXPORT DeleteOperation : public UpdateOperation
+ {
+ public:
+ DeleteOperation();
+ ~DeleteOperation();
+
+ void backup();
+ bool performOperation();
+ bool undoOperation();
+ bool testOperation();
+ DeleteOperation* clone() const;
+
+ QDomDocument toXml() const;
+ };
+
+ class KDTOOLS_UPDATER_EXPORT MkdirOperation : public UpdateOperation
+ {
+ public:
+ MkdirOperation();
+ ~MkdirOperation();
+
+ void backup();
+ bool performOperation();
+ bool undoOperation();
+ bool testOperation();
+ MkdirOperation* clone() const;
+ };
+
+ class KDTOOLS_UPDATER_EXPORT RmdirOperation : public UpdateOperation
+ {
+ public:
+ RmdirOperation();
+ ~RmdirOperation();
+
+ void backup();
+ bool performOperation();
+ bool undoOperation();
+ bool testOperation();
+ RmdirOperation* clone() const;
+ };
+
+ class KDTOOLS_UPDATER_EXPORT AppendFileOperation : public UpdateOperation
+ {
+ public:
+ AppendFileOperation();
+ ~AppendFileOperation();
+
+ void backup();
+ bool performOperation();
+ bool undoOperation();
+ bool testOperation();
+ AppendFileOperation* clone() const;
+ };
+
+ class KDTOOLS_UPDATER_EXPORT PrependFileOperation : public UpdateOperation
+ {
+ public:
+ PrependFileOperation();
+ ~PrependFileOperation();
+
+ void backup();
+ bool performOperation();
+ bool undoOperation();
+ bool testOperation();
+ PrependFileOperation* clone() const;
+ };
+
+ class KDTOOLS_UPDATER_EXPORT ExecuteOperation : public QObject, public UpdateOperation
+ {
+ Q_OBJECT
+ public:
+ ExecuteOperation();
+ ~ExecuteOperation();
+
+ void backup();
+ bool performOperation();
+ bool undoOperation();
+ bool testOperation();
+ ExecuteOperation* clone() const;
+
+ public Q_SLOTS:
+ void cancelOperation();
+
+ private Q_SLOTS:
+ void readProcessOutput();
+
+ Q_SIGNALS:
+ void outputTextChanged(const QString &text);
+
+ private:
+ QProcess process;
+ };
+
+ class KDTOOLS_UPDATER_EXPORT UpdatePackageOperation : public UpdateOperation
+ {
+ public:
+ UpdatePackageOperation();
+ ~UpdatePackageOperation();
+
+ void backup();
+ bool performOperation();
+ bool undoOperation();
+ bool testOperation();
+ UpdatePackageOperation* clone() const;
+ };
+
+ class KDTOOLS_UPDATER_EXPORT UpdateCompatOperation : public UpdateOperation
+ {
+ public:
+ UpdateCompatOperation();
+ ~UpdateCompatOperation();
+
+ void backup();
+ bool performOperation();
+ bool undoOperation();
+ bool testOperation();
+ UpdateCompatOperation* clone() const;
+ };
+
+};
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesdialog.cpp b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesdialog.cpp
new file mode 100644
index 000000000..2b8d54a6b
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesdialog.cpp
@@ -0,0 +1,305 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdupdaterupdatesdialog.h"
+#include "kdupdaterpackagesinfo.h"
+#include "kdupdaterupdate.h"
+#include "kdupdaterapplication.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDir>
+#include <QtCore/QHash>
+#include <QtCore/QSet>
+
+#if defined( KDUPDATERGUIWEBVIEW )
+#include <QtWebKit/QWebView>
+#elif defined( KDUPDATERGUITEXTBROWSER )
+#include <QtGui/QTextBrowser>
+#endif
+
+#include "ui_updatesdialog.h"
+
+/*!
+ \ingroup kdupdater
+ \class KDUpdater::UpdatesDialog kdupdaterupdatesdialog.h KDUpdaterUpdatesDialog
+ \brief A dialog that let the user chooses which updates he wants to install
+
+ After \ref KDUpdater::UpdateFinder class finds all updates available for an application,
+ this dialog can be used to help the user select which update he wants to install.
+
+ Usage:
+ \code
+ QList<KDUpdater::Update*> updates = updateFinder.updates();
+
+ KDUpdater::UpdatesDialog updatesDialog(this);
+ updatesDialog.setUpdates(updates);
+
+ if( updatesDialog.exec() != QDialog::Accepted )
+ {
+ qDeleteAll(updates);
+ updates.clear();
+ return;
+ }
+
+ QList<KDUpdater::Update*> reqUpdates;
+ for(int i=0; i<updates.count(); i++)
+ {
+ if( !updatesDialog.isUpdateAllowed(updates[i]) )
+ continue;
+ reqUpdates.append(updates[i]);
+ }
+ \endcode
+*/
+
+class KDUpdater::UpdatesDialog::Private
+{
+ Q_DECLARE_TR_FUNCTIONS(KDUpdater::Private)
+
+public:
+ explicit Private( UpdatesDialog* qq ) :
+ q( qq )
+ {}
+
+ UpdatesDialog* q;
+
+ Ui::UpdatesDialog ui;
+
+ int currentUpdate;
+ QList<Update*> updates;
+ QSet<const Update*> status;
+
+ void setCurrentUpdate(int index);
+
+ QString packageDescription( Update* update );
+ QString compatDescription( Update* update );
+ void slotStateChanged();
+ void slotPreviousClicked();
+ void slotNextClicked();
+};
+
+/*!
+ Constructor.
+*/
+KDUpdater::UpdatesDialog::UpdatesDialog(QWidget *parent)
+ : QDialog(parent),
+ d( new Private( this ) )
+{
+ d->ui.setupUi(this);
+ d->currentUpdate = -1;
+
+ connect(d->ui.packageUpdateCheckBox, SIGNAL(stateChanged(int)),
+ this, SLOT(slotStateChanged()));
+ connect(d->ui.nextPackageButton, SIGNAL(clicked()),
+ this, SLOT(slotNextClicked()));
+ connect(d->ui.previousPackageButton, SIGNAL(clicked()),
+ this, SLOT(slotPreviousClicked()));
+}
+
+
+/*!
+ Destructor.
+*/
+KDUpdater::UpdatesDialog::~UpdatesDialog()
+{
+ delete d;
+}
+
+
+/*!
+ Sets the list of updates available to the user.
+*/
+void KDUpdater::UpdatesDialog::setUpdates(const QList<Update*> &updates)
+{
+ d->updates = updates;
+ d->status.clear();
+
+ d->ui.packageSwitchBar->setVisible( d->updates.size()>1 );
+
+ if (d->updates.isEmpty()) {
+ d->ui.descriptionLabel->setText(tr("<b>No update available...</b>"));
+ d->ui.descriptionLabel->setFixedSize(d->ui.descriptionLabel->sizeHint());
+ d->ui.releaseNotesGroup->hide();
+ d->ui.pixmapLabel->hide();
+ } else if (d->updates.size()==1) {
+ //Only one update, so pre-accept it.
+ //OK/Cancel will do from the user POV
+ d->status.insert( d->updates.front() );
+ }
+
+ d->ui.totalPackageLabel->setText(QString::number(d->updates.size()));
+ d->setCurrentUpdate(0);
+}
+
+
+/*!
+ returns the list of updates available to the user.
+*/
+QList<KDUpdater::Update*> KDUpdater::UpdatesDialog::updates() const
+{
+ return d->updates;
+}
+
+
+/*!
+ Returns true if the update needs to be installed.
+*/
+bool KDUpdater::UpdatesDialog::isUpdateAllowed(const KDUpdater::Update *update) const
+{
+ return d->status.contains( update );
+}
+
+void KDUpdater::UpdatesDialog::Private::slotStateChanged()
+{
+ if (currentUpdate<0 || currentUpdate>=updates.size()) {
+ return;
+ }
+
+ if ( ui.packageUpdateCheckBox->isChecked() )
+ status.insert( updates[currentUpdate] );
+ else
+ status.remove( updates[currentUpdate] );
+}
+
+void KDUpdater::UpdatesDialog::Private::slotPreviousClicked()
+{
+ setCurrentUpdate(currentUpdate-1);
+}
+
+void KDUpdater::UpdatesDialog::Private::slotNextClicked()
+{
+ setCurrentUpdate(currentUpdate+1);
+}
+
+void KDUpdater::UpdatesDialog::Private::setCurrentUpdate(int index)
+{
+ if (updates.isEmpty()) {
+ if (currentUpdate == -1)
+ return;
+
+ currentUpdate = -1;
+ return;
+ }
+
+ if (index<0 || index>=updates.size()) {
+ return;
+ }
+
+ currentUpdate = index;
+
+ KDUpdater::Update *update = updates.at( index );
+
+ QString description;
+
+ switch ( update->type() ) {
+ case PackageUpdate:
+ case NewPackage:
+ description = packageDescription( update );
+ break;
+ case CompatUpdate:
+ description = compatDescription( update );
+ break;
+ default:
+ description = tr( "<unkown>" );
+ }
+
+ ui.descriptionLabel->setText(description);
+ ui.descriptionLabel->setMinimumHeight(ui.descriptionLabel->heightForWidth(400));
+
+ ui.packageUpdateCheckBox->setChecked( status.contains( update ) );
+
+ ui.currentPackageLabel->setText(QString::number(index+1));
+ ui.nextPackageButton->setEnabled( index!=(updates.size()-1) );
+ ui.previousPackageButton->setEnabled( index!=0 );
+
+ QDir appdir(update->application()->applicationDirectory());
+ if (update->data( QLatin1String( "ReleaseNotes" ) ).isValid()) {
+ ui.releaseNotesGroup->show();
+#if defined( KDUPDATERGUIWEBVIEW )
+ ui.releaseNotesView->setUrl( update->data( QLatin1String( "ReleaseNotes" ) ).toUrl() );
+#elif defined( KDUPDATERGUITEXTBROWSER )
+ ui.releaseNotesView->setSource( update->data( QLatin1String( "ReleaseNotes" ) ).toUrl());
+#endif
+ }
+ else {
+ ui.releaseNotesGroup->hide();
+ }
+}
+
+
+QString KDUpdater::UpdatesDialog::Private::packageDescription( KDUpdater::Update* update )
+{
+ KDUpdater::PackagesInfo *packages = update->application()->packagesInfo();
+ KDUpdater::PackageInfo info = packages->packageInfo(
+ packages->findPackageInfo(update->data( QLatin1String( "Name" ) ).toString()));
+
+ QDir appdir(update->application()->applicationDirectory());
+ QPixmap pixmap(appdir.filePath(info.pixmap));
+ if (!pixmap.isNull()) {
+ ui.pixmapLabel->setPixmap(pixmap.scaled(96, 96));
+ }
+
+
+ QString description = tr("<b>A new package update is available for %1!</b><br/><br/>"
+ "The package %2 %3 is now available -- you have version %4")
+ .arg(packages->applicationName(),
+ update->data( QLatin1String( "Name" ) ).toString(),
+ update->data( QLatin1String( "Version" ) ).toString(),
+ info.version);
+
+ if (!info.title.isEmpty() || !info.description.isEmpty() ) {
+ description += QLatin1String( "<br/><br/>" );
+ description += tr("<b>Package Details:</b>" );
+ if ( !info.title.isEmpty() ) {
+ description += tr( "<br/><i>Title:</i> %1" ).arg( info.title );
+ }
+ if ( !info.description.isEmpty() ) {
+ description += tr( "<br/><i>Description:</i> %1" ).arg( info.description );
+ }
+ }
+
+ if ( update->data( QLatin1String( "Description" ) ).isValid() ) {
+ description += QLatin1String( "<br/><br/>" );
+ description += tr( "<b>Update description:</b><br/>%1" )
+ .arg( update->data( QLatin1String( "Description" ) ).toString() );
+ }
+ return description;
+}
+
+QString KDUpdater::UpdatesDialog::Private::compatDescription( Update* update )
+{
+ KDUpdater::PackagesInfo *packages = update->application()->packagesInfo();
+
+ QString description = tr("<b>A new compatibility update is available for %1!</b><br/><br/>"
+ "The compatibility level %2 is now available -- you have level %3")
+ .arg(packages->applicationName(),
+ QString::number(update->data( QLatin1String( "CompatLevel" ) ).toInt()),
+ QString::number(packages->compatLevel()));
+
+ if ( update->data( QLatin1String( "Description" ) ).isValid() ) {
+ description += QLatin1String( "<br/><br/>" );
+ description += tr( "<b>Update description:</b> %1" )
+ .arg( update->data( QLatin1String( "Description" ) ).toString() );
+ }
+ return description;
+}
+
+#include "moc_kdupdaterupdatesdialog.cpp"
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesdialog.h b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesdialog.h
new file mode 100644
index 000000000..85a90a595
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesdialog.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef KD_UPDATER_UPDATES_DIALOG_H
+#define KD_UPDATER_UPDATES_DIALOG_H
+
+#include "kdupdater.h"
+#include <QtCore/QList>
+#include <QtGui/QDialog>
+
+namespace KDUpdater
+{
+ class Update;
+
+ class KDTOOLS_UPDATER_EXPORT UpdatesDialog : public QDialog
+ {
+ Q_OBJECT
+
+ public:
+ explicit UpdatesDialog(QWidget *parent = 0);
+ ~UpdatesDialog();
+
+ void setUpdates(const QList<Update*> &updates);
+ QList<Update*> updates() const;
+
+ bool isUpdateAllowed( const Update * update ) const;
+
+ private:
+ class Private;
+ Private * const d;
+
+ Q_PRIVATE_SLOT( d, void slotStateChanged() )
+ Q_PRIVATE_SLOT( d, void slotPreviousClicked() )
+ Q_PRIVATE_SLOT( d, void slotNextClicked() )
+ };
+}
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesinfo.cpp b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesinfo.cpp
new file mode 100644
index 000000000..4e9f60195
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesinfo.cpp
@@ -0,0 +1,372 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdupdaterupdatesinfo_p.h"
+
+#include <QCoreApplication>
+#include <QDomDocument>
+#include <QDomElement>
+#include <QFile>
+#include <QSharedData>
+
+//
+// KDUpdater::UpdatesInfo::UpdatesInfoData
+//
+struct KDUpdater::UpdatesInfo::UpdatesInfoData : public QSharedData
+{
+ Q_DECLARE_TR_FUNCTIONS(KDUpdater::UpdatesInfoData)
+
+public:
+ UpdatesInfoData() : error(UpdatesInfo::NotYetReadError), compatLevel(-1) { }
+
+ QString errorMessage;
+ UpdatesInfo::Error error;
+ QString updateXmlFile;
+ QString applicationName;
+ QString applicationVersion;
+ int compatLevel;
+ QList<KDUpdater::UpdateInfo> updateInfoList;
+
+ void parseFile(const QString& updateXmlFile);
+ bool parsePackageUpdateElement(const QDomElement & updateE);
+ bool parseCompatUpdateElement(const QDomElement & updateE);
+
+ void setInvalidContentError( const QString& detail );
+};
+
+void KDUpdater::UpdatesInfo::UpdatesInfoData::setInvalidContentError(const QString& detail)
+{
+ error = UpdatesInfo::InvalidContentError;
+ errorMessage = tr("Updates.Xml contains invalid content: %1").arg(detail);
+}
+
+void KDUpdater::UpdatesInfo::UpdatesInfoData::parseFile(const QString& updateXmlFile)
+{
+ QFile file( updateXmlFile );
+ if( !file.open(QFile::ReadOnly) )
+ {
+ error = UpdatesInfo::CouldNotReadUpdateInfoFileError;
+ errorMessage = tr("Could not read \"%1\"").arg(updateXmlFile);
+ return;
+ }
+
+ QDomDocument doc;
+ QString parseErrorMessage;
+ int parseErrorLine;
+ int parseErrorColumn;
+ if( !doc.setContent( &file, &parseErrorMessage, &parseErrorLine, &parseErrorColumn ) )
+ {
+ error = UpdatesInfo::InvalidXmlError;
+ errorMessage = tr("Parse error in %1 at %2, %3: %4")
+ .arg( updateXmlFile,
+ QString::number( parseErrorLine ),
+ QString::number( parseErrorColumn ),
+ parseErrorMessage );
+ return;
+ }
+
+ QDomElement rootE = doc.documentElement();
+ if( rootE.tagName() != QLatin1String( "Updates" ) )
+ {
+ setInvalidContentError(tr("root element %1 unexpected, should be \"Updates\"").arg(rootE.tagName()));
+ return;
+ }
+
+ QDomNodeList childNodes = rootE.childNodes();
+ for(int i=0; i<childNodes.count(); i++)
+ {
+ QDomNode childNode = childNodes.at(i);
+ QDomElement childE = childNode.toElement();
+ if( childE.isNull() )
+ continue;
+
+ if( childE.tagName() == QLatin1String( "ApplicationName" ) )
+ applicationName = childE.text();
+ else if( childE.tagName() == QLatin1String( "ApplicationVersion" ) )
+ applicationVersion = childE.text();
+ else if( childE.tagName() == QLatin1String( "RequiredCompatLevel" ) )
+ compatLevel = childE.text().toInt();
+ else if( childE.tagName() == QLatin1String( "PackageUpdate" ) ) {
+ const bool res = parsePackageUpdateElement( childE );
+ if (!res) {
+ //error handled in subroutine
+ return;
+ }
+ } else if( childE.tagName() == QLatin1String( "CompatUpdate" ) ) {
+ const bool res = parseCompatUpdateElement( childE );
+ if (!res) {
+ //error handled in subroutine
+ return;
+ }
+ }
+ }
+
+ if (applicationName.isEmpty())
+ {
+ setInvalidContentError(tr("ApplicationName element is missing"));
+ return;
+ }
+
+ if (applicationVersion.isEmpty())
+ {
+ setInvalidContentError(tr("ApplicationVersion element is missing"));
+ return;
+ }
+
+ error = UpdatesInfo::NoError;
+ errorMessage.clear();
+}
+
+bool KDUpdater::UpdatesInfo::UpdatesInfoData::parsePackageUpdateElement(const QDomElement & updateE)
+{
+ if( updateE.isNull() )
+ return false;
+
+ KDUpdater::UpdateInfo info;
+ info.type = KDUpdater::PackageUpdate;
+
+ QDomNodeList childNodes = updateE.childNodes();
+ for(int i=0; i<childNodes.count(); i++)
+ {
+ QDomNode childNode = childNodes.at(i);
+ QDomElement childE = childNode.toElement();
+ if( childE.isNull() )
+ continue;
+
+ if( childE.tagName() == QLatin1String( "ReleaseNotes" ) ) {
+ info.data[childE.tagName()] = QUrl(childE.text());
+ }
+ else if( childE.tagName() == QLatin1String( "UpdateFile" ) )
+ {
+ KDUpdater::UpdateFileInfo ufInfo;
+ ufInfo.arch = childE.attribute(QLatin1String( "Arch" ), QLatin1String( "i386" ));
+ ufInfo.os = childE.attribute(QLatin1String( "OS" ));
+ ufInfo.compressedSize = childE.attribute( QLatin1String( "CompressedSize" ) ).toLongLong();
+ ufInfo.uncompressedSize = childE.attribute( QLatin1String( "UncompressedSize" ) ).toLongLong();
+ ufInfo.sha1sum = QByteArray::fromHex( childE.attribute( QLatin1String( "sha1sum" ) ).toAscii() );
+ ufInfo.fileName = childE.text();
+ info.updateFiles.append(ufInfo);
+ }
+ else if (childE.tagName() == QLatin1String("Licenses")) {
+ QHash<QString, QVariant> licenseHash;
+ const QDomNodeList licenseNodes = childE.childNodes();
+ for (int i = 0; i < licenseNodes.count(); ++i) {
+ const QDomNode licenseNode = licenseNodes.at(i);
+ if (licenseNode.nodeName() == QLatin1String("License")) {
+ QDomElement element = licenseNode.toElement();
+ licenseHash.insert(element.attributeNode(QLatin1String("name")).value(),
+ element.attributeNode(QLatin1String("file")).value());
+ }
+ }
+ if (!licenseHash.isEmpty())
+ info.data.insert(QLatin1String("Licenses"), licenseHash);
+ }
+ else {
+ info.data[childE.tagName()] = childE.text();
+ }
+ }
+
+ if (!info.data.contains( QLatin1String( "Name" ) ))
+ {
+ setInvalidContentError(tr("PackageUpdate element without Name"));
+ return false;
+ }
+ else if (!info.data.contains( QLatin1String( "Version" ) ))
+ {
+ setInvalidContentError(tr("PackageUpdate element without Version"));
+ return false;
+ }
+ else if (!info.data.contains( QLatin1String( "ReleaseDate" ) ))
+ {
+ setInvalidContentError(tr("PackageUpdate element without ReleaseDate"));
+ return false;
+ }
+ else if (info.updateFiles.isEmpty())
+ {
+ setInvalidContentError(tr("PackageUpdate element without UpdateFile"));
+ return false;
+ }
+
+ updateInfoList.append(info);
+ return true;
+}
+
+bool KDUpdater::UpdatesInfo::UpdatesInfoData::parseCompatUpdateElement(const QDomElement & updateE)
+{
+ if( updateE.isNull() )
+ return false;
+
+ KDUpdater::UpdateInfo info;
+ info.type = KDUpdater::CompatUpdate;
+
+ QDomNodeList childNodes = updateE.childNodes();
+ for(int i=0; i<childNodes.count(); i++)
+ {
+ QDomNode childNode = childNodes.at(i);
+ QDomElement childE = childNode.toElement();
+ if( childE.isNull() )
+ continue;
+
+ if( childE.tagName() == QLatin1String( "ReleaseNotes" ) ) {
+ info.data[childE.tagName()] = QUrl(childE.text());
+ }
+ else if( childE.tagName() == QLatin1String( "UpdateFile" ) )
+ {
+ KDUpdater::UpdateFileInfo ufInfo;
+ ufInfo.arch = childE.attribute(QLatin1String( "Arch" ), QLatin1String( "i386" ));
+ ufInfo.os = childE.attribute(QLatin1String( "OS" ));
+ ufInfo.fileName = childE.text();
+ info.updateFiles.append(ufInfo);
+ }
+ else {
+ info.data[childE.tagName()] = childE.text();
+ }
+ }
+
+ if (!info.data.contains( QLatin1String( "CompatLevel" ) ))
+ {
+ setInvalidContentError(tr("CompatUpdate element without CompatLevel"));
+ return false;
+ }
+
+ if (!info.data.contains( QLatin1String( "ReleaseDate" ) ))
+ {
+ setInvalidContentError(tr("CompatUpdate element without ReleaseDate"));
+ return false;
+ }
+
+ if (info.updateFiles.isEmpty())
+ {
+ setInvalidContentError(tr("CompatUpdate element without UpdateFile"));
+ return false;
+ }
+
+ updateInfoList.append(info);
+ return true;
+}
+
+
+//
+// KDUpdater::UpdatesInfo
+//
+KDUpdater::UpdatesInfo::UpdatesInfo()
+ : d(new KDUpdater::UpdatesInfo::UpdatesInfoData)
+{
+}
+
+KDUpdater::UpdatesInfo::~UpdatesInfo()
+{
+}
+
+bool KDUpdater::UpdatesInfo::isValid() const
+{
+ return d->error == NoError;
+}
+
+QString KDUpdater::UpdatesInfo::errorString() const
+{
+ return d->errorMessage;
+}
+
+void KDUpdater::UpdatesInfo::setFileName(const QString& updateXmlFile)
+{
+ if( d->updateXmlFile == updateXmlFile )
+ return;
+
+ d->applicationName.clear();
+ d->applicationVersion.clear();
+ d->updateInfoList.clear();
+
+ d->updateXmlFile = updateXmlFile;
+ d->parseFile( d->updateXmlFile );
+}
+
+QString KDUpdater::UpdatesInfo::fileName() const
+{
+ return d->updateXmlFile;
+}
+
+QString KDUpdater::UpdatesInfo::applicationName() const
+{
+ return d->applicationName;
+}
+
+QString KDUpdater::UpdatesInfo::applicationVersion() const
+{
+ return d->applicationVersion;
+}
+
+int KDUpdater::UpdatesInfo::compatLevel() const
+{
+ return d->compatLevel;
+}
+
+int KDUpdater::UpdatesInfo::updateInfoCount( int type) const
+{
+ if ( type == KDUpdater::AllUpdate ) {
+ return d->updateInfoList.count();
+ }
+ int count = 0;
+ for ( int i=0; i<d->updateInfoList.count(); ++i ) {
+ if ( d->updateInfoList.at( i ).type == type )
+ ++count;
+ }
+ return count;
+}
+
+KDUpdater::UpdateInfo KDUpdater::UpdatesInfo::updateInfo(int index) const
+{
+ if(index < 0 || index >= d->updateInfoList.count())
+ return KDUpdater::UpdateInfo();
+
+ return d->updateInfoList.at( index );
+}
+
+QList<KDUpdater::UpdateInfo> KDUpdater::UpdatesInfo::updatesInfo( int type, int compatLevel ) const
+{
+ QList<KDUpdater::UpdateInfo> list;
+ if ( compatLevel == -1 ) {
+ if ( type == KDUpdater::AllUpdate ) {
+ return d->updateInfoList;
+ }
+ for ( int i=0; i<d->updateInfoList.count(); ++i ) {
+ if ( d->updateInfoList.at( i ).type == type )
+ list.append( d->updateInfoList.at( i ) );
+ }
+ }
+ else {
+ for ( int i=0; i<d->updateInfoList.count(); ++i ) {
+ UpdateInfo updateInfo = d->updateInfoList.at( i );
+ if ( updateInfo.type == type ) {
+ if ( updateInfo.type == CompatUpdate ) {
+ if ( updateInfo.data.value( QLatin1String( "CompatLevel" ) ) == compatLevel )
+ list.append( updateInfo );
+ }
+ else {
+ if ( updateInfo.data.value( QLatin1String( "RequiredCompatLevel" ) ) == compatLevel )
+ list.append( updateInfo );
+ }
+ }
+ }
+ }
+ return list;
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesinfo_p.h b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesinfo_p.h
new file mode 100644
index 000000000..4179e3d8d
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesinfo_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef KD_UPDATER_UPDATE_PACKAGES_INFO_H
+#define KD_UPDATER_UPDATE_PACKAGES_INFO_H
+
+#include "kdupdater.h"
+#include <QSharedDataPointer>
+#include <QString>
+#include <QDate>
+#include <QList>
+#include <QStringList>
+#include <QUrl>
+#include <QMap>
+#include <QVariant>
+
+// Classes and structures in this header file are for internal use only.
+// They are not a part of the public API
+
+namespace KDUpdater
+{
+ struct UpdateFileInfo
+ {
+ UpdateFileInfo()
+ : compressedSize( 0 ),
+ uncompressedSize( 0 )
+ {
+ }
+ QString arch;
+ QString os;
+ QString fileName;
+ QByteArray sha1sum;
+ quint64 compressedSize;
+ quint64 uncompressedSize;
+ };
+
+ struct UpdateInfo
+ {
+ int type;
+ QMap<QString, QVariant> data;
+ QList<UpdateFileInfo> updateFiles;
+ };
+
+ class UpdatesInfo
+ {
+ public:
+ enum Error
+ {
+ NoError=0,
+ NotYetReadError,
+ CouldNotReadUpdateInfoFileError,
+ InvalidXmlError,
+ InvalidContentError
+ };
+
+ UpdatesInfo();
+ ~UpdatesInfo();
+
+ bool isValid() const;
+ QString errorString() const;
+ Error error() const;
+
+ void setFileName(const QString& updateXmlFile);
+ QString fileName() const;
+
+ QString applicationName() const;
+ QString applicationVersion() const;
+ int compatLevel() const;
+
+ int updateInfoCount( int type=AllUpdate ) const;
+ UpdateInfo updateInfo(int index) const;
+ QList<UpdateInfo> updatesInfo( int type=AllUpdate, int compatLevel=-1 ) const;
+
+ private:
+ struct UpdatesInfoData;
+ QSharedDataPointer<UpdatesInfoData> d;
+ };
+};
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesourcesinfo.cpp b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesourcesinfo.cpp
new file mode 100644
index 000000000..14a765a5b
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesourcesinfo.cpp
@@ -0,0 +1,511 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdupdaterupdatesourcesinfo.h"
+#include "kdupdaterapplication.h"
+
+#include <QDomElement>
+#include <QDomDocument>
+#include <QDomText>
+#include <QDomCDATASection>
+#include <QFileInfo>
+#include <QFile>
+#include <QTextStream>
+
+
+/*!
+ \ingroup kdupdater
+ \class KDUpdater::UpdateSourcesInfo kdupdaterupdatesourcesinfo.h KDUpdaterUpdateSourcesInfo
+ \brief Provides access to information about the update sources set for the application.
+
+ An update source is a repository that contains updates applicable for the application.
+ Applications can download updates from the update source and install them locally.
+
+ Each application can have one or more update sources from which it can download updates.
+ Information about update source is stored in a file called UpdateSources.xml. This class helps
+ access and modify the UpdateSources.xml file.
+
+ The complete file name of the UpdateSources.xml file can be specified via the \ref setFileName()
+ method. The class then parses the XML file and makes available information contained in
+ that XML file through an easy to use API. You can
+
+ \li Get update sources information via the \ref updateSourceInfoCount() and \ref updateSourceInfo()
+ methods.
+ \li You can add/remove/change update source information via the \ref addUpdateSourceInfo(),
+ \ref removeUpdateSource(), \ref setUpdateSourceAt() methods.
+
+ The class emits appropriate signals to inform listeners about changes in the update application.
+*/
+
+/*! \enum UpdateSourcesInfo::Error
+ * Error codes related to retrieving update sources
+ */
+
+/*! \var UpdateSourcesInfo::Error UpdateSourcesInfo::NoError
+ * No error occurred
+ */
+
+/*! \var UpdateSourcesInfo::Error UpdateSourcesInfo::NotYetReadError
+ * The package information was not parsed yet from the XML file
+ */
+
+/*! \var UpdateSourcesInfo::Error UpdateSourcesInfo::CouldNotReadSourceFileError
+ * the specified update source file could not be read (does not exist or not readable)
+ */
+
+/*! \var UpdateSourcesInfo::Error UpdateSourcesInfo::InvalidXmlError
+ * The source file contains invalid XML.
+ */
+
+/*! \var UpdateSourcesInfo::Error UpdateSourcesInfo::InvalidContentError
+ * The source file contains valid XML, but does not match the expected format for source descriptions
+ */
+
+/*! \var UpdateSourcesInfo::Error UpdateSourcesInfo::CouldNotSaveChangesError
+ * Changes made to the object could be saved back to the source file
+ */
+
+namespace KDUpdater
+{
+struct UpdateSourceInfoPriorityHigherThan
+{
+ bool operator()( const UpdateSourceInfo& lhs, const UpdateSourceInfo& rhs ) const
+ {
+ return lhs.priority > rhs.priority;
+ }
+};
+}
+
+struct KDUpdater::UpdateSourcesInfo::UpdateSourcesInfoData
+{
+ UpdateSourcesInfoData( UpdateSourcesInfo* qq ) :
+ q( qq ),
+ error(UpdateSourcesInfo::NotYetReadError),
+ application(0),
+ modified(false)
+ {}
+
+ UpdateSourcesInfo* q;
+
+ QString errorMessage;
+ UpdateSourcesInfo::Error error;
+ KDUpdater::Application* application;
+ bool modified;
+ QString fileName;
+ QList<KDUpdater::UpdateSourceInfo> updateSourceInfoList;
+
+ void addUpdateSourceFrom( const QDomElement & element );
+ void addChildElement( QDomDocument & doc, QDomElement & parentE, const QString & tagName, const QString & text, bool htmlText=false );
+ void setInvalidContentError( const QString& detail );
+ void clearError();
+ void saveChanges();
+};
+
+void KDUpdater::UpdateSourcesInfo::UpdateSourcesInfoData::setInvalidContentError(const QString& detail)
+{
+ error = UpdateSourcesInfo::InvalidContentError;
+ errorMessage = tr("%1 contains invalid content: %2").arg(fileName, detail);
+}
+
+void KDUpdater::UpdateSourcesInfo::UpdateSourcesInfoData::clearError()
+{
+ error = UpdateSourcesInfo::NoError;
+ errorMessage.clear();
+}
+
+/*!
+ \internal
+*/
+KDUpdater::UpdateSourcesInfo::UpdateSourcesInfo(Application* application)
+ : QObject(application),
+ d( new KDUpdater::UpdateSourcesInfo::UpdateSourcesInfoData( this ) )
+{
+ d->application = application;
+}
+
+/*!
+ \internal
+*/
+KDUpdater::UpdateSourcesInfo::~UpdateSourcesInfo()
+{
+ d->saveChanges();
+ delete d;
+}
+
+/*!
+ Returns a pointer to the update application for which this class manages update sources.
+*/
+KDUpdater::Application* KDUpdater::UpdateSourcesInfo::application() const
+{
+ return d->application;
+}
+
+/*!
+ \internal
+*/
+bool KDUpdater::UpdateSourcesInfo::isValid() const
+{
+ return d->error == NoError;
+}
+
+/*!
+ returns a human-readable description of the error
+ */
+QString KDUpdater::UpdateSourcesInfo::errorString() const
+{
+ return d->errorMessage;
+}
+
+/*!
+ returns the last error
+ */
+KDUpdater::UpdateSourcesInfo::Error KDUpdater::UpdateSourcesInfo::error() const
+{
+ return d->error;
+}
+
+bool KDUpdater::UpdateSourcesInfo::isModified() const
+{
+ return d->modified;
+}
+
+void KDUpdater::UpdateSourcesInfo::setModified(bool modified)
+{
+ d->modified = modified;
+}
+
+/*!
+ Sets the complete file name of the UpdateSources.xml file. The function also issues a call
+ to refresh() to reload package information from the XML file.
+
+ \sa KDUpdater::Application::setUpdateSourcesXMLFileName()
+*/
+void KDUpdater::UpdateSourcesInfo::setFileName(const QString& fileName)
+{
+ if( d->fileName == fileName )
+ return;
+
+ d->fileName = fileName;
+ refresh(); // load new file
+}
+
+/*!
+ Returns the name of the UpdateSources.xml file that this class referred to.
+*/
+QString KDUpdater::UpdateSourcesInfo::fileName() const
+{
+ return d->fileName;
+}
+
+/*!
+ Returns the number of update source info structures contained in this class.
+*/
+int KDUpdater::UpdateSourcesInfo::updateSourceInfoCount() const
+{
+ return d->updateSourceInfoList.count();
+}
+
+/*!
+ Returns the update source info structure at \c index. If an invalid index is passed
+ the function returns a dummy constructor.
+*/
+KDUpdater::UpdateSourceInfo KDUpdater::UpdateSourcesInfo::updateSourceInfo(int index) const
+{
+ if( index < 0 || index >= d->updateSourceInfoList.count() )
+ return KDUpdater::UpdateSourceInfo();
+
+ return d->updateSourceInfoList[index];
+}
+
+/*!
+ Adds an update source info to this class. Upon successful addition, the class emits a
+ \ref updateSourceInfoAdded() signal.
+*/
+void KDUpdater::UpdateSourcesInfo::addUpdateSourceInfo(const KDUpdater::UpdateSourceInfo& info)
+{
+ if( d->updateSourceInfoList.contains( info ) )
+ return;
+ d->updateSourceInfoList.push_back( info );
+ qSort( d->updateSourceInfoList.begin(), d->updateSourceInfoList.end(), KDUpdater::UpdateSourceInfoPriorityHigherThan() );
+ emit updateSourceInfoAdded(info);
+ d->modified = true;
+}
+
+/*!
+ Removes an update source info from this class. Upon successful removal, the class emits a
+ \ref updateSourceInfoRemoved() signal.
+*/
+void KDUpdater::UpdateSourcesInfo::removeUpdateSourceInfo(const KDUpdater::UpdateSourceInfo& info)
+{
+ if( !d->updateSourceInfoList.contains(info) )
+ return;
+ d->updateSourceInfoList.removeAll(info);
+ emit updateSourceInfoRemoved(info);
+ d->modified = true;
+}
+
+/*!
+ Removes an update source info at \index in this class. Upon successful removal, the class emits a
+ \ref updateSourceInfoRemoved() signal.
+*/
+void KDUpdater::UpdateSourcesInfo::removeUpdateSourceInfoAt(int index)
+{
+ if( index < 0 || index >= d->updateSourceInfoList.count() )
+ return;
+ KDUpdater::UpdateSourceInfo info = d->updateSourceInfoList[index];
+ d->updateSourceInfoList.removeAt(index);
+ emit updateSourceInfoRemoved(info);
+ d->modified = true;
+}
+
+/*!
+ Changes the update source info at \c index to \c info. If \c index is equal to the number of
+ source info structures in this class (\ref updateSourceInfoCount()) then \c info is appended;
+ otherwise the existing info at \c index will be changed.
+
+ Depending on what the function does \ref updateSourceInfoAdded() or \ref updateSourceInfoChanged()
+ signal is emitted.
+*/
+void KDUpdater::UpdateSourcesInfo::setUpdateSourceInfoAt(int index, const KDUpdater::UpdateSourceInfo& info)
+{
+ if( index < 0 || index > d->updateSourceInfoList.count() )
+ return;
+
+ if( index == d->updateSourceInfoList.count() )
+ {
+ d->updateSourceInfoList.append(info);
+ emit updateSourceInfoAdded(info);
+ }
+ else
+ {
+ KDUpdater::UpdateSourceInfo oldInfo = d->updateSourceInfoList[index];
+ if( info == oldInfo )
+ return;
+
+ d->updateSourceInfoList[index] = info;
+ emit updateSourceInfoChanged(info, oldInfo);
+ }
+ d->modified = true;
+}
+
+/*!
+ This slot reloads the update source information from UpdateSources.xml.
+*/
+void KDUpdater::UpdateSourcesInfo::refresh()
+{
+ d->saveChanges(); // save changes done in the previous file
+ d->updateSourceInfoList.clear();
+
+ QFile file( d->fileName );
+
+ // if the file does not exist then we just skip the reading
+ if( !file.exists() )
+ {
+ d->clearError();
+ emit reset();
+ return;
+ }
+
+ // Open the XML file
+ if( !file.open(QFile::ReadOnly) )
+ {
+ d->errorMessage = tr("Could not read \"%1\"").arg(d->fileName);
+ d->error = CouldNotReadSourceFileError;
+ emit reset();
+ return;
+ }
+
+ QDomDocument doc;
+ QString parseErrorMessage;
+ int parseErrorLine;
+ int parseErrorColumn;
+ if( !doc.setContent( &file, &parseErrorMessage, &parseErrorLine, &parseErrorColumn ) )
+ {
+ d->error = InvalidXmlError;
+ d->errorMessage = tr("XML Parse error in %1 at %2, %3: %4")
+ .arg( d->fileName,
+ QString::number( parseErrorLine ),
+ QString::number( parseErrorColumn ),
+ parseErrorMessage );
+ emit reset();
+ return;
+ }
+
+ // Now parse the XML file.
+ QDomElement rootE = doc.documentElement();
+ if( rootE.tagName() != QLatin1String( "UpdateSources" ) )
+ {
+ d->setInvalidContentError(tr("Root element %1 unexpected, should be \"UpdateSources\"").arg(rootE.tagName()));
+ emit reset();
+ return;
+ }
+
+ QDomNodeList childNodes = rootE.childNodes();
+ for(int i=0; i<childNodes.count(); i++)
+ {
+ QDomNode childNode = childNodes.item(i);
+ QDomElement childNodeE = childNode.toElement();
+ if( childNodeE.isNull() )
+ continue;
+
+ if( childNodeE.tagName() == QLatin1String( "UpdateSource" ) )
+ d->addUpdateSourceFrom(childNodeE);
+ }
+
+ d->clearError();
+ emit reset();
+}
+
+void KDUpdater::UpdateSourcesInfo::UpdateSourcesInfoData::saveChanges()
+{
+ if( !modified || fileName.isEmpty() )
+ return;
+
+ const bool hadSaveError = error == UpdateSourcesInfo::CouldNotSaveChangesError;
+
+ QDomDocument doc;
+
+ QDomElement rootE = doc.createElement( QLatin1String( "UpdateSources") );
+ doc.appendChild(rootE);
+
+ for(int i=0; i<updateSourceInfoList.count(); i++)
+ {
+ KDUpdater::UpdateSourceInfo info = updateSourceInfoList[i];
+
+ QDomElement infoE = doc.createElement( QLatin1String( "UpdateSource" ) );
+ rootE.appendChild(infoE);
+ addChildElement(doc, infoE, QLatin1String( "Name" ), info.name);
+ addChildElement(doc, infoE, QLatin1String( "Title" ), info.title);
+ addChildElement(doc, infoE, QLatin1String( "Description" ), info.description,
+ (info.description.length() && info.description[0] == QLatin1Char( '<' ) ) );
+ addChildElement(doc, infoE, QLatin1String( "Url" ), info.url.toString());
+ }
+
+ QFile file( fileName );
+ if ( !file.open( QFile::WriteOnly ) )
+ {
+ error = UpdateSourcesInfo::CouldNotSaveChangesError;
+ errorMessage = tr("Could not save changes to \"%1\": %2").arg(fileName, file.errorString());
+ return;
+ }
+
+ QTextStream stream( &file );
+ doc.save( stream, 2 );
+ stream.flush();
+ file.close();
+
+ if ( file.error() != QFile::NoError )
+ {
+ error = UpdateSourcesInfo::CouldNotSaveChangesError;
+ errorMessage = tr("Could not save changes to \"%1\": %2").arg(fileName, file.errorString());
+ return;
+ }
+
+ //if there was a write error before, clear the error, as the write was successful now
+ if ( hadSaveError )
+ clearError();
+
+ modified = false;
+}
+
+void KDUpdater::UpdateSourcesInfo::UpdateSourcesInfoData::addUpdateSourceFrom( const QDomElement & element )
+{
+ if( element.tagName() != QLatin1String( "UpdateSource" ) )
+ return;
+
+ QDomNodeList childNodes = element.childNodes();
+ if(!childNodes.count())
+ return;
+
+ KDUpdater::UpdateSourceInfo info;
+
+ for(int i=0; i<childNodes.count(); i++)
+ {
+ QDomNode childNode = childNodes.item(i);
+ QDomElement childNodeE = childNode.toElement();
+ if( childNodeE.isNull() )
+ continue;
+
+ if( childNodeE.tagName() == QLatin1String( "Name" ) )
+ info.name = childNodeE.text();
+ else if( childNodeE.tagName() == QLatin1String( "Title" ) )
+ info.title = childNodeE.text();
+ else if( childNodeE.tagName() == QLatin1String( "Description" ) )
+ info.description = childNodeE.text();
+ else if( childNodeE.tagName() == QLatin1String( "Url" ) )
+ info.url = childNodeE.text();
+ }
+
+ this->updateSourceInfoList.append(info);
+}
+
+void KDUpdater::UpdateSourcesInfo::UpdateSourcesInfoData::addChildElement( QDomDocument & doc, QDomElement & parentE, const QString & tagName, const QString & text, bool htmlText )
+{
+ QDomElement childE = doc.createElement(tagName);
+ parentE.appendChild(childE);
+
+ if( htmlText )
+ {
+ QDomCDATASection textE = doc.createCDATASection(text);
+ childE.appendChild(textE);
+ }
+ else
+ {
+ QDomText textE = doc.createTextNode(text);
+ childE.appendChild(textE);
+ }
+}
+
+/*!
+ \ingroup kdupdater
+ \struct KDUpdater::UpdateSourceInfo kdupdaterupdatesourcesinfo.h KDUpdaterUpdateSourcesInfo
+ \brief Describes a single update source
+
+ An update source is a repository that contains updates applicable for the application.
+ This structure describes a single update source in terms of name, title, description, url and priority.
+*/
+
+/*!
+ \var QString KDUpdater::UpdateSourceInfo::name
+*/
+
+/*!
+ \var QString KDUpdater::UpdateSourceInfo::title
+*/
+
+/*!
+ \var QString KDUpdater::UpdateSourceInfo::description
+*/
+
+/*!
+ \var QUrl KDUpdater::UpdateSourceInfo::url
+*/
+
+/*!
+ \var QUrl KDUpdater::UpdateSourceInfo::priority
+*/
+
+bool KDUpdater::operator==( const UpdateSourceInfo & lhs, const UpdateSourceInfo & rhs )
+{
+ return (lhs.name == rhs.name) && (lhs.title == rhs.title) &&
+ (lhs.description == rhs.description) && (lhs.url == rhs.url);
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesourcesinfo.h b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesourcesinfo.h
new file mode 100644
index 000000000..231002ee0
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesourcesinfo.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef KD_UPDATER_UPDATE_SOURCES_INFO_H
+#define KD_UPDATER_UPDATE_SOURCES_INFO_H
+
+#include "kdupdater.h"
+
+#include <QObject>
+#include <QVariant>
+#include <QUrl>
+
+namespace KDUpdater
+{
+ class Application;
+
+ struct KDTOOLS_UPDATER_EXPORT UpdateSourceInfo
+ {
+ UpdateSourceInfo() : priority(-1) { }
+
+ QString name;
+ QString title;
+ QString description;
+ QUrl url;
+ int priority;
+
+ };
+
+ KDTOOLS_UPDATER_EXPORT bool operator==( const UpdateSourceInfo & lhs, const UpdateSourceInfo & rhs );
+ inline bool operator!= ( const UpdateSourceInfo & lhs, const UpdateSourceInfo & rhs ) {
+ return !operator==( lhs, rhs );
+ }
+
+ class KDTOOLS_UPDATER_EXPORT UpdateSourcesInfo : public QObject
+ {
+ Q_OBJECT
+
+ public:
+ ~UpdateSourcesInfo();
+
+ enum Error
+ {
+ NoError=0,
+ NotYetReadError,
+ CouldNotReadSourceFileError,
+ InvalidXmlError,
+ InvalidContentError,
+ CouldNotSaveChangesError
+ };
+
+ Application* application() const;
+
+ bool isValid() const;
+ QString errorString() const;
+ Error error() const;
+
+ bool isModified() const;
+ void setModified(bool modified);
+
+ void setFileName(const QString& fileName);
+ QString fileName() const;
+
+ int updateSourceInfoCount() const;
+ UpdateSourceInfo updateSourceInfo(int index) const;
+
+ void addUpdateSourceInfo(const UpdateSourceInfo& info);
+ void removeUpdateSourceInfo(const UpdateSourceInfo& info);
+ void removeUpdateSourceInfoAt(int index);
+ void setUpdateSourceInfoAt(int index, const UpdateSourceInfo& info);
+
+ protected:
+ explicit UpdateSourcesInfo(Application* application);
+
+ public Q_SLOTS:
+ void refresh();
+
+ Q_SIGNALS:
+ void reset();
+ void updateSourceInfoAdded(const UpdateSourceInfo& info);
+ void updateSourceInfoRemoved(const UpdateSourceInfo& info);
+ void updateSourceInfoChanged(const UpdateSourceInfo& newInfo,
+ const UpdateSourceInfo& oldInfo);
+
+ private:
+ friend class Application;
+ struct UpdateSourcesInfoData;
+ UpdateSourcesInfoData* d;
+ };
+}
+
+Q_DECLARE_METATYPE(KDUpdater::UpdateSourceInfo)
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesourcesview.cpp b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesourcesview.cpp
new file mode 100644
index 000000000..aec942614
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesourcesview.cpp
@@ -0,0 +1,375 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdupdaterupdatesourcesview.h"
+#include "kdupdaterupdatesourcesinfo.h"
+#include "ui_addupdatesourcedialog.h"
+
+#include <QMessageBox>
+#include <QContextMenuEvent>
+#include <QAction>
+#include <QMenu>
+
+/*!
+ \ingroup kdupdater
+ \class KDUpdater::UpdateSourcesView kdupdaterupdatesourcesview.h KDUpdaterUpdateSourcesView
+ \brief A widget that helps view and/or edit \ref KDUpdater::UpdateSourcesInfo
+
+ \ref KDUpdater::UpdateSourcesInfo, associated with \ref KDUpdater::Application, contains information
+ about all the update sources from which the application can download and install updates.
+ This widget helps view and edit update sources information.
+
+ \image html updatesourcesview.jpg
+
+ The widget provides the following slots for editing update sources information
+ \ref addNewSource()
+ \ref editCurrentSource()
+ \ref removeCurrentSource()
+
+ You can include this widget within another form or dialog and connect to these slots which make
+ use of an inbuilt dialog box to add/edit update sources. Shown below is a screenshot of the
+ inbuilt dialog box.
+
+ \image html editupdatesource.jpg
+
+ Alternatively you can also use your own dialog box and directly update \ref KDUpdater::UpdateSourcesInfo.
+ This widget connects to \ref KDUpdater::UpdateSourcesInfo signals and ensures that the data it displays
+ is always kept updated.
+
+ The widget provides a context menu using which you can add/remove/edit update sources. Shown below is a
+ screenshot of the context menu.
+
+ \image html updatesourcesview_contextmenu.jpg
+*/
+
+struct KDUpdater::UpdateSourcesView::UpdateSourcesViewData
+{
+ UpdateSourcesViewData( UpdateSourcesView* qq ) :
+ q( qq ),
+ updateSourcesInfo(0)
+ {}
+
+ UpdateSourcesView* q;
+ UpdateSourcesInfo* updateSourcesInfo;
+};
+
+/*!
+ Constructor
+*/
+KDUpdater::UpdateSourcesView::UpdateSourcesView(QWidget* parent)
+ : QTreeWidget(parent),
+ d(new KDUpdater::UpdateSourcesView::UpdateSourcesViewData( this ) )
+{
+ setColumnCount(3);
+ setHeaderLabels( QStringList() << tr("Name") << tr("Title") << tr("URL") );
+ setRootIsDecorated(false);
+
+ connect(this, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(editCurrentSource()));
+}
+
+/*!
+ Destructor
+*/
+KDUpdater::UpdateSourcesView::~UpdateSourcesView()
+{
+ delete d;
+}
+
+/*!
+ Sets the \ref KDUpdater::UpdateSourcesInfo object whose information this widget should show.
+
+ \code
+ KDUpdater::Application application;
+
+ KDUpdater::UpdateSourcesView updatesView;
+ updatesView.setUpdateSourcesInfo( application.updateSourcesInfo() );
+ updatesView.show();
+ \endcode
+*/
+void KDUpdater::UpdateSourcesView::setUpdateSourcesInfo(KDUpdater::UpdateSourcesInfo* info)
+{
+ if( d->updateSourcesInfo == info )
+ return;
+
+ if(d->updateSourcesInfo)
+ disconnect(d->updateSourcesInfo, 0, this, 0);
+
+ d->updateSourcesInfo = info;
+ if(d->updateSourcesInfo)
+ {
+ connect(d->updateSourcesInfo, SIGNAL(reset()), this, SLOT(refresh()));
+ connect(d->updateSourcesInfo, SIGNAL(updateSourceInfoAdded(UpdateSourceInfo)),
+ this, SLOT(slotUpdateSourceInfoAdded(UpdateSourceInfo)));
+ connect(d->updateSourcesInfo, SIGNAL(updateSourceInfoRemoved(UpdateSourceInfo)),
+ this, SLOT(slotUpdateSourceInfoRemoved(UpdateSourceInfo)));
+ connect(d->updateSourcesInfo, SIGNAL(updateSourceInfoChanged(UpdateSourceInfo,UpdateSourceInfo)),
+ this, SLOT(slotUpdateSourceInfoChanged(UpdateSourceInfo,UpdateSourceInfo)));
+ }
+
+ refresh();
+}
+
+/*!
+ Returns a pointer to the \ref KDUpdater::UpdateSourcesInfo object whose information this
+ widget is showing.
+*/
+KDUpdater::UpdateSourcesInfo* KDUpdater::UpdateSourcesView::updateSourcesInfo() const
+{
+ return d->updateSourcesInfo;
+}
+
+/*!
+ Returns the index of the currently selected update source in the widget. You can use this
+ index along with \ref KDUpdater::UpdateSourcesInfo::updateSourceInfo() method to get hold
+ of the update source info.
+*/
+int KDUpdater::UpdateSourcesView::currentUpdateSourceInfoIndex() const
+{
+ if( !d->updateSourcesInfo )
+ return -1;
+
+ QTreeWidgetItem* item = this->currentItem();
+ if( !item )
+ return -1;
+
+ int index = this->indexOfTopLevelItem(item);
+ if( index < 0 )
+ return -1;
+
+ return index;
+}
+
+/*!
+ Call this slot to reload the updates information. By default this slot is connected to
+ \ref KDUpdater::UpdateSourcesInfo::reset() signal in \ref setUpdateSourcesInfo().
+*/
+void KDUpdater::UpdateSourcesView::refresh()
+{
+ this->clear();
+
+ if( !d->updateSourcesInfo )
+ return;
+
+ for(int i=0; i<d->updateSourcesInfo->updateSourceInfoCount(); i++)
+ {
+ KDUpdater::UpdateSourceInfo info = d->updateSourcesInfo->updateSourceInfo(i);
+ QTreeWidgetItem* item = new QTreeWidgetItem(this);
+ item->setText(0, info.name);
+ item->setText(1, info.title);
+ item->setText(2, info.url.toString());
+ item->setData(0, Qt::UserRole, qVariantFromValue<KDUpdater::UpdateSourceInfo>(info));
+ }
+
+ resizeColumnToContents(0);
+}
+
+/*!
+ Call this slot to make use of the in-built dialog box to add a new update source. Shown
+ below is a screenshot of the in-built dialog box.
+
+ \image html addupdatesource.jpg
+*/
+void KDUpdater::UpdateSourcesView::addNewSource()
+{
+ if( !d->updateSourcesInfo )
+ return;
+
+ QDialog dialog(this);
+ Ui::AddUpdateSourceDialog ui;
+ ui.setupUi(&dialog);
+
+ while(1)
+ {
+ if( dialog.exec() == QDialog::Rejected )
+ return;
+
+ if(ui.txtName->text().isEmpty() || ui.txtUrl->text().isEmpty())
+ {
+ QMessageBox::information(this, tr("Invalid Update Source Info"),
+ tr("A valid update source name and url has to be provided"));
+ continue;
+ }
+
+ break;
+ }
+
+ KDUpdater::UpdateSourceInfo newInfo;
+ newInfo.name = ui.txtName->text();
+ newInfo.title = ui.txtTitle->text();
+ newInfo.description = ui.txtDescription->toPlainText(); // FIXME: This should perhaps be toHtml
+ newInfo.url = QUrl(ui.txtUrl->text());
+
+ d->updateSourcesInfo->addUpdateSourceInfo(newInfo);
+}
+
+/*!
+ Call this slot to delete the currently selected update source.
+*/
+void KDUpdater::UpdateSourcesView::removeCurrentSource()
+{
+ if( !d->updateSourcesInfo )
+ return;
+
+ QTreeWidgetItem* item = this->currentItem();
+ if( !item )
+ return;
+
+ int index = this->indexOfTopLevelItem(item);
+ if( index < 0 )
+ return;
+
+ d->updateSourcesInfo->removeUpdateSourceInfoAt(index);
+}
+
+/*!
+ Call this slot to edit the currently selected update source, using the in-built edit
+ update source dialog box. Shown below is a screenshot of the edit update source dialog
+ box.
+
+ \image html editupdatesource.jpg
+*/
+void KDUpdater::UpdateSourcesView::editCurrentSource()
+{
+ if( !d->updateSourcesInfo )
+ return;
+
+ QTreeWidgetItem* item = this->currentItem();
+ if( !item )
+ return;
+
+ int index = this->indexOfTopLevelItem(item);
+ if( index < 0 )
+ return;
+
+ KDUpdater::UpdateSourceInfo info = item->data(0, Qt::UserRole).value<KDUpdater::UpdateSourceInfo>();
+
+ QDialog dialog(this);
+ Ui::AddUpdateSourceDialog ui;
+ ui.setupUi(&dialog);
+ ui.txtName->setText(info.name);
+ ui.txtTitle->setText(info.title);
+ ui.txtDescription->setPlainText(info.description); // FIXME: This should perhaps be setHtml
+ ui.txtUrl->setText(info.url.toString());
+ dialog.setWindowTitle(tr("Edit Update Source"));
+
+ if( dialog.exec() == QDialog::Rejected )
+ return;
+
+ KDUpdater::UpdateSourceInfo newInfo;
+ newInfo.name = ui.txtName->text();
+ newInfo.title = ui.txtTitle->text();
+ newInfo.description = ui.txtDescription->toPlainText(); // FIXME: This should perhaps be setHtml
+ newInfo.url = QUrl(ui.txtUrl->text());
+
+ d->updateSourcesInfo->setUpdateSourceInfoAt(index, newInfo);
+}
+
+/*!
+ \internal
+*/
+void KDUpdater::UpdateSourcesView::slotUpdateSourceInfoAdded(const KDUpdater::UpdateSourceInfo &info)
+{
+ if( !d->updateSourcesInfo )
+ return;
+
+ QTreeWidgetItem* item = new QTreeWidgetItem(this);
+ item->setText(0, info.name);
+ item->setText(1, info.title);
+ item->setText(2, info.url.toString());
+ item->setData(0, Qt::UserRole, qVariantFromValue<KDUpdater::UpdateSourceInfo>(info));
+}
+
+/*!
+ \internal
+*/
+void KDUpdater::UpdateSourcesView::slotUpdateSourceInfoRemoved(const KDUpdater::UpdateSourceInfo &info)
+{
+ if( !d->updateSourcesInfo )
+ return;
+
+ QTreeWidgetItem* item = 0;
+ for(int i=0; i<topLevelItemCount(); i++)
+ {
+ item = topLevelItem(i);
+ KDUpdater::UpdateSourceInfo itemInfo = item->data(0, Qt::UserRole).value<KDUpdater::UpdateSourceInfo>();
+ if(itemInfo == info)
+ break;
+ item = 0;
+ }
+
+ if( !item )
+ return;
+
+ delete item;
+}
+
+/*!
+ \internal
+*/
+void KDUpdater::UpdateSourcesView::slotUpdateSourceInfoChanged (const KDUpdater::UpdateSourceInfo &newInfo,
+ const KDUpdater::UpdateSourceInfo &oldInfo)
+{
+ if( !d->updateSourcesInfo )
+ return;
+
+ QTreeWidgetItem* item = 0;
+ for(int i=0; i<topLevelItemCount(); i++)
+ {
+ item = topLevelItem(i);
+ KDUpdater::UpdateSourceInfo itemInfo = item->data(0, Qt::UserRole).value<KDUpdater::UpdateSourceInfo>();
+ if(itemInfo == oldInfo)
+ break;
+ item = 0;
+ }
+
+ if( !item )
+ return;
+
+ item->setText(0, newInfo.name);
+ item->setText(1, newInfo.title);
+ item->setText(2, newInfo.url.toString());
+ item->setData(0, Qt::UserRole, qVariantFromValue<KDUpdater::UpdateSourceInfo>(newInfo));
+}
+
+/*!
+ \internal
+*/
+void KDUpdater::UpdateSourcesView::contextMenuEvent(QContextMenuEvent* e)
+{
+ QTreeWidgetItem* item = this->itemAt( e->pos() );
+
+ QMenu menu;
+ QAction* addAction = menu.addAction(tr("&Add Source"));
+ QAction* editAction = item ? menu.addAction(tr("&Edit Source")) : 0;
+ QAction* remAction = item ? menu.addAction(tr("&Remove Source")) : 0;
+
+ QAction* result = menu.exec( QCursor::pos() );
+ if( !result )
+ return;
+
+ if( result == addAction )
+ this->addNewSource();
+ else if( result == remAction )
+ this->removeCurrentSource();
+ else if( result == editAction )
+ this->editCurrentSource();
+}
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesourcesview.h b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesourcesview.h
new file mode 100644
index 000000000..c2c840d72
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterupdatesourcesview.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#ifndef KD_UPDATER_UPDATE_SOURCES_VIEW_H
+#define KD_UPDATER_UPDATE_SOURCES_VIEW_H
+
+#include "kdupdater.h"
+#include <QTreeWidget>
+
+namespace KDUpdater
+{
+ struct UpdateSourceInfo;
+ class UpdateSourcesInfo;
+
+ class KDTOOLS_UPDATER_EXPORT UpdateSourcesView : public QTreeWidget
+ {
+ Q_OBJECT
+
+ public:
+ explicit UpdateSourcesView(QWidget* parent=0);
+ ~UpdateSourcesView();
+
+ void setUpdateSourcesInfo(UpdateSourcesInfo* info);
+ UpdateSourcesInfo* updateSourcesInfo() const;
+
+ int currentUpdateSourceInfoIndex() const;
+
+ public Q_SLOTS:
+ void refresh();
+ void addNewSource();
+ void removeCurrentSource();
+ void editCurrentSource();
+
+ protected:
+ void contextMenuEvent(QContextMenuEvent* e);
+
+ private Q_SLOTS:
+ void slotUpdateSourceInfoAdded(const UpdateSourceInfo &info);
+ void slotUpdateSourceInfoRemoved(const UpdateSourceInfo &info);
+ void slotUpdateSourceInfoChanged(const UpdateSourceInfo &newInfo,
+ const UpdateSourceInfo &oldInfo);
+
+ private:
+ struct UpdateSourcesViewData;
+ UpdateSourcesViewData* d;
+ };
+};
+
+#endif
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/updatesdialog.ui b/installerbuilder/libinstaller/kdtools/KDUpdater/updatesdialog.ui
new file mode 100644
index 000000000..52162109e
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/updatesdialog.ui
@@ -0,0 +1,245 @@
+<ui version="4.0" >
+ <class>UpdatesDialog</class>
+ <widget class="QDialog" name="UpdatesDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>555</width>
+ <height>478</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Update</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout" >
+ <property name="sizeConstraint" >
+ <enum>QLayout::SetMinAndMaxSize</enum>
+ </property>
+ <item row="0" column="0" >
+ <widget class="QLabel" name="pixmapLabel" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Minimum" hsizetype="Minimum" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize" >
+ <size>
+ <width>96</width>
+ <height>96</height>
+ </size>
+ </property>
+ <property name="text" >
+ <string/>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2" colspan="2" >
+ <widget class="QLabel" name="descriptionLabel" >
+ <property name="minimumSize" >
+ <size>
+ <width>400</width>
+ <height>96</height>
+ </size>
+ </property>
+ <property name="text" >
+ <string/>
+ </property>
+ <property name="textFormat" >
+ <enum>Qt::RichText</enum>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <property name="wordWrap" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2" colspan="2" >
+ <layout class="QVBoxLayout" name="verticalLayout_2" >
+ <item>
+ <widget class="QWidget" native="1" name="releaseNotesGroup" >
+ <layout class="QVBoxLayout" name="verticalLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>&lt;b>Release Notes:&lt;/b></string>
+ </property>
+ <property name="textFormat" >
+ <enum>Qt::RichText</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="KDUPDATERVIEW" native="1" name="releaseNotesView" >
+ <property name="minimumSize" >
+ <size>
+ <width>400</width>
+ <height>200</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QWidget" native="1" name="packageSwitchBar" >
+ <layout class="QHBoxLayout" name="horizontalLayout" >
+ <property name="spacing" >
+ <number>0</number>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QCheckBox" name="packageUpdateCheckBox" >
+ <property name="text" >
+ <string>Update the current package</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>296</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QToolButton" name="previousPackageButton" >
+ <property name="text" >
+ <string/>
+ </property>
+ <property name="iconSize" >
+ <size>
+ <width>8</width>
+ <height>8</height>
+ </size>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ <property name="arrowType" >
+ <enum>Qt::LeftArrow</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="currentPackageLabel" >
+ <property name="text" >
+ <string>N</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_2" >
+ <property name="text" >
+ <string>/</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="totalPackageLabel" >
+ <property name="text" >
+ <string>M</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="nextPackageButton" >
+ <property name="text" >
+ <string/>
+ </property>
+ <property name="iconSize" >
+ <size>
+ <width>8</width>
+ <height>8</height>
+ </size>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ <property name="arrowType" >
+ <enum>Qt::RightArrow</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="3" >
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>KDUPDATERVIEW</class>
+ <extends>QWidget</extends>
+ <header>qwidget.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>UpdatesDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>UpdatesDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/installerbuilder/libinstaller/kdtools/LICENSE.LGPL b/installerbuilder/libinstaller/kdtools/LICENSE.LGPL
new file mode 100644
index 000000000..ea164db15
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/LICENSE.LGPL
@@ -0,0 +1,488 @@
+
+ The KD Tools Library is Copyright (C) 2001-2009 Klarälvdalens Datakonsult AB.
+
+ You may use, distribute and copy the KD Tools Library under the terms of
+ GNU Library General Public License version 2, which is displayed below.
+
+-------------------------------------------------------------------------
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!