From de8b7ede25558e0cd97cf3cfea039158b71ad8e2 Mon Sep 17 00:00:00 2001 From: Karsten Heimrich Date: Tue, 14 Jul 2015 13:52:28 +0200 Subject: Rename files. Remove {kd} prefix. Remove {kdupdater} prefix. Change-Id: I88c93cab718f4659296d5f7f562beefd747a366f Reviewed-by: Jarek Kobus --- src/libs/installer/component.cpp | 2 +- .../installer/createlocalrepositoryoperation.cpp | 2 +- src/libs/installer/downloadarchivesjob.cpp | 4 +- src/libs/installer/downloadarchivesjob.h | 2 +- src/libs/installer/downloadfiletask.h | 2 +- src/libs/installer/init.cpp | 4 +- src/libs/installer/metadatajob.h | 2 +- src/libs/installer/packagemanagercore.cpp | 4 +- src/libs/installer/packagemanagercore_p.cpp | 6 +- src/libs/installer/packagemanagercore_p.h | 4 +- src/libs/installer/packagemanagergui.cpp | 2 +- src/libs/installer/packagemanagerpagefactory.h | 2 +- src/libs/installer/packagemanagerproxyfactory.h | 2 +- src/libs/installer/qinstallerglobal.h | 4 +- src/libs/installer/repository.cpp | 2 +- src/libs/installer/selfrestartoperation.cpp | 2 +- src/libs/installer/settingsoperation.cpp | 2 +- src/libs/installer/sysinfo_win.cpp | 2 +- src/libs/installer/testrepository.h | 3 +- src/libs/kdtools/filedownloader.cpp | 1407 ++++++++++++++++++++ src/libs/kdtools/filedownloader.h | 147 ++ src/libs/kdtools/filedownloader_p.h | 150 +++ src/libs/kdtools/filedownloaderfactory.cpp | 198 +++ src/libs/kdtools/filedownloaderfactory.h | 107 ++ src/libs/kdtools/genericfactory.cpp | 117 ++ src/libs/kdtools/genericfactory.h | 91 ++ src/libs/kdtools/job.cpp | 248 ++++ src/libs/kdtools/job.h | 121 ++ src/libs/kdtools/kdgenericfactory.cpp | 117 -- src/libs/kdtools/kdgenericfactory.h | 91 -- src/libs/kdtools/kdjob.cpp | 248 ---- src/libs/kdtools/kdjob.h | 121 -- src/libs/kdtools/kdlockfile.cpp | 62 - src/libs/kdtools/kdlockfile.h | 59 - src/libs/kdtools/kdlockfile_p.h | 71 - src/libs/kdtools/kdlockfile_unix.cpp | 95 -- src/libs/kdtools/kdlockfile_win.cpp | 93 -- src/libs/kdtools/kdrunoncechecker.cpp | 110 -- src/libs/kdtools/kdrunoncechecker.h | 63 - src/libs/kdtools/kdselfrestarter.cpp | 99 -- src/libs/kdtools/kdselfrestarter.h | 55 - src/libs/kdtools/kdsysinfo.cpp | 161 --- src/libs/kdtools/kdsysinfo.h | 97 -- src/libs/kdtools/kdsysinfo_mac.cpp | 161 --- src/libs/kdtools/kdsysinfo_win.cpp | 2 +- src/libs/kdtools/kdsysinfo_x11.cpp | 145 -- src/libs/kdtools/kdtools.pri | 85 +- src/libs/kdtools/kdupdater.h | 54 - src/libs/kdtools/kdupdaterfiledownloader.cpp | 1407 -------------------- src/libs/kdtools/kdupdaterfiledownloader.h | 147 -- src/libs/kdtools/kdupdaterfiledownloader_p.h | 150 --- .../kdtools/kdupdaterfiledownloaderfactory.cpp | 198 --- src/libs/kdtools/kdupdaterfiledownloaderfactory.h | 107 -- src/libs/kdtools/kdupdatertask.cpp | 455 ------- src/libs/kdtools/kdupdatertask.h | 120 -- src/libs/kdtools/kdupdaterupdate.cpp | 68 - src/libs/kdtools/kdupdaterupdate.h | 62 - src/libs/kdtools/kdupdaterupdatefinder.cpp | 640 --------- src/libs/kdtools/kdupdaterupdatefinder.h | 76 -- src/libs/kdtools/kdupdaterupdateoperation.cpp | 528 -------- src/libs/kdtools/kdupdaterupdateoperation.h | 113 -- .../kdtools/kdupdaterupdateoperationfactory.cpp | 96 -- src/libs/kdtools/kdupdaterupdateoperationfactory.h | 70 - src/libs/kdtools/kdupdaterupdateoperations.cpp | 786 ----------- src/libs/kdtools/kdupdaterupdateoperations.h | 131 -- src/libs/kdtools/kdupdaterupdatesinfo.cpp | 250 ---- src/libs/kdtools/kdupdaterupdatesinfo_p.h | 91 -- src/libs/kdtools/kdupdaterupdatesinfodata_p.h | 73 - src/libs/kdtools/localpackagehub.h | 2 +- src/libs/kdtools/lockfile.cpp | 62 + src/libs/kdtools/lockfile.h | 59 + src/libs/kdtools/lockfile_p.h | 71 + src/libs/kdtools/lockfile_unix.cpp | 95 ++ src/libs/kdtools/lockfile_win.cpp | 93 ++ src/libs/kdtools/runoncechecker.cpp | 110 ++ src/libs/kdtools/runoncechecker.h | 63 + src/libs/kdtools/selfrestarter.cpp | 99 ++ src/libs/kdtools/selfrestarter.h | 55 + src/libs/kdtools/sysinfo.cpp | 161 +++ src/libs/kdtools/sysinfo.h | 97 ++ src/libs/kdtools/sysinfo_mac.cpp | 161 +++ src/libs/kdtools/sysinfo_x11.cpp | 145 ++ src/libs/kdtools/task.cpp | 455 +++++++ src/libs/kdtools/task.h | 120 ++ src/libs/kdtools/update.cpp | 68 + src/libs/kdtools/update.h | 62 + src/libs/kdtools/updatefinder.cpp | 640 +++++++++ src/libs/kdtools/updatefinder.h | 76 ++ src/libs/kdtools/updateoperation.cpp | 528 ++++++++ src/libs/kdtools/updateoperation.h | 113 ++ src/libs/kdtools/updateoperationfactory.cpp | 97 ++ src/libs/kdtools/updateoperationfactory.h | 70 + src/libs/kdtools/updateoperations.cpp | 786 +++++++++++ src/libs/kdtools/updateoperations.h | 131 ++ src/libs/kdtools/updater.h | 54 + src/libs/kdtools/updatesinfo.cpp | 250 ++++ src/libs/kdtools/updatesinfo_p.h | 91 ++ src/libs/kdtools/updatesinfodata_p.h | 73 + src/sdk/installerbase.cpp | 6 +- src/sdk/main.cpp | 2 +- src/sdk/updatechecker.cpp | 2 +- 101 files changed, 7549 insertions(+), 7544 deletions(-) create mode 100644 src/libs/kdtools/filedownloader.cpp create mode 100644 src/libs/kdtools/filedownloader.h create mode 100644 src/libs/kdtools/filedownloader_p.h create mode 100644 src/libs/kdtools/filedownloaderfactory.cpp create mode 100644 src/libs/kdtools/filedownloaderfactory.h create mode 100644 src/libs/kdtools/genericfactory.cpp create mode 100644 src/libs/kdtools/genericfactory.h create mode 100644 src/libs/kdtools/job.cpp create mode 100644 src/libs/kdtools/job.h delete mode 100644 src/libs/kdtools/kdgenericfactory.cpp delete mode 100644 src/libs/kdtools/kdgenericfactory.h delete mode 100644 src/libs/kdtools/kdjob.cpp delete mode 100644 src/libs/kdtools/kdjob.h delete mode 100644 src/libs/kdtools/kdlockfile.cpp delete mode 100644 src/libs/kdtools/kdlockfile.h delete mode 100644 src/libs/kdtools/kdlockfile_p.h delete mode 100644 src/libs/kdtools/kdlockfile_unix.cpp delete mode 100644 src/libs/kdtools/kdlockfile_win.cpp delete mode 100644 src/libs/kdtools/kdrunoncechecker.cpp delete mode 100644 src/libs/kdtools/kdrunoncechecker.h delete mode 100644 src/libs/kdtools/kdselfrestarter.cpp delete mode 100644 src/libs/kdtools/kdselfrestarter.h delete mode 100644 src/libs/kdtools/kdsysinfo.cpp delete mode 100644 src/libs/kdtools/kdsysinfo.h delete mode 100644 src/libs/kdtools/kdsysinfo_mac.cpp delete mode 100644 src/libs/kdtools/kdsysinfo_x11.cpp delete mode 100644 src/libs/kdtools/kdupdater.h delete mode 100644 src/libs/kdtools/kdupdaterfiledownloader.cpp delete mode 100644 src/libs/kdtools/kdupdaterfiledownloader.h delete mode 100644 src/libs/kdtools/kdupdaterfiledownloader_p.h delete mode 100644 src/libs/kdtools/kdupdaterfiledownloaderfactory.cpp delete mode 100644 src/libs/kdtools/kdupdaterfiledownloaderfactory.h delete mode 100644 src/libs/kdtools/kdupdatertask.cpp delete mode 100644 src/libs/kdtools/kdupdatertask.h delete mode 100644 src/libs/kdtools/kdupdaterupdate.cpp delete mode 100644 src/libs/kdtools/kdupdaterupdate.h delete mode 100644 src/libs/kdtools/kdupdaterupdatefinder.cpp delete mode 100644 src/libs/kdtools/kdupdaterupdatefinder.h delete mode 100644 src/libs/kdtools/kdupdaterupdateoperation.cpp delete mode 100644 src/libs/kdtools/kdupdaterupdateoperation.h delete mode 100644 src/libs/kdtools/kdupdaterupdateoperationfactory.cpp delete mode 100644 src/libs/kdtools/kdupdaterupdateoperationfactory.h delete mode 100644 src/libs/kdtools/kdupdaterupdateoperations.cpp delete mode 100644 src/libs/kdtools/kdupdaterupdateoperations.h delete mode 100644 src/libs/kdtools/kdupdaterupdatesinfo.cpp delete mode 100644 src/libs/kdtools/kdupdaterupdatesinfo_p.h delete mode 100644 src/libs/kdtools/kdupdaterupdatesinfodata_p.h create mode 100644 src/libs/kdtools/lockfile.cpp create mode 100644 src/libs/kdtools/lockfile.h create mode 100644 src/libs/kdtools/lockfile_p.h create mode 100644 src/libs/kdtools/lockfile_unix.cpp create mode 100644 src/libs/kdtools/lockfile_win.cpp create mode 100644 src/libs/kdtools/runoncechecker.cpp create mode 100644 src/libs/kdtools/runoncechecker.h create mode 100644 src/libs/kdtools/selfrestarter.cpp create mode 100644 src/libs/kdtools/selfrestarter.h create mode 100644 src/libs/kdtools/sysinfo.cpp create mode 100644 src/libs/kdtools/sysinfo.h create mode 100644 src/libs/kdtools/sysinfo_mac.cpp create mode 100644 src/libs/kdtools/sysinfo_x11.cpp create mode 100644 src/libs/kdtools/task.cpp create mode 100644 src/libs/kdtools/task.h create mode 100644 src/libs/kdtools/update.cpp create mode 100644 src/libs/kdtools/update.h create mode 100644 src/libs/kdtools/updatefinder.cpp create mode 100644 src/libs/kdtools/updatefinder.h create mode 100644 src/libs/kdtools/updateoperation.cpp create mode 100644 src/libs/kdtools/updateoperation.h create mode 100644 src/libs/kdtools/updateoperationfactory.cpp create mode 100644 src/libs/kdtools/updateoperationfactory.h create mode 100644 src/libs/kdtools/updateoperations.cpp create mode 100644 src/libs/kdtools/updateoperations.h create mode 100644 src/libs/kdtools/updater.h create mode 100644 src/libs/kdtools/updatesinfo.cpp create mode 100644 src/libs/kdtools/updatesinfo_p.h create mode 100644 src/libs/kdtools/updatesinfodata_p.h (limited to 'src') diff --git a/src/libs/installer/component.cpp b/src/libs/installer/component.cpp index 9b8c2a430..cabaa9231 100644 --- a/src/libs/installer/component.cpp +++ b/src/libs/installer/component.cpp @@ -43,7 +43,7 @@ #include "remoteclient.h" #include "settings.h" -#include +#include "updateoperationfactory.h" #include diff --git a/src/libs/installer/createlocalrepositoryoperation.cpp b/src/libs/installer/createlocalrepositoryoperation.cpp index 5ce08c26f..c4101c3d2 100644 --- a/src/libs/installer/createlocalrepositoryoperation.cpp +++ b/src/libs/installer/createlocalrepositoryoperation.cpp @@ -45,7 +45,7 @@ #include "packagemanagercore.h" #include "productkeycheck.h" -#include "kdupdaterupdateoperations.h" +#include "updateoperations.h" #include #include diff --git a/src/libs/installer/downloadarchivesjob.cpp b/src/libs/installer/downloadarchivesjob.cpp index 828e7f99a..536a8963f 100644 --- a/src/libs/installer/downloadarchivesjob.cpp +++ b/src/libs/installer/downloadarchivesjob.cpp @@ -39,8 +39,8 @@ #include "packagemanagercore.h" #include "utils.h" -#include "kdupdaterfiledownloader.h" -#include "kdupdaterfiledownloaderfactory.h" +#include "filedownloader.h" +#include "filedownloaderfactory.h" #include #include diff --git a/src/libs/installer/downloadarchivesjob.h b/src/libs/installer/downloadarchivesjob.h index 61600c596..e1359de71 100644 --- a/src/libs/installer/downloadarchivesjob.h +++ b/src/libs/installer/downloadarchivesjob.h @@ -35,7 +35,7 @@ #ifndef DOWNLOADARCHIVESJOB_H #define DOWNLOADARCHIVESJOB_H -#include +#include "job.h" #include diff --git a/src/libs/installer/downloadfiletask.h b/src/libs/installer/downloadfiletask.h index 2d0d4cf41..63134e3be 100644 --- a/src/libs/installer/downloadfiletask.h +++ b/src/libs/installer/downloadfiletask.h @@ -36,7 +36,7 @@ #define DOWNLOADFILETASK_H #include "abstractfiletask.h" -#include "kdupdaterfiledownloaderfactory.h" +#include "filedownloaderfactory.h" #include Q_DECLARE_METATYPE(QAuthenticator) diff --git a/src/libs/installer/init.cpp b/src/libs/installer/init.cpp index cedf93a8b..117eed54f 100644 --- a/src/libs/installer/init.cpp +++ b/src/libs/installer/init.cpp @@ -57,8 +57,8 @@ #include "lib7z_facade.h" #include "utils.h" -#include "kdupdaterupdateoperationfactory.h" -#include "kdupdaterfiledownloaderfactory.h" +#include "updateoperationfactory.h" +#include "filedownloaderfactory.h" #include #include diff --git a/src/libs/installer/metadatajob.h b/src/libs/installer/metadatajob.h index 5dbb5d833..4369c5566 100644 --- a/src/libs/installer/metadatajob.h +++ b/src/libs/installer/metadatajob.h @@ -37,7 +37,7 @@ #include "downloadfiletask.h" #include "fileutils.h" -#include "kdjob.h" +#include "job.h" #include "repository.h" #include diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp index ddd35b974..7ee6f5e06 100644 --- a/src/libs/installer/packagemanagercore.cpp +++ b/src/libs/installer/packagemanagercore.cpp @@ -65,8 +65,8 @@ #include #include -#include "kdsysinfo.h" -#include "kdupdaterupdateoperationfactory.h" +#include "sysinfo.h" +#include "updateoperationfactory.h" #ifdef Q_OS_WIN # include "qt_windows.h" diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp index f240a309f..cfa7574ad 100644 --- a/src/libs/installer/packagemanagercore_p.cpp +++ b/src/libs/installer/packagemanagercore_p.cpp @@ -55,9 +55,9 @@ #include "componentchecker.h" #include "globals.h" -#include "kdselfrestarter.h" -#include "kdupdaterfiledownloaderfactory.h" -#include "kdupdaterupdateoperationfactory.h" +#include "selfrestarter.h" +#include "filedownloaderfactory.h" +#include "updateoperationfactory.h" #include diff --git a/src/libs/installer/packagemanagercore_p.h b/src/libs/installer/packagemanagercore_p.h index 6a7db3edb..62a36f30f 100644 --- a/src/libs/installer/packagemanagercore_p.h +++ b/src/libs/installer/packagemanagercore_p.h @@ -42,8 +42,8 @@ #include "packagesource.h" #include "qinstallerglobal.h" -#include "kdsysinfo.h" -#include "kdupdaterupdatefinder.h" +#include "sysinfo.h" +#include "updatefinder.h" #include diff --git a/src/libs/installer/packagemanagergui.cpp b/src/libs/installer/packagemanagergui.cpp index 116a9e039..22092cfdd 100644 --- a/src/libs/installer/packagemanagergui.cpp +++ b/src/libs/installer/packagemanagergui.cpp @@ -46,7 +46,7 @@ #include "scriptengine.h" #include "productkeycheck.h" -#include "kdsysinfo.h" +#include "sysinfo.h" #include diff --git a/src/libs/installer/packagemanagerpagefactory.h b/src/libs/installer/packagemanagerpagefactory.h index ee8b8ff66..928fc53bc 100644 --- a/src/libs/installer/packagemanagerpagefactory.h +++ b/src/libs/installer/packagemanagerpagefactory.h @@ -35,7 +35,7 @@ #ifndef PACKAGEMANAGERPAGEFACTORY_H #define PACKAGEMANAGERPAGEFACTORY_H -#include "kdgenericfactory.h" +#include "genericfactory.h" #include "qinstallerglobal.h" namespace QInstaller { diff --git a/src/libs/installer/packagemanagerproxyfactory.h b/src/libs/installer/packagemanagerproxyfactory.h index 34b834807..28f53df6e 100644 --- a/src/libs/installer/packagemanagerproxyfactory.h +++ b/src/libs/installer/packagemanagerproxyfactory.h @@ -35,7 +35,7 @@ #ifndef PACKAGEMANAGERPROXYFACTORY_H #define PACKAGEMANAGERPROXYFACTORY_H -#include "kdupdaterfiledownloaderfactory.h" +#include "filedownloaderfactory.h" namespace QInstaller { diff --git a/src/libs/installer/qinstallerglobal.h b/src/libs/installer/qinstallerglobal.h index 4831d99f3..a03daf6a4 100644 --- a/src/libs/installer/qinstallerglobal.h +++ b/src/libs/installer/qinstallerglobal.h @@ -37,8 +37,8 @@ #include -#include -#include +#include "update.h" +#include "updateoperation.h" #include "localpackagehub.h" namespace QInstaller { diff --git a/src/libs/installer/repository.cpp b/src/libs/installer/repository.cpp index 8911b3950..dda22bb59 100644 --- a/src/libs/installer/repository.cpp +++ b/src/libs/installer/repository.cpp @@ -33,7 +33,7 @@ **************************************************************************/ #include "repository.h" -#include "kdupdaterfiledownloaderfactory.h" +#include "filedownloaderfactory.h" #include #include diff --git a/src/libs/installer/selfrestartoperation.cpp b/src/libs/installer/selfrestartoperation.cpp index 4c6965176..7b0358b86 100644 --- a/src/libs/installer/selfrestartoperation.cpp +++ b/src/libs/installer/selfrestartoperation.cpp @@ -35,7 +35,7 @@ #include "selfrestartoperation.h" #include "packagemanagercore.h" -#include +#include "selfrestarter.h" using namespace QInstaller; diff --git a/src/libs/installer/settingsoperation.cpp b/src/libs/installer/settingsoperation.cpp index 9884a95e9..d2d91872c 100644 --- a/src/libs/installer/settingsoperation.cpp +++ b/src/libs/installer/settingsoperation.cpp @@ -33,7 +33,7 @@ **************************************************************************/ #include "settingsoperation.h" #include "packagemanagercore.h" -#include "kdupdaterupdateoperations.h" +#include "updateoperations.h" #include "qsettingswrapper.h" #include diff --git a/src/libs/installer/sysinfo_win.cpp b/src/libs/installer/sysinfo_win.cpp index 969ab69d3..6bca3e304 100644 --- a/src/libs/installer/sysinfo_win.cpp +++ b/src/libs/installer/sysinfo_win.cpp @@ -32,7 +32,7 @@ ** **************************************************************************/ -#include "kdsysinfo.h" +#include "sysinfo.h" #include "link.h" #ifdef Q_CC_MINGW diff --git a/src/libs/installer/testrepository.h b/src/libs/installer/testrepository.h index a056b60e4..4116f1967 100644 --- a/src/libs/installer/testrepository.h +++ b/src/libs/installer/testrepository.h @@ -35,7 +35,7 @@ #define TESTREPOSITORY_H #include "downloadfiletask.h" -#include "kdjob.h" +#include "job.h" #include "repository.h" #include @@ -44,7 +44,6 @@ namespace QInstaller { class PackageManagerCore; -class Repository; class INSTALLER_EXPORT TestRepository : public KDJob { diff --git a/src/libs/kdtools/filedownloader.cpp b/src/libs/kdtools/filedownloader.cpp new file mode 100644 index 000000000..fbc328d50 --- /dev/null +++ b/src/libs/kdtools/filedownloader.cpp @@ -0,0 +1,1407 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "filedownloader_p.h" +#include "filedownloaderfactory.h" +#include "ui_authenticationdialog.h" + +#include "fileutils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace KDUpdater; +using namespace QInstaller; + +static double calcProgress(qint64 done, qint64 total) +{ + return total ? (double(done) / double(total)) : 0; +} + + +// -- KDUpdater::FileDownloader + +/*! + \inmodule kdupdater + \class KDUpdater::FileDownloader + \brief The FileDownloader class is the 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 files from a specific category of sources (such as + \c local, \c ftp, \c http). + + This is an internal class, not a part of the public API. Currently we have the + following subclasses of FileDownloader: + \list + \li HttpDownloader to download files over FTP, HTTP, or HTTPS if Qt is built with SSL. + \li LocalFileDownloader to copy files from the local file system. + \li ResourceFileDownloader to download resource files. + \endlist +*/ + +/*! + \property FileDownloader::autoRemoveDownloadedFile + \brief Whether the downloaded file should be automatically removed after it + is downloaded and the class goes out of scope. +*/ + +/*! + \property FileDownloader::url + \brief The URL to download files from. +*/ + +/*! + \property FileDownloader::scheme + \brief The scheme to use for downloading files. + */ + +/*! + \fn FileDownloader::authenticatorChanged(const QAuthenticator &authenticator) + This signal is emitted when the authenticator changes to \a authenticator. +*/ + +/*! + \fn FileDownloader::canDownload() const = 0 + Returns \c true if the file exists and is readable. +*/ + +/*! + \fn FileDownloader::clone(QObject *parent=0) const = 0 + Clones the local file downloader and assigns it the parent \a parent. +*/ + +/*! + \fn FileDownloader::downloadCanceled() + This signal is emitted if downloading a file is canceled. +*/ + +/*! + \fn FileDownloader::downloadedFileName() const = 0 + Returns the file name of the downloaded file. +*/ + +/*! + \fn FileDownloader::downloadProgress(double progress) + This signal is emitted with the current download \a progress. +*/ + +/*! + \fn FileDownloader::downloadProgress(qint64 bytesReceived, qint64 bytesToReceive) + This signal is emitted with the download progress as the number of received bytes, + \a bytesReceived, and the total size of the file to download, \a bytesToReceive. +*/ + +/*! + \fn FileDownloader::downloadSpeed(qint64 bytesPerSecond) + This signal is emitted with the download speed in bytes per second as \a bytesPerSecond. +*/ + +/*! + \fn FileDownloader::downloadStarted() + This signal is emitted when downloading a file starts. +*/ + +/*! + \fn FileDownloader::downloadStatus(const QString &status) + This signal is emitted with textual representation of the current download \a status in the + following format: "100 MiB of 150 MiB - (DAYS) (HOURS) (MINUTES) (SECONDS) remaining". +*/ + +/*! + \fn FileDownloader::estimatedDownloadTime(int seconds) + This signal is emitted with the estimated download time in \a seconds. +*/ + +/*! + \fn FileDownloader::isDownloaded() const = 0 + Returns \c true if the file is downloaded. +*/ + +/*! + \fn FileDownloader::onError() = 0 + Closes the destination file if an error occurs during copying and stops + the download speed timer. +*/ + +/*! + \fn FileDownloader::onSuccess() = 0 + Closes the destination file after it has been successfully copied and stops + the download speed timer. +*/ + +/*! + \fn FileDownloader::setDownloadedFileName(const QString &name) = 0 + Sets the file name of the downloaded file to \a name. +*/ + +struct KDUpdater::FileDownloader::Private +{ + Private() + : m_hash(QCryptographicHash::Sha1) + , m_assumedSha1Sum("") + , autoRemove(true) + , m_speedTimerInterval(100) + , m_bytesReceived(0) + , m_bytesToReceive(0) + , m_currentSpeedBin(0) + , m_sampleIndex(0) + , m_downloadSpeed(0) + , m_factory(0) + , m_ignoreSslErrors(false) + { + memset(m_samples, 0, sizeof(m_samples)); + } + + ~Private() + { + delete m_factory; + } + + QUrl url; + QString scheme; + + QCryptographicHash m_hash; + QByteArray m_assumedSha1Sum; + + QString errorString; + bool autoRemove; + bool followRedirect; + + QBasicTimer m_timer; + int m_speedTimerInterval; + + qint64 m_bytesReceived; + qint64 m_bytesToReceive; + + mutable qint64 m_samples[50]; + mutable qint64 m_currentSpeedBin; + mutable quint32 m_sampleIndex; + mutable qint64 m_downloadSpeed; + + QAuthenticator m_authenticator; + FileDownloaderProxyFactory *m_factory; + bool m_ignoreSslErrors; +}; + +/*! + Creates a file downloader with the scheme \a scheme and parent \a parent. +*/ +KDUpdater::FileDownloader::FileDownloader(const QString &scheme, QObject *parent) + : QObject(parent) + , d(new Private) +{ + d->scheme = scheme; + d->followRedirect = false; +} + +/*! + Destroys the file downloader. +*/ +KDUpdater::FileDownloader::~FileDownloader() +{ + delete d; +} + +void KDUpdater::FileDownloader::setUrl(const QUrl &url) +{ + d->url = url; +} + +QUrl KDUpdater::FileDownloader::url() const +{ + return d->url; +} + +/*! + Returns the SHA-1 checksum of the downloaded file. +*/ +QByteArray KDUpdater::FileDownloader::sha1Sum() const +{ + return d->m_hash.result(); +} + +/*! + Returns the assumed SHA-1 checksum of the file to download. +*/ +QByteArray KDUpdater::FileDownloader::assumedSha1Sum() const +{ + return d->m_assumedSha1Sum; +} + +/*! + Sets the assumed SHA-1 checksum of the file to download to \a sum. +*/ +void KDUpdater::FileDownloader::setAssumedSha1Sum(const QByteArray &sum) +{ + d->m_assumedSha1Sum = sum; +} + +/*! + Returns an error message. +*/ +QString FileDownloader::errorString() const +{ + return d->errorString; +} + +/*! + Sets the human readable description of the last error that occurred to \a error. Emits the + downloadStatus() and downloadAborted() signals. +*/ +void FileDownloader::setDownloadAborted(const QString &error) +{ + d->errorString = error; + emit downloadStatus(error); + emit downloadAborted(error); +} + +/*! + Sets the download status to \c completed and displays a status message. + + If an assumed SHA-1 checksum is set and the actual calculated checksum does not match it, sets + the status to \c error. If no SHA-1 is assumed, no check is performed, and status is set to + \c success. + + Emits the downloadCompleted() and downloadStatus() signals on success. +*/ +void KDUpdater::FileDownloader::setDownloadCompleted() +{ + if (d->m_assumedSha1Sum.isEmpty() || (d->m_assumedSha1Sum == sha1Sum())) { + onSuccess(); + emit downloadCompleted(); + emit downloadStatus(tr("Download finished.")); + } else { + onError(); + setDownloadAborted(tr("Cryptographic hashes do not match.")); + } +} + +/*! + Emits the downloadCanceled() and downloadStatus() signals. +*/ +void KDUpdater::FileDownloader::setDownloadCanceled() +{ + emit downloadCanceled(); + emit downloadStatus(tr("Download canceled.")); +} + +QString KDUpdater::FileDownloader::scheme() const +{ + return d->scheme; +} + +void KDUpdater::FileDownloader::setScheme(const QString &scheme) +{ + d->scheme = scheme; +} + +void KDUpdater::FileDownloader::setAutoRemoveDownloadedFile(bool val) +{ + d->autoRemove = val; +} + +/*! + Determines that redirects should be followed if \a val is \c true. +*/ +void KDUpdater::FileDownloader::setFollowRedirects(bool val) +{ + d->followRedirect = val; +} + +/*! + Returns whether redirects should be followed. +*/ +bool KDUpdater::FileDownloader::followRedirects() const +{ + return d->followRedirect; +} + +bool KDUpdater::FileDownloader::isAutoRemoveDownloadedFile() const +{ + return d->autoRemove; +} + +/*! + Downloads files. +*/ +void KDUpdater::FileDownloader::download() +{ + QMetaObject::invokeMethod(this, "doDownload", Qt::QueuedConnection); +} + +/*! + Cancels file download. +*/ +void KDUpdater::FileDownloader::cancelDownload() +{ + // Do nothing +} + +/*! + Starts the download speed timer. +*/ +void KDUpdater::FileDownloader::runDownloadSpeedTimer() +{ + if (!d->m_timer.isActive()) + d->m_timer.start(d->m_speedTimerInterval, this); +} + +/*! + Stops the download speed timer. +*/ +void KDUpdater::FileDownloader::stopDownloadSpeedTimer() +{ + d->m_timer.stop(); +} + +/*! + Adds \a sample to the current speed bin. +*/ +void KDUpdater::FileDownloader::addSample(qint64 sample) +{ + d->m_currentSpeedBin += sample; +} + +/*! + Returns the download speed timer ID. +*/ +int KDUpdater::FileDownloader::downloadSpeedTimerId() const +{ + return d->m_timer.timerId(); +} + +/*! + Sets the file download progress to the number of received bytes, \a bytesReceived, + and the number of total bytes to receive, \a bytesToReceive. +*/ +void KDUpdater::FileDownloader::setProgress(qint64 bytesReceived, qint64 bytesToReceive) +{ + d->m_bytesReceived = bytesReceived; + d->m_bytesToReceive = bytesToReceive; +} + +/*! + Calculates the download speed in bytes per second and emits the downloadSpeed() signal. +*/ +void KDUpdater::FileDownloader::emitDownloadSpeed() +{ + unsigned int windowSize = sizeof(d->m_samples) / sizeof(qint64); + + // add speed of last time bin to the window + d->m_samples[d->m_sampleIndex % windowSize] = d->m_currentSpeedBin; + d->m_currentSpeedBin = 0; // reset bin for next time interval + + // advance the sample index + d->m_sampleIndex++; + d->m_downloadSpeed = 0; + + // dynamic window size until the window is completely filled + if (d->m_sampleIndex < windowSize) + windowSize = d->m_sampleIndex; + + for (unsigned int i = 0; i < windowSize; ++i) + d->m_downloadSpeed += d->m_samples[i]; + + d->m_downloadSpeed /= windowSize; // computer average + d->m_downloadSpeed *= 1000.0 / d->m_speedTimerInterval; // rescale to bytes/second + + emit downloadSpeed(d->m_downloadSpeed); +} + +/*! + Builds a textual representation of the download status in the following format: + "100 MiB of 150 MiB - (DAYS) (HOURS) (MINUTES) (SECONDS) remaining". + + Emits the downloadStatus() signal. +*/ +void KDUpdater::FileDownloader::emitDownloadStatus() +{ + QString status; + if (d->m_bytesToReceive > 0) { + QString bytesReceived = humanReadableSize(d->m_bytesReceived); + const QString bytesToReceive = humanReadableSize(d->m_bytesToReceive); + + // remove the unit from the bytesReceived value if bytesToReceive has the same + const QString tmp = bytesToReceive.mid(bytesToReceive.indexOf(QLatin1Char(' '))); + if (bytesReceived.endsWith(tmp)) + bytesReceived.chop(tmp.length()); + + status = tr("%1 of %2").arg(bytesReceived).arg(bytesToReceive); + } else { + if (d->m_bytesReceived > 0) + status = tr("%1 downloaded.").arg(humanReadableSize(d->m_bytesReceived)); + } + + status += QLatin1Char(' ') + tr("(%1/sec)").arg(humanReadableSize(d->m_downloadSpeed)); + if (d->m_bytesToReceive > 0 && d->m_downloadSpeed > 0) { + const qint64 time = (d->m_bytesToReceive - d->m_bytesReceived) / d->m_downloadSpeed; + + int s = time % 60; + const int d = time / 86400; + const int h = (time / 3600) - (d * 24); + const int m = (time / 60) - (d * 1440) - (h * 60); + + QString days; + if (d > 0) + days = tr("%n day(s), ", "", d); + + QString hours; + if (h > 0) + hours = tr("%n hour(s), ", "", h); + + QString minutes; + if (m > 0) + minutes = tr("%n minute(s)", "", m); + + QString seconds; + if (s >= 0 && minutes.isEmpty()) { + s = (s <= 0 ? 1 : s); + seconds = tr("%n second(s)", "", s); + } + status += tr(" - %1%2%3%4 remaining.").arg(days).arg(hours).arg(minutes).arg(seconds); + } else { + status += tr(" - unknown time remaining."); + } + + emit downloadStatus(status); +} + +/*! + Emits dowload progress. +*/ +void KDUpdater::FileDownloader::emitDownloadProgress() +{ + emit downloadProgress(d->m_bytesReceived, d->m_bytesToReceive); +} + +/*! + Emits the estimated download time. +*/ +void KDUpdater::FileDownloader::emitEstimatedDownloadTime() +{ + if (d->m_bytesToReceive <= 0 || d->m_downloadSpeed <= 0) { + emit estimatedDownloadTime(-1); + return; + } + emit estimatedDownloadTime((d->m_bytesToReceive - d->m_bytesReceived) / d->m_downloadSpeed); +} + +/*! + \overload addCheckSumData() +*/ +void KDUpdater::FileDownloader::addCheckSumData(const QByteArray &data) +{ + d->m_hash.addData(data); +} + +/*! + Adds the \a length of characters of \a data to the cryptographic hash of the downloaded file. +*/ +void KDUpdater::FileDownloader::addCheckSumData(const char *data, int length) +{ + d->m_hash.addData(data, length); +} + +/*! + Resets SHA-1 checksum data of the downloaded file. +*/ +void KDUpdater::FileDownloader::resetCheckSumData() +{ + d->m_hash.reset(); +} + + +/*! + Returns a copy of the proxy factory that this FileDownloader object is using to determine the + proxies to be used for requests. +*/ +FileDownloaderProxyFactory *KDUpdater::FileDownloader::proxyFactory() const +{ + if (d->m_factory) + return d->m_factory->clone(); + return 0; +} + +/*! + Sets the proxy factory for this class to be \a factory. A proxy factory is used to determine a + more specific list of proxies to be used for a given request, instead of trying to use the same + proxy value for all requests. This might only be of use for HTTP or FTP requests. +*/ +void KDUpdater::FileDownloader::setProxyFactory(FileDownloaderProxyFactory *factory) +{ + delete d->m_factory; + d->m_factory = factory; +} + +/*! + Returns a copy of the authenticator that this FileDownloader object is using to set the username + and password for a download request. +*/ +QAuthenticator KDUpdater::FileDownloader::authenticator() const +{ + return d->m_authenticator; +} + +/*! + Sets the authenticator object for this class to be \a authenticator. An authenticator is used to + pass on the required authentication information. This might only be of use for HTTP or FTP + requests. Emits the authenticator changed signal with the new authenticator in use. +*/ +void KDUpdater::FileDownloader::setAuthenticator(const QAuthenticator &authenticator) +{ + if (d->m_authenticator.isNull() || (d->m_authenticator != authenticator)) { + d->m_authenticator = authenticator; + emit authenticatorChanged(authenticator); + } +} + +/*! + Returns \c true if SSL errors should be ignored. +*/ +bool KDUpdater::FileDownloader::ignoreSslErrors() +{ + return d->m_ignoreSslErrors; +} + +/*! + Determines that SSL errors should be ignored if \a ignore is \c true. +*/ +void KDUpdater::FileDownloader::setIgnoreSslErrors(bool ignore) +{ + d->m_ignoreSslErrors = ignore; +} + +// -- KDUpdater::LocalFileDownloader + +/*! + \inmodule kdupdater + \class KDUpdater::LocalFileDownloader + \brief The LocalFileDownloader class is used to copy files from the local + file system. + + The user of KDUpdater might be simultaneously downloading several files; + sometimes in parallel to other file downloaders. If copying a local file takes + a long time, it will make the other downloads hang. Therefore, a timer is used + and one block of data is copied per unit time, even though QFile::copy() does the + task of copying local files from one place to another. +*/ + +struct KDUpdater::LocalFileDownloader::Private +{ + Private() + : source(0) + , destination(0) + , downloaded(false) + , timerId(-1) + {} + + QFile *source; + QFile *destination; + QString destFileName; + bool downloaded; + int timerId; +}; + +/*! + Creates a local file downloader with the parent \a parent. +*/ +KDUpdater::LocalFileDownloader::LocalFileDownloader(QObject *parent) + : KDUpdater::FileDownloader(QLatin1String("file"), parent) + , d (new Private) +{ +} + +/*! + Destroys the local file downloader. +*/ +KDUpdater::LocalFileDownloader::~LocalFileDownloader() +{ + if (this->isAutoRemoveDownloadedFile() && !d->destFileName.isEmpty()) + QFile::remove(d->destFileName); + + delete d; +} + +/*! + Returns \c true if the file exists and is readable. +*/ +bool KDUpdater::LocalFileDownloader::canDownload() const +{ + QFileInfo fi(url().toLocalFile()); + return fi.exists() && fi.isReadable(); +} + +/*! + Returns \c true if the file is copied. +*/ +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); + if (!d->source->open(QFile::ReadOnly)) { + onError(); + setDownloadAborted(tr("Cannot open file \"%1\" for reading: %2").arg(QFileInfo(localFile) + .fileName(), d->source->errorString())); + return; + } + + if (d->destFileName.isEmpty()) { + QTemporaryFile *file = new QTemporaryFile(this); + file->open(); + d->destination = file; + } else { + d->destination = new QFile(d->destFileName, this); + d->destination->open(QIODevice::ReadWrite | QIODevice::Truncate); + } + + if (!d->destination->isOpen()) { + onError(); + setDownloadAborted(tr("Cannot open file \"%1\" for writing: %2") + .arg(QFileInfo(d->destination->fileName()).fileName(), d->destination->errorString())); + return; + } + + runDownloadSpeedTimer(); + // Start a timer and kickoff the copy process + d->timerId = startTimer(0); // as fast as possible + + emit downloadStarted(); + emit downloadProgress(0); +} + +/*! + Returns the file name of the copied file. +*/ +QString KDUpdater::LocalFileDownloader::downloadedFileName() const +{ + return d->destFileName; +} + +/*! + Sets the file name of the copied file to \a name. +*/ +void KDUpdater::LocalFileDownloader::setDownloadedFileName(const QString &name) +{ + d->destFileName = name; +} + +/*! + Clones the local file downloader and assigns it the parent \a parent. Returns + the new local file downloader. +*/ +KDUpdater::LocalFileDownloader *KDUpdater::LocalFileDownloader::clone(QObject *parent) const +{ + return new LocalFileDownloader(parent); +} + +/*! + Cancels copying the file. +*/ +void KDUpdater::LocalFileDownloader::cancelDownload() +{ + if (d->timerId < 0) + return; + + killTimer(d->timerId); + d->timerId = -1; + + onError(); + setDownloadCanceled(); +} + +/*! + Called when the download timer event \a event occurs. +*/ +void KDUpdater::LocalFileDownloader::timerEvent(QTimerEvent *event) +{ + if (event->timerId() == d->timerId) { + 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 file \"%1\" failed: %2").arg( + QDir::toNativeSeparators(d->destination->fileName()), + d->destination->errorString())); + return; + } + toWrite -= numWritten; + } + addSample(numRead); + addCheckSumData(buffer.data(), numRead); + + if (numRead > 0) { + setProgress(d->source->pos(), d->source->size()); + emit downloadProgress(calcProgress(d->source->pos(), d->source->size())); + return; + } + + d->destination->flush(); + + killTimer(d->timerId); + d->timerId = -1; + + setDownloadCompleted(); + } else if (event->timerId() == downloadSpeedTimerId()) { + emitDownloadSpeed(); + emitDownloadStatus(); + emitDownloadProgress(); + emitEstimatedDownloadTime(); + } +} + +/*! + Closes the destination file after it has been successfully copied and stops + the download speed timer. +*/ +void LocalFileDownloader::onSuccess() +{ + d->downloaded = true; + d->destFileName = d->destination->fileName(); + if (QTemporaryFile *file = dynamic_cast(d->destination)) + file->setAutoRemove(false); + d->destination->close(); + delete d->destination; + d->destination = 0; + delete d->source; + d->source = 0; + stopDownloadSpeedTimer(); +} + +/*! + Clears the destination file if an error occurs during copying and stops + the download speed timer. +*/ +void LocalFileDownloader::onError() +{ + d->downloaded = false; + d->destFileName.clear(); + delete d->destination; + d->destination = 0; + delete d->source; + d->source = 0; + stopDownloadSpeedTimer(); +} + + +// -- ResourceFileDownloader + +/*! + \inmodule kdupdater + \class KDUpdater::ResourceFileDownloader + \brief The ResourceFileDownloader class can be used to download resource files. +*/ +struct KDUpdater::ResourceFileDownloader::Private +{ + Private() + : timerId(-1) + , downloaded(false) + {} + + int timerId; + QFile destFile; + bool downloaded; +}; + +/*! + Creates a resource file downloader with the parent \a parent. +*/ +KDUpdater::ResourceFileDownloader::ResourceFileDownloader(QObject *parent) + : KDUpdater::FileDownloader(QLatin1String("resource"), parent) + , d(new Private) +{ +} + +/*! + Destroys the resource file downloader. +*/ +KDUpdater::ResourceFileDownloader::~ResourceFileDownloader() +{ + delete d; +} + +/*! + Returns \c true if the file exists and is readable. +*/ +bool KDUpdater::ResourceFileDownloader::canDownload() const +{ + const QFileInfo fi(QInstaller::pathFromUrl(url())); + return fi.exists() && fi.isReadable(); +} + +/*! + Returns \c true if the file is downloaded. +*/ +bool KDUpdater::ResourceFileDownloader::isDownloaded() const +{ + return d->downloaded; +} + +/*! + Downloads a resource file. +*/ +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->destFile.setFileName(QString::fromLatin1(":%1").arg(url.toLocalFile())); + + emit downloadStarted(); + emit downloadProgress(0); + + d->destFile.open(QIODevice::ReadOnly); + d->timerId = startTimer(0); // start as fast as possible +} + +/*! + Returns the file name of the downloaded file. +*/ +QString KDUpdater::ResourceFileDownloader::downloadedFileName() const +{ + return d->destFile.fileName(); +} + +/*! + Sets the file name of the downloaded file to \a name. +*/ +void KDUpdater::ResourceFileDownloader::setDownloadedFileName(const QString &/*name*/) +{ + // Not supported! +} + +/*! + Clones the resource file downloader and assigns it the parent \a parent. Returns + the new resource file downloader. +*/ +KDUpdater::ResourceFileDownloader *KDUpdater::ResourceFileDownloader::clone(QObject *parent) const +{ + return new ResourceFileDownloader(parent); +} + +/*! + Cancels downloading the file. +*/ +void KDUpdater::ResourceFileDownloader::cancelDownload() +{ + if (d->timerId < 0) + return; + + killTimer(d->timerId); + d->timerId = -1; + + setDownloadCanceled(); +} + +/*! + Called when the download timer event \a event occurs. +*/ +void KDUpdater::ResourceFileDownloader::timerEvent(QTimerEvent *event) +{ + if (event->timerId() == d->timerId) { + if (!d->destFile.isOpen()) { + onError(); + killTimer(d->timerId); + emit downloadProgress(1); + setDownloadAborted(tr("Cannot read resource file \"%1\": %2").arg(downloadedFileName(), + d->destFile.errorString())); + return; + } + + QByteArray buffer; + buffer.resize(32768); + const qint64 numRead = d->destFile.read(buffer.data(), buffer.size()); + + addSample(numRead); + addCheckSumData(buffer.data(), numRead); + + if (numRead > 0) { + setProgress(d->destFile.pos(), d->destFile.size()); + emit downloadProgress(calcProgress(d->destFile.pos(), d->destFile.size())); + return; + } + + killTimer(d->timerId); + d->timerId = -1; + setDownloadCompleted(); + } else if (event->timerId() == downloadSpeedTimerId()) { + emitDownloadSpeed(); + emitDownloadStatus(); + emitDownloadProgress(); + emitEstimatedDownloadTime(); + } +} + +/*! + Closes the destination file after it has been successfully copied and stops + the download speed timer. +*/ +void KDUpdater::ResourceFileDownloader::onSuccess() +{ + d->destFile.close(); + d->downloaded = true; + stopDownloadSpeedTimer(); +} + +/*! + Closes the destination file if an error occurs during copying and stops + the download speed timer. +*/ +void KDUpdater::ResourceFileDownloader::onError() +{ + d->destFile.close(); + d->downloaded = false; + stopDownloadSpeedTimer(); + d->destFile.setFileName(QString()); +} + + +// -- KDUpdater::HttpDownloader + +/*! + \inmodule kdupdater + \class KDUpdater::HttpDownloader + \brief The HttpDownloader class is used to download files over FTP, HTTP, or HTTPS. + + HTTPS is supported if Qt is built with SSL. +*/ +struct KDUpdater::HttpDownloader::Private +{ + explicit Private(HttpDownloader *qq) + : q(qq) + , http(0) + , destination(0) + , downloaded(false) + , aborted(false) + , m_authenticationCount(0) + {} + + HttpDownloader *const q; + QNetworkAccessManager manager; + QNetworkReply *http; + QFile *destination; + QString destFileName; + bool downloaded; + bool aborted; + int m_authenticationCount; + + void shutDown() + { + disconnect(http, &QNetworkReply::finished, q, &HttpDownloader::httpReqFinished); + http->deleteLater(); + http = 0; + destination->close(); + destination->deleteLater(); + destination = 0; + q->resetCheckSumData(); + } +}; + +/*! + Creates an HTTP downloader with the parent \a parent. +*/ +KDUpdater::HttpDownloader::HttpDownloader(QObject *parent) + : KDUpdater::FileDownloader(QLatin1String("http"), parent) + , d(new Private(this)) +{ +#ifndef QT_NO_SSL + connect(&d->manager, &QNetworkAccessManager::sslErrors, + this, &HttpDownloader::onSslErrors); +#endif + connect(&d->manager, &QNetworkAccessManager::authenticationRequired, + this, &HttpDownloader::onAuthenticationRequired); +} + +/*! + Destroys an HTTP downloader. + + Removes the downloaded file if FileDownloader::isAutoRemoveDownloadedFile() returns \c true or + FileDownloader::setAutoRemoveDownloadedFile() was called with \c true. +*/ +KDUpdater::HttpDownloader::~HttpDownloader() +{ + if (this->isAutoRemoveDownloadedFile() && !d->destFileName.isEmpty()) + QFile::remove(d->destFileName); + delete d; +} + +/*! + Returns \c true if the file exists and is readable. +*/ +bool KDUpdater::HttpDownloader::canDownload() const +{ + // TODO: Check whether the http file actually exists or not. + return true; +} + +/*! + Returns \c true if the file is downloaded. +*/ +bool KDUpdater::HttpDownloader::isDownloaded() const +{ + return d->downloaded; +} + +void KDUpdater::HttpDownloader::doDownload() +{ + if (d->downloaded) + return; + + if (d->http) + return; + + startDownload(url()); + runDownloadSpeedTimer(); +} + +/*! + Returns the file name of the downloaded file. +*/ +QString KDUpdater::HttpDownloader::downloadedFileName() const +{ + return d->destFileName; +} + +/*! + Sets the file name of the downloaded file to \a name. +*/ +void KDUpdater::HttpDownloader::setDownloadedFileName(const QString &name) +{ + d->destFileName = name; +} + +/*! + Clones the HTTP downloader and assigns it the parent \a parent. Returns the new + HTTP downloader. +*/ +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 error = d->destination->errorString(); + const QString fileName = d->destination->fileName(); + d->shutDown(); + setDownloadAborted(tr("Cannot download %1. Writing to file \"%2\" failed: %3") + .arg(url().toString(), fileName, error)); + return; + } + written += numWritten; + } + addSample(written); + addCheckSumData(buffer.data(), read); + } +} + +void KDUpdater::HttpDownloader::httpError(QNetworkReply::NetworkError) +{ + if (!d->aborted) + httpDone(true); +} + +/*! + Cancels downloading the file. +*/ +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; + setDownloadCanceled(); + } else { + setDownloadAborted(err); + } + } + //PENDING: what about the non-error case?? +} + +/*! + Closes the destination file if an error occurs during copying and stops + the download speed timer. +*/ +void KDUpdater::HttpDownloader::onError() +{ + d->downloaded = false; + d->destFileName.clear(); + delete d->destination; + d->destination = 0; + stopDownloadSpeedTimer(); +} + +/*! + Closes the destination file after it has been successfully copied and stops + the download speed timer. +*/ +void KDUpdater::HttpDownloader::onSuccess() +{ + d->downloaded = true; + d->destFileName = d->destination->fileName(); + if (QTemporaryFile *file = dynamic_cast(d->destination)) + file->setAutoRemove(false); + delete d->destination; + d->destination = 0; + stopDownloadSpeedTimer(); +} + +void KDUpdater::HttpDownloader::httpReqFinished() +{ + const QVariant redirect = d->http == 0 ? QVariant() + : d->http->attribute(QNetworkRequest::RedirectionTargetAttribute); + + const QUrl redirectUrl = redirect.toUrl(); + if (followRedirects() && redirectUrl.isValid()) { + d->shutDown(); // clean the previous download + startDownload(redirectUrl); + } else { + if (d->http == 0) + return; + + httpReadyRead(); + d->destination->flush(); + setDownloadCompleted(); + d->http->deleteLater(); + d->http = 0; + } +} + +void KDUpdater::HttpDownloader::httpReadProgress(qint64 done, qint64 total) +{ + if (d->http) { + const QUrl redirectUrl = d->http->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); + if (followRedirects() && redirectUrl.isValid()) + return; // if we are a redirection, do not emit the progress + } + + setProgress(done, total); + emit downloadProgress(calcProgress(done, total)); +} + +/*! + Called when the download timer event \a event occurs. +*/ +void KDUpdater::HttpDownloader::timerEvent(QTimerEvent *event) +{ + if (event->timerId() == downloadSpeedTimerId()) { + emitDownloadSpeed(); + emitDownloadStatus(); + emitDownloadProgress(); + emitEstimatedDownloadTime(); + } +} + +void KDUpdater::HttpDownloader::startDownload(const QUrl &url) +{ + d->m_authenticationCount = 0; + d->manager.setProxyFactory(proxyFactory()); + d->http = d->manager.get(QNetworkRequest(url)); + + connect(d->http, &QIODevice::readyRead, this, &HttpDownloader::httpReadyRead); + connect(d->http, &QNetworkReply::downloadProgress, + this, &HttpDownloader::httpReadProgress); + connect(d->http, &QNetworkReply::finished, this, &HttpDownloader::httpReqFinished); + void (QNetworkReply::*errorSignal)(QNetworkReply::NetworkError) = &QNetworkReply::error; + connect(d->http, errorSignal, this, &HttpDownloader::httpError); + + if (d->destFileName.isEmpty()) { + QTemporaryFile *file = new QTemporaryFile(this); + file->open(); + d->destination = file; + } else { + d->destination = new QFile(d->destFileName, this); + d->destination->open(QIODevice::ReadWrite | QIODevice::Truncate); + } + + if (!d->destination->isOpen()) { + const QString error = d->destination->errorString(); + const QString fileName = d->destination->fileName(); + d->shutDown(); + setDownloadAborted(tr("Cannot download %1. Cannot create file \"%2\": %3").arg( + url.toString(), fileName, error)); + } +} + +void KDUpdater::HttpDownloader::onAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator) +{ + Q_UNUSED(reply) + // first try with the information we have already + if (d->m_authenticationCount == 0) { + d->m_authenticationCount++; + authenticator->setUser(this->authenticator().user()); + authenticator->setPassword(this->authenticator().password()); + } else if (d->m_authenticationCount == 1) { + // we failed to authenticate, ask for new credentials + QDialog dlg; + Ui::Dialog ui; + ui.setupUi(&dlg); + dlg.adjustSize(); + ui.siteDescription->setText(tr("%1 at %2").arg(authenticator->realm()).arg(url().host())); + + ui.userEdit->setText(this->authenticator().user()); + ui.passwordEdit->setText(this->authenticator().password()); + + if (dlg.exec() == QDialog::Accepted) { + authenticator->setUser(ui.userEdit->text()); + authenticator->setPassword(ui.passwordEdit->text()); + + // update the authenticator we used initially + QAuthenticator auth; + auth.setUser(ui.userEdit->text()); + auth.setPassword(ui.passwordEdit->text()); + emit authenticatorChanged(auth); + } else { + d->shutDown(); + setDownloadAborted(tr("Authentication request canceled.")); + emit downloadCanceled(); + } + d->m_authenticationCount++; + } +} + +#ifndef QT_NO_SSL + +#include "messageboxhandler.h" + +void KDUpdater::HttpDownloader::onSslErrors(QNetworkReply* reply, const QList &errors) +{ + Q_UNUSED(reply) + QString errorString; + foreach (const QSslError &error, errors) { + if (!errorString.isEmpty()) + errorString += QLatin1String(", "); + errorString += error.errorString(); + } + qDebug() << errorString; + + const QStringList arguments = QCoreApplication::arguments(); + if (arguments.contains(QLatin1String("--script")) || arguments.contains(QLatin1String("Script")) + || ignoreSslErrors()) { + reply->ignoreSslErrors(); + return; + } + // TODO: Remove above code once we have a proper implementation for message box handler supporting + // methods used in the following code, right now we return here cause the message box is not scriptable. + + QMessageBox msgBox(MessageBoxHandler::currentBestSuitParent()); + msgBox.setDetailedText(errorString); + msgBox.setIcon(QMessageBox::Warning); + msgBox.setWindowModality(Qt::WindowModal); + msgBox.setWindowTitle(tr("Secure Connection Failed")); + msgBox.setText(tr("There was an error during connection to: %1.").arg(url().toString())); + msgBox.setInformativeText(QString::fromLatin1("
  • %1
  • %2
").arg(tr("This could be " + "a problem with the server's configuration, or it could be someone trying to impersonate the " + "server."), tr("If you have connected to this server successfully in the past or trust this server, " + "the error may be temporary and you can try again."))); + + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel); + msgBox.setButtonText(QMessageBox::Yes, tr("Try again")); + msgBox.setDefaultButton(QMessageBox::Cancel); + + if (msgBox.exec() == QMessageBox::Cancel) { + if (!d->aborted) + httpDone(true); + } else { + reply->ignoreSslErrors(); + KDUpdater::FileDownloaderFactory::instance().setIgnoreSslErrors(true); + } +} +#endif diff --git a/src/libs/kdtools/filedownloader.h b/src/libs/kdtools/filedownloader.h new file mode 100644 index 000000000..a74097625 --- /dev/null +++ b/src/libs/kdtools/filedownloader.h @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef KD_UPDATER_FILE_DOWNLOADER_H +#define KD_UPDATER_FILE_DOWNLOADER_H + +#include "kdtoolsglobal.h" + +#include +#include + +#include + +namespace KDUpdater { + +class FileDownloaderProxyFactory; + +class KDTOOLS_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 WRITE setScheme) + +public: + explicit FileDownloader(const QString &scheme, QObject *parent = 0); + ~FileDownloader(); + + QUrl url() const; + void setUrl(const QUrl &url); + + QByteArray sha1Sum() const; + + QByteArray assumedSha1Sum() const; + void setAssumedSha1Sum(const QByteArray &sha1); + + QString scheme() const; + void setScheme(const QString &scheme); + + QString errorString() const; + + virtual bool canDownload() const = 0; + virtual bool isDownloaded() const = 0; + virtual QString downloadedFileName() const = 0; + virtual void setDownloadedFileName(const QString &name) = 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; + + FileDownloaderProxyFactory *proxyFactory() const; + void setProxyFactory(FileDownloaderProxyFactory *factory); + + QAuthenticator authenticator() const; + void setAuthenticator(const QAuthenticator &authenticator); + + bool ignoreSslErrors(); + void setIgnoreSslErrors(bool ignore); + +public Q_SLOTS: + virtual void cancelDownload(); + +protected: + virtual void onError() = 0; + virtual void onSuccess() = 0; + +Q_SIGNALS: + void downloadStarted(); + void downloadCanceled(); + + void downloadProgress(double progress); + void estimatedDownloadTime(int seconds); + void downloadSpeed(qint64 bytesPerSecond); + void downloadStatus(const QString &status); + void downloadProgress(qint64 bytesReceived, qint64 bytesToReceive); + void authenticatorChanged(const QAuthenticator &authenticator); + void downloadCompleted(); + void downloadAborted(const QString &errorMessage); + +protected: + void setDownloadCanceled(); + void setDownloadCompleted(); + void setDownloadAborted(const QString &error); + + void runDownloadSpeedTimer(); + void stopDownloadSpeedTimer(); + + void addSample(qint64 sample); + int downloadSpeedTimerId() const; + void setProgress(qint64 bytesReceived, qint64 bytesToReceive); + + void emitDownloadSpeed(); + void emitDownloadStatus(); + void emitDownloadProgress(); + void emitEstimatedDownloadTime(); + + void addCheckSumData(const QByteArray &data); + void addCheckSumData(const char *data, int length); + void resetCheckSumData(); + +private Q_SLOTS: + virtual void doDownload() = 0; + +private: + struct Private; + Private *d; +}; + +} // namespace KDUpdater + +#endif // KD_UPDATER_FILE_DOWNLOADER_H diff --git a/src/libs/kdtools/filedownloader_p.h b/src/libs/kdtools/filedownloader_p.h new file mode 100644 index 000000000..b787e8392 --- /dev/null +++ b/src/libs/kdtools/filedownloader_p.h @@ -0,0 +1,150 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef KD_UPDATER_FILE_DOWNLOADER_P_H +#define KD_UPDATER_FILE_DOWNLOADER_P_H + +#include "filedownloader.h" + +#include + +// these classes are not a part of the public API + +namespace KDUpdater { + +class LocalFileDownloader : public FileDownloader +{ + Q_OBJECT + +public: + explicit LocalFileDownloader(QObject *parent = 0); + ~LocalFileDownloader(); + + bool canDownload() const; + bool isDownloaded() const; + QString downloadedFileName() const; + void setDownloadedFileName(const QString &name); + LocalFileDownloader *clone(QObject *parent = 0) const; + +public Q_SLOTS: + void cancelDownload(); + +protected: + void timerEvent(QTimerEvent *te); + void onError(); + void onSuccess(); + +private Q_SLOTS: + void doDownload(); + +private: + struct Private; + Private *d; +}; + +class ResourceFileDownloader : public FileDownloader +{ + Q_OBJECT + +public: + explicit ResourceFileDownloader(QObject *parent = 0); + ~ResourceFileDownloader(); + + bool canDownload() const; + bool isDownloaded() const; + QString downloadedFileName() const; + void setDownloadedFileName(const QString &name); + ResourceFileDownloader *clone(QObject *parent = 0) const; + +public Q_SLOTS: + void cancelDownload(); + +protected: + void timerEvent(QTimerEvent *te); + void onError(); + void onSuccess(); + +private Q_SLOTS: + void doDownload(); + +private: + struct Private; + Private *d; +}; + +class HttpDownloader : public FileDownloader +{ + Q_OBJECT + +public: + explicit HttpDownloader(QObject *parent = 0); + ~HttpDownloader(); + + bool canDownload() const; + bool isDownloaded() const; + QString downloadedFileName() const; + void setDownloadedFileName(const QString &name); + HttpDownloader *clone(QObject *parent = 0) const; + +public Q_SLOTS: + void cancelDownload(); + +protected: + void onError(); + void onSuccess(); + void timerEvent(QTimerEvent *event); + +private Q_SLOTS: + void doDownload(); + + void httpReadyRead(); + void httpReadProgress(qint64 done, qint64 total); + void httpError(QNetworkReply::NetworkError); + void httpDone(bool error); + void httpReqFinished(); + void onAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator); +#ifndef QT_NO_SSL + void onSslErrors(QNetworkReply* reply, const QList &errors); +#endif +private: + void startDownload(const QUrl &url); + +private: + struct Private; + Private *d; +}; + +} // namespace KDUpdater + +#endif // KD_UPDATER_FILE_DOWNLOADER_P_H diff --git a/src/libs/kdtools/filedownloaderfactory.cpp b/src/libs/kdtools/filedownloaderfactory.cpp new file mode 100644 index 000000000..2581aa11f --- /dev/null +++ b/src/libs/kdtools/filedownloaderfactory.cpp @@ -0,0 +1,198 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "filedownloaderfactory.h" +#include "filedownloader_p.h" + +#include + +using namespace KDUpdater; + +/*! + \inmodule kdupdater + \class KDUpdater::FileDownloaderFactory + \brief The FileDownloaderFactory class acts as a factory for KDUpdater::FileDownloader. + + You can register one or more file downloaders with this factory and query them based on their + scheme. The class follows the singleton design pattern. Only one instance of this class can + be created and its reference can be fetched from the instance() method. +*/ + +/*! + Returns the file downloader factory instance. +*/ +FileDownloaderFactory& FileDownloaderFactory::instance() +{ + static KDUpdater::FileDownloaderFactory theFactory; + return theFactory; +} + +/*! + Constructs a file downloader factory and registers the default file downloader set. +*/ +FileDownloaderFactory::FileDownloaderFactory() + : d (new FileDownloaderFactoryData) +{ + // Register the default file downloader set + registerFileDownloader( QLatin1String("file")); + registerFileDownloader(QLatin1String("ftp")); + registerFileDownloader(QLatin1String("http")); + registerFileDownloader(QLatin1String("resource")); + +#ifndef QT_NO_SSL + if (QSslSocket::supportsSsl()) + registerFileDownloader(QLatin1String("https")); + else + qWarning() << "Cannot register file downloader for https protocol: QSslSocket::supportsSsl() returns false"; +#endif + + d->m_followRedirects = false; +} + +/*! + Returns whether redirects should be followed. +*/ +bool FileDownloaderFactory::followRedirects() +{ + return FileDownloaderFactory::instance().d->m_followRedirects; +} + +/*! + Determines that redirects should be followed if \a val is \c true. +*/ +void FileDownloaderFactory::setFollowRedirects(bool val) +{ + FileDownloaderFactory::instance().d->m_followRedirects = val; +} + +/*! + Sets \a factory as the file downloader proxy factory. +*/ +void FileDownloaderFactory::setProxyFactory(FileDownloaderProxyFactory *factory) +{ + delete FileDownloaderFactory::instance().d->m_factory; + FileDownloaderFactory::instance().d->m_factory = factory; +} + +/*! + Returns \c true if SSL errors should be ignored. +*/ +bool FileDownloaderFactory::ignoreSslErrors() +{ + return FileDownloaderFactory::instance().d->m_ignoreSslErrors; +} + +/*! + Determines that SSL errors should be ignored if \a ignore is \c true. +*/ +void FileDownloaderFactory::setIgnoreSslErrors(bool ignore) +{ + FileDownloaderFactory::instance().d->m_ignoreSslErrors = ignore; +} + +/*! + Destroys the file downloader factory. +*/ +FileDownloaderFactory::~FileDownloaderFactory() +{ + delete d; +} + +/*! + Returns a list of supported schemes. +*/ +QStringList FileDownloaderFactory::supportedSchemes() +{ + return FileDownloaderFactory::instance().d->m_supportedSchemes; +} + +/*! + Returns \c true if \a scheme is a supported scheme. +*/ +bool FileDownloaderFactory::isSupportedScheme(const QString &scheme) +{ + return FileDownloaderFactory::instance().d->m_supportedSchemes.contains(scheme + , Qt::CaseInsensitive); +} + +/*! + Returns a new instance of a KDUpdater::FileDownloader subclass. The + instantiation of a subclass depends on the communication protocol string + stored in \a scheme with the parent \a parent. + + \note Ownership of the created object remains with the programmer. +*/ +FileDownloader *FileDownloaderFactory::create(const QString &scheme, QObject *parent) const +{ + FileDownloader *downloader = + KDGenericFactory::create(scheme, parent); + if (downloader != 0) { + downloader->setFollowRedirects(d->m_followRedirects); + downloader->setIgnoreSslErrors(d->m_ignoreSslErrors); + if (d->m_factory) + downloader->setProxyFactory(d->m_factory->clone()); + } + return downloader; +} + +/*! + \fn void KDUpdater::FileDownloaderFactory::registerFileDownloader(const QString &scheme) + + Registers a new file downloader with the factory based on \a scheme. If there is already + a downloader with the same scheme, the downloader is replaced. When create() is called + with that \a scheme, the file downloader is constructed using its default constructor. +*/ + +/*! + \inmodule kdupdater + \class KDUpdater::FileDownloaderProxyFactory + \brief The FileDownloaderProxyFactory class provides fine-grained proxy selection. + + File downloader objects use a proxy factory to determine a more specific + list of proxies to be used for a given request, instead of trying to use the + same proxy value for all requests. This might only be of use for HTTP or FTP + requests. +*/ + +/*! + \fn FileDownloaderProxyFactory::~FileDownloaderProxyFactory() + + Destroys the file downloader proxy factory. +*/ + +/*! + \fn FileDownloaderProxyFactory::clone() const + + Clones a file downloader proxy factory. +*/ diff --git a/src/libs/kdtools/filedownloaderfactory.h b/src/libs/kdtools/filedownloaderfactory.h new file mode 100644 index 000000000..6f3740489 --- /dev/null +++ b/src/libs/kdtools/filedownloaderfactory.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef KD_UPDATER_FILE_DOWNLOADER_FACTORY_H +#define KD_UPDATER_FILE_DOWNLOADER_FACTORY_H + +#include "genericfactory.h" +#include "updater.h" + +#include +#include + +#include + +QT_BEGIN_NAMESPACE +class QObject; +QT_END_NAMESPACE + +namespace KDUpdater { + +class FileDownloader; + +class KDTOOLS_EXPORT FileDownloaderProxyFactory : public QNetworkProxyFactory +{ +public: + virtual ~FileDownloaderProxyFactory() {} + virtual FileDownloaderProxyFactory *clone() const = 0; +}; + +class KDTOOLS_EXPORT FileDownloaderFactory : public KDGenericFactory +{ + Q_DISABLE_COPY(FileDownloaderFactory) + struct FileDownloaderFactoryData { + FileDownloaderFactoryData() : m_factory(0) {} + ~FileDownloaderFactoryData() { delete m_factory; } + + bool m_followRedirects; + bool m_ignoreSslErrors; + QStringList m_supportedSchemes; + FileDownloaderProxyFactory *m_factory; + }; + +public: + static FileDownloaderFactory &instance(); + ~FileDownloaderFactory(); + + template + void registerFileDownloader(const QString &scheme) + { + registerProduct(scheme); + d->m_supportedSchemes.append(scheme); + } + FileDownloader *create(const QString &scheme, QObject *parent = 0) const; + + static bool followRedirects(); + static void setFollowRedirects(bool val); + + static void setProxyFactory(FileDownloaderProxyFactory *factory); + + static bool ignoreSslErrors(); + static void setIgnoreSslErrors(bool ignore); + + static QStringList supportedSchemes(); + static bool isSupportedScheme(const QString &scheme); + +private: + FileDownloaderFactory(); + +private: + FileDownloaderFactoryData *d; +}; + +} // namespace KDUpdater + +#endif // KD_UPDATER_FILE_DOWNLOADER_FACTORY_H diff --git a/src/libs/kdtools/genericfactory.cpp b/src/libs/kdtools/genericfactory.cpp new file mode 100644 index 000000000..f38cec31a --- /dev/null +++ b/src/libs/kdtools/genericfactory.cpp @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "genericfactory.h" + +/*! + \inmodule kdupdater + \class KDGenericFactory + \brief The KDGenericFactory class implements a template-based generic factory. + + KDGenericFactory is an implementation of the factory pattern. It can be used to produce + instances of different classes having a common superclass \c BASE. The user of the factory + registers those producible classes in the factory by using the identifier \c IDENTIFIER. That + identifier can then be used to produce as many instances of the registered product as the + user wants. + + One factory instance is able to produce instances of different types of DERIVED classes only + when the constructor of DERIVED or the registered generator function have a common signature + for all DERIVED classes. This signature is described by the declaration order of ARGUMENTS. It + is referred to as SIGNATURE in the following paragraphs. + + If a class derived from BASE does not contain a SIGNATURE matching the registered one for the + constructor or the generator function, it is not possible to create instances of it using one + instance of KDGenericFactory subclass. In that case, more than one KDGenericFactory subclass + and instance are needed. + + It is possible to register a subclass of BASE inside an instance of KDGenericFactory subclass + using the registerProduct() function. At least one of the following conditions needs to be met: + + \list + \li A global or static function with SIGNATURE exists. + \li The DERIVED class has a constructor with SIGNATURE. + \li The DERIVED class has a static function with SIGNATURE. + \endlist + + To get a new instance of DERIVED, one needs to call the create() function. The value of + IDENTIFIER determines the product's subclass registered in the factory, while the values + of SIGNATURE are the actual arguments passed to the class constructor or the registered + generator function. +*/ + +/*! + \fn KDGenericFactory::KDGenericFactory() + + Creates the generic factory. +*/ + +/*! + \fn KDGenericFactory::~KDGenericFactory() + + Destroys the generic factory. +*/ + +/*! + \typedef KDGenericFactory::FactoryFunction + + This typedef defines a factory function producing an object of type BASE. +*/ + +/*! + \fn void KDGenericFactory::registerProduct(const IDENTIFIER &id) + + Registers a type DERIVED, identified by \a id in the factory. Any type with the same id gets + unregistered. +*/ + +/*! + \overload + \fn void KDGenericFactory::registerProduct(const IDENTIFIER &id, FactoryFunction func) + + Registers a function \a func that can create the type DERIVED, identified by \a id in the + factory. Any type with the same id gets unregistered. +*/ + +/*! + \fn bool KDGenericFactory::containsProduct(const IDENTIFIER &id) const + + Returns \c true if the factory contains a type with the \a id; otherwise returns false. +*/ + +/*! + \fn BASE *KDGenericFactory::create(const IDENTIFIER &id, ARGUMENTS... args) const + + Creates and returns the type identified by \a id, but automatically upcasted to BASE. Ownership + of the type is transferred to the caller. +*/ diff --git a/src/libs/kdtools/genericfactory.h b/src/libs/kdtools/genericfactory.h new file mode 100644 index 000000000..29051e22a --- /dev/null +++ b/src/libs/kdtools/genericfactory.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef KDTOOLS__KDGENERICFACTORY_H +#define KDTOOLS__KDGENERICFACTORY_H + +#include "kdtoolsglobal.h" + +#include + +template +class KDGenericFactory +{ +public: + virtual ~KDGenericFactory() {} + + typedef BASE *(*FactoryFunction)(ARGUMENTS...); + + template + void registerProduct(const IDENTIFIER &id) + { + m_hash.insert(id, &KDGenericFactory::create); + } + + void registerProduct(const IDENTIFIER &id, FactoryFunction func) + { + m_hash.insert(id, func); + } + + bool containsProduct(const IDENTIFIER &id) const + { + return m_hash.contains(id); + } + + BASE *create(const IDENTIFIER &id, ARGUMENTS... args) const + { + const auto it = m_hash.constFind(id); + if (it == m_hash.constEnd()) + return 0; + return (*it)(std::forward(args)...); + } + +protected: + KDGenericFactory() = default; + +private: + template + static BASE *create(ARGUMENTS... args) + { + return new DERIVED(std::forward(args)...); + } + + KDGenericFactory(const KDGenericFactory &) = delete; + KDGenericFactory &operator=(const KDGenericFactory &) = delete; + +private: + QHash m_hash; +}; + +#endif diff --git a/src/libs/kdtools/job.cpp b/src/libs/kdtools/job.cpp new file mode 100644 index 000000000..ad2472ae3 --- /dev/null +++ b/src/libs/kdtools/job.cpp @@ -0,0 +1,248 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "job.h" + +#include +#include +#include + + +// -- KDJob::Private + +class KDJob::Private +{ + KDJob *const q; + +public: + explicit Private(KDJob *qq) + : q(qq) + , error(KDJob::NoError) + , caps(KDJob::NoCapabilities) + , autoDelete(true) + , totalAmount(100) + , processedAmount(0) + , m_timeout(-1) + { + connect(&m_timer, &QTimer::timeout, q, &KDJob::cancel); + } + + ~Private() + { + m_timer.stop(); + } + + void delayedStart() + { + q->doStart(); + emit q->started(q); + } + + void waitForSignal(const char *sig) + { + QEventLoop loop; + q->connect(q, sig, &loop, SLOT(quit())); + + if (m_timeout >= 0) + m_timer.start(m_timeout); + else + m_timer.stop(); + + loop.exec(); + } + + int error; + QString errorString; + KDJob::Capabilities caps; + bool autoDelete; + quint64 totalAmount; + quint64 processedAmount; + int m_timeout; + QTimer m_timer; +}; + + +// -- KDJob + +KDJob::KDJob(QObject *parent) + : QObject(parent), + d(new Private(this)) +{ + connect(this, &KDJob::finished, this, &KDJob::onFinished); +} + +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); +} + +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::cancel() +{ + if (d->caps & Cancelable) { + doCancel(); + if (error() == NoError) { + setError(Canceled); + setErrorString(tr("Canceled")); + } + emitFinished(); + } else { + qDebug() << "The current job cannot be canceled, missing \"Cancelable\" capability."; + } +} + +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); +} + +/*! + Returns the timeout in milliseconds before the job's cancel slot gets triggered. A return value + of -1 means there is currently no timeout used for the job. +*/ +int KDJob::timeout() const +{ + return d->m_timeout; +} + +/*! + Sets the timeout in \a milliseconds before the job's cancel slot gets triggered. \note Only jobs + that have the \c KDJob::Cancelable capability can be canceled by a timeout. A value of -1 will + stop the timeout mechanism. +*/ +void KDJob::setTimeout(int milliseconds) +{ + d->m_timeout = milliseconds; +} + +void KDJob::setProcessedAmount(quint64 amount) +{ + if (d->processedAmount == amount) + return; + d->processedAmount = amount; + emit progress(this, d->processedAmount, d->totalAmount); +} + +void KDJob::onFinished() +{ + d->m_timer.stop(); + if (d->autoDelete) + deleteLater(); +} + +#include "moc_job.cpp" diff --git a/src/libs/kdtools/job.h b/src/libs/kdtools/job.h new file mode 100644 index 000000000..14231e7ed --- /dev/null +++ b/src/libs/kdtools/job.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef KDTOOLS_KDJOB_H +#define KDTOOLS_KDJOB_H + +#include "kdtoolsglobal.h" + +#include + +class KDTOOLS_EXPORT KDJob : public QObject +{ + Q_OBJECT + class Private; + + Q_PROPERTY(int timeout READ timeout WRITE setTimeout) + 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; + + int timeout() const; + void setTimeout(int milliseconds); + +public Q_SLOTS: + void start(); + void cancel(); + +Q_SIGNALS: + void started(KDJob *job); + void finished(KDJob *job); + + void infoMessage(KDJob *job, const QString &message); + void progress(KDJob *job, quint64 processed, quint64 total); + +protected: + virtual void doStart() = 0; + virtual void doCancel() = 0; + + 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 Q_SLOTS: + void onFinished(); + +private: + Private *d; + Q_PRIVATE_SLOT(d, void delayedStart()) +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(KDJob::Capabilities) + +#endif // KDTOOLS_KDJOB_H diff --git a/src/libs/kdtools/kdgenericfactory.cpp b/src/libs/kdtools/kdgenericfactory.cpp deleted file mode 100644 index 2a7718be3..000000000 --- a/src/libs/kdtools/kdgenericfactory.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "kdgenericfactory.h" - -/*! - \inmodule kdupdater - \class KDGenericFactory - \brief The KDGenericFactory class implements a template-based generic factory. - - KDGenericFactory is an implementation of the factory pattern. It can be used to produce - instances of different classes having a common superclass \c BASE. The user of the factory - registers those producible classes in the factory by using the identifier \c IDENTIFIER. That - identifier can then be used to produce as many instances of the registered product as the - user wants. - - One factory instance is able to produce instances of different types of DERIVED classes only - when the constructor of DERIVED or the registered generator function have a common signature - for all DERIVED classes. This signature is described by the declaration order of ARGUMENTS. It - is referred to as SIGNATURE in the following paragraphs. - - If a class derived from BASE does not contain a SIGNATURE matching the registered one for the - constructor or the generator function, it is not possible to create instances of it using one - instance of KDGenericFactory subclass. In that case, more than one KDGenericFactory subclass - and instance are needed. - - It is possible to register a subclass of BASE inside an instance of KDGenericFactory subclass - using the registerProduct() function. At least one of the following conditions needs to be met: - - \list - \li A global or static function with SIGNATURE exists. - \li The DERIVED class has a constructor with SIGNATURE. - \li The DERIVED class has a static function with SIGNATURE. - \endlist - - To get a new instance of DERIVED, one needs to call the create() function. The value of - IDENTIFIER determines the product's subclass registered in the factory, while the values - of SIGNATURE are the actual arguments passed to the class constructor or the registered - generator function. -*/ - -/*! - \fn KDGenericFactory::KDGenericFactory() - - Creates the generic factory. -*/ - -/*! - \fn KDGenericFactory::~KDGenericFactory() - - Destroys the generic factory. -*/ - -/*! - \typedef KDGenericFactory::FactoryFunction - - This typedef defines a factory function producing an object of type BASE. -*/ - -/*! - \fn void KDGenericFactory::registerProduct(const IDENTIFIER &id) - - Registers a type DERIVED, identified by \a id in the factory. Any type with the same id gets - unregistered. -*/ - -/*! - \overload - \fn void KDGenericFactory::registerProduct(const IDENTIFIER &id, FactoryFunction func) - - Registers a function \a func that can create the type DERIVED, identified by \a id in the - factory. Any type with the same id gets unregistered. -*/ - -/*! - \fn bool KDGenericFactory::containsProduct(const IDENTIFIER &id) const - - Returns \c true if the factory contains a type with the \a id; otherwise returns false. -*/ - -/*! - \fn BASE *KDGenericFactory::create(const IDENTIFIER &id, ARGUMENTS... args) const - - Creates and returns the type identified by \a id, but automatically upcasted to BASE. Ownership - of the type is transferred to the caller. -*/ diff --git a/src/libs/kdtools/kdgenericfactory.h b/src/libs/kdtools/kdgenericfactory.h deleted file mode 100644 index 048dc90ad..000000000 --- a/src/libs/kdtools/kdgenericfactory.h +++ /dev/null @@ -1,91 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef KDTOOLS__KDGENERICFACTORY_H -#define KDTOOLS__KDGENERICFACTORY_H - -#include - -#include - -template -class KDGenericFactory -{ -public: - virtual ~KDGenericFactory() {} - - typedef BASE *(*FactoryFunction)(ARGUMENTS...); - - template - void registerProduct(const IDENTIFIER &id) - { - m_hash.insert(id, &KDGenericFactory::create); - } - - void registerProduct(const IDENTIFIER &id, FactoryFunction func) - { - m_hash.insert(id, func); - } - - bool containsProduct(const IDENTIFIER &id) const - { - return m_hash.contains(id); - } - - BASE *create(const IDENTIFIER &id, ARGUMENTS... args) const - { - const auto it = m_hash.constFind(id); - if (it == m_hash.constEnd()) - return 0; - return (*it)(std::forward(args)...); - } - -protected: - KDGenericFactory() = default; - -private: - template - static BASE *create(ARGUMENTS... args) - { - return new DERIVED(std::forward(args)...); - } - - KDGenericFactory(const KDGenericFactory &) = delete; - KDGenericFactory &operator=(const KDGenericFactory &) = delete; - -private: - QHash m_hash; -}; - -#endif diff --git a/src/libs/kdtools/kdjob.cpp b/src/libs/kdtools/kdjob.cpp deleted file mode 100644 index cca082f9f..000000000 --- a/src/libs/kdtools/kdjob.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "kdjob.h" - -#include -#include -#include - - -// -- KDJob::Private - -class KDJob::Private -{ - KDJob *const q; - -public: - explicit Private(KDJob *qq) - : q(qq) - , error(KDJob::NoError) - , caps(KDJob::NoCapabilities) - , autoDelete(true) - , totalAmount(100) - , processedAmount(0) - , m_timeout(-1) - { - connect(&m_timer, &QTimer::timeout, q, &KDJob::cancel); - } - - ~Private() - { - m_timer.stop(); - } - - void delayedStart() - { - q->doStart(); - emit q->started(q); - } - - void waitForSignal(const char *sig) - { - QEventLoop loop; - q->connect(q, sig, &loop, SLOT(quit())); - - if (m_timeout >= 0) - m_timer.start(m_timeout); - else - m_timer.stop(); - - loop.exec(); - } - - int error; - QString errorString; - KDJob::Capabilities caps; - bool autoDelete; - quint64 totalAmount; - quint64 processedAmount; - int m_timeout; - QTimer m_timer; -}; - - -// -- KDJob - -KDJob::KDJob(QObject *parent) - : QObject(parent), - d(new Private(this)) -{ - connect(this, &KDJob::finished, this, &KDJob::onFinished); -} - -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); -} - -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::cancel() -{ - if (d->caps & Cancelable) { - doCancel(); - if (error() == NoError) { - setError(Canceled); - setErrorString(tr("Canceled")); - } - emitFinished(); - } else { - qDebug() << "The current job cannot be canceled, missing \"Cancelable\" capability."; - } -} - -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); -} - -/*! - Returns the timeout in milliseconds before the job's cancel slot gets triggered. A return value - of -1 means there is currently no timeout used for the job. -*/ -int KDJob::timeout() const -{ - return d->m_timeout; -} - -/*! - Sets the timeout in \a milliseconds before the job's cancel slot gets triggered. \note Only jobs - that have the \c KDJob::Cancelable capability can be canceled by a timeout. A value of -1 will - stop the timeout mechanism. -*/ -void KDJob::setTimeout(int milliseconds) -{ - d->m_timeout = milliseconds; -} - -void KDJob::setProcessedAmount(quint64 amount) -{ - if (d->processedAmount == amount) - return; - d->processedAmount = amount; - emit progress(this, d->processedAmount, d->totalAmount); -} - -void KDJob::onFinished() -{ - d->m_timer.stop(); - if (d->autoDelete) - deleteLater(); -} - -#include "moc_kdjob.cpp" diff --git a/src/libs/kdtools/kdjob.h b/src/libs/kdtools/kdjob.h deleted file mode 100644 index 14231e7ed..000000000 --- a/src/libs/kdtools/kdjob.h +++ /dev/null @@ -1,121 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef KDTOOLS_KDJOB_H -#define KDTOOLS_KDJOB_H - -#include "kdtoolsglobal.h" - -#include - -class KDTOOLS_EXPORT KDJob : public QObject -{ - Q_OBJECT - class Private; - - Q_PROPERTY(int timeout READ timeout WRITE setTimeout) - 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; - - int timeout() const; - void setTimeout(int milliseconds); - -public Q_SLOTS: - void start(); - void cancel(); - -Q_SIGNALS: - void started(KDJob *job); - void finished(KDJob *job); - - void infoMessage(KDJob *job, const QString &message); - void progress(KDJob *job, quint64 processed, quint64 total); - -protected: - virtual void doStart() = 0; - virtual void doCancel() = 0; - - 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 Q_SLOTS: - void onFinished(); - -private: - Private *d; - Q_PRIVATE_SLOT(d, void delayedStart()) -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS(KDJob::Capabilities) - -#endif // KDTOOLS_KDJOB_H diff --git a/src/libs/kdtools/kdlockfile.cpp b/src/libs/kdtools/kdlockfile.cpp deleted file mode 100644 index c929298e3..000000000 --- a/src/libs/kdtools/kdlockfile.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "kdlockfile.h" -#include "kdlockfile_p.h" - -KDLockFile::KDLockFile(const QString &name) - : d(new Private(name)) -{ -} - -KDLockFile::~KDLockFile() -{ - delete d; -} - -bool KDLockFile::lock() -{ - return d->lock(); -} - -QString KDLockFile::errorString() const -{ - return d->errorString; -} - -bool KDLockFile::unlock() -{ - return d->unlock(); -} diff --git a/src/libs/kdtools/kdlockfile.h b/src/libs/kdtools/kdlockfile.h deleted file mode 100644 index 615793fb4..000000000 --- a/src/libs/kdtools/kdlockfile.h +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef KDLOCKFILE_H -#define KDLOCKFILE_H - -#include - -class KDTOOLS_EXPORT KDLockFile -{ - Q_DISABLE_COPY(KDLockFile) - -public: - explicit KDLockFile(const QString &name); - ~KDLockFile(); - - QString errorString() const; - - bool lock(); - bool unlock(); - -private: - class Private; - Private *d; -}; - -#endif // KDLOCKFILE_H diff --git a/src/libs/kdtools/kdlockfile_p.h b/src/libs/kdtools/kdlockfile_p.h deleted file mode 100644 index 8c482a3a0..000000000 --- a/src/libs/kdtools/kdlockfile_p.h +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef KDLOCKFILE_P_H -#define KDLOCKFILE_P_H - -#include "kdlockfile.h" - -#include - -#ifdef Q_OS_WIN -# include -#endif - -class KDLockFile::Private -{ -public: - explicit Private(const QString& name) - : filename(name) - , handle(0) - , locked(false) - {} - - bool lock(); - bool unlock(); - - QString errorString; - -private: - QString filename; -#ifdef Q_OS_WIN - HANDLE handle; -#else - int handle; -#endif - bool locked; -}; - -#endif // KDLOCKFILE_P_H diff --git a/src/libs/kdtools/kdlockfile_unix.cpp b/src/libs/kdtools/kdlockfile_unix.cpp deleted file mode 100644 index d763c7c14..000000000 --- a/src/libs/kdtools/kdlockfile_unix.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "kdlockfile_p.h" - -#include -#include - -#include -#include -#include - -bool KDLockFile::Private::lock() -{ - if (locked) - return true; - - errorString.clear(); - errno = 0; - handle = open(filename.toLatin1().constData(), O_CREAT | O_RDWR | O_NONBLOCK, 0600); - if (handle == -1) { - errorString = QCoreApplication::translate("KDLockFile", "Cannot create lock file \"%1\": " - "%2").arg(QDir::toNativeSeparators(filename), QString::fromLocal8Bit(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 = QCoreApplication::translate("KDLockFile", "Cannot write PID to lock " - "file \"%1\": %2").arg(QDir::toNativeSeparators(filename), QString::fromLocal8Bit(strerror(errno))); - return false; - } - written += n; - } - errno = 0; - locked = flock(handle, LOCK_NB | LOCK_EX) != -1; - if (!locked) { - errorString = QCoreApplication::translate("KDLockFile", "Cannot obtain the lock for " - "file \"%1\": %2").arg(QDir::toNativeSeparators(filename), QString::fromLocal8Bit(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 = QCoreApplication::translate("KDLockFile", "Cannot release the lock for " - "file \"%1\": %2").arg(QDir::toNativeSeparators(filename), QString::fromLocal8Bit(strerror(errno))); - } else { - unlink(filename.toLatin1()); - } - return !locked; -} diff --git a/src/libs/kdtools/kdlockfile_win.cpp b/src/libs/kdtools/kdlockfile_win.cpp deleted file mode 100644 index b3241b003..000000000 --- a/src/libs/kdtools/kdlockfile_win.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "kdlockfile.h" -#include "kdlockfile_p.h" - -#include - -#include -#include -#include - -bool KDLockFile::Private::lock() -{ - if (locked) - return locked; - - errorString.clear(); - handle = CreateFile(filename.toStdWString().data(), GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ, NULL, QFileInfo(filename).exists() ? OPEN_EXISTING : CREATE_NEW, - FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, NULL); - - if (handle == INVALID_HANDLE_VALUE) { - errorString = QCoreApplication::translate("KDLockFile", "Cannot create lock file \"%1\": " - "%2").arg(QDir::toNativeSeparators(filename), QInstaller::windowsErrorString(GetLastError())); - return false; - } - - DWORD bytesWritten; - const QByteArray pid = QString::number(QCoreApplication::applicationPid()).toLatin1(); - if (!WriteFile(handle, pid.data(), pid.size(), &bytesWritten, NULL)) { - errorString = QCoreApplication::translate("KDLockFile", "Cannot write PID to lock file " - "\"%1\": %2").arg(QDir::toNativeSeparators(filename), QInstaller::windowsErrorString(GetLastError())); - return false; - } - FlushFileBuffers(handle); - - if (!LockFile(handle, 0, 0, QFileInfo(filename).size(), 0)) { - errorString = QCoreApplication::translate("KDLockFile", "Cannot obtain the lock for " - "file \"%1\": %2").arg(QDir::toNativeSeparators(filename), QInstaller::windowsErrorString(GetLastError())); - } else { - locked = true; - } - return locked; -} - -bool KDLockFile::Private::unlock() -{ - errorString.clear(); - if (!locked) - return true; - - if (!UnlockFile(handle, 0, 0, QFileInfo(filename).size(), 0)) { - errorString = QCoreApplication::translate("KDLockFile", "Cannot release the lock for " - "file \"%1\": %2").arg(QDir::toNativeSeparators(filename), QInstaller::windowsErrorString(GetLastError())); - } else { - locked = false; - CloseHandle(handle); - } - return !locked; -} diff --git a/src/libs/kdtools/kdrunoncechecker.cpp b/src/libs/kdtools/kdrunoncechecker.cpp deleted file mode 100644 index d3f953fcc..000000000 --- a/src/libs/kdtools/kdrunoncechecker.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "kdrunoncechecker.h" -#include "kdlockfile.h" -#include "kdsysinfo.h" - -#include -#include -#include -#include -#include - -#include - -using namespace KDUpdater; - -KDRunOnceChecker::KDRunOnceChecker(const QString &filename) - : m_lockfile(filename) -{ -} - -KDRunOnceChecker::~KDRunOnceChecker() -{ - if (!m_lockfile.unlock()) - qWarning().noquote() << m_lockfile.errorString(); -} - -class ProcessnameEquals -{ -public: - ProcessnameEquals(const QString &name) -#ifdef Q_OS_WIN - : m_name(name.toLower()) -#else - : m_name(name) -#endif - {} - - bool operator()(const ProcessInfo &info) - { -#ifdef Q_OS_WIN - const QString infoName = info.name.toLower(); - if (infoName == QDir::toNativeSeparators(m_name)) - return true; -#else - const QString infoName = info.name; -#endif - if (infoName == m_name) - return true; - - const QFileInfo fi(infoName); - if (fi.fileName() == m_name || fi.baseName() == m_name) - return true; - return false; - } - -private: - QString m_name; -}; - -bool KDRunOnceChecker::isRunning(KDRunOnceChecker::ConditionFlags flags) -{ - if (flags.testFlag(ConditionFlag::ProcessList)) { - const QList allProcesses = runningProcesses(); - const int count = std::count_if(allProcesses.constBegin(), allProcesses.constEnd(), - ProcessnameEquals(QCoreApplication::applicationFilePath())); - return (count > 1); - } - - if (flags.testFlag(ConditionFlag::Lockfile)) { - const bool locked = m_lockfile.lock(); - if (!locked) - qWarning().noquote() << m_lockfile.errorString(); - return !locked; - } - return false; -} diff --git a/src/libs/kdtools/kdrunoncechecker.h b/src/libs/kdtools/kdrunoncechecker.h deleted file mode 100644 index 9ee71b8e0..000000000 --- a/src/libs/kdtools/kdrunoncechecker.h +++ /dev/null @@ -1,63 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef KDTOOLS_RUNONCECHECKER_H -#define KDTOOLS_RUNONCECHECKER_H - -#include "kdlockfile.h" - -#include - -class KDTOOLS_EXPORT KDRunOnceChecker -{ - Q_DISABLE_COPY(KDRunOnceChecker) - -public: - enum struct ConditionFlag { - Lockfile = 0x01, - ProcessList = 0x02 - }; - Q_DECLARE_FLAGS(ConditionFlags, ConditionFlag) - - explicit KDRunOnceChecker(const QString &filename = QString()); - ~KDRunOnceChecker(); - - bool isRunning(KDRunOnceChecker::ConditionFlags flags); - -private: - KDLockFile m_lockfile; -}; - -#endif // KDTOOLS_RUNONCECHECKER_H diff --git a/src/libs/kdtools/kdselfrestarter.cpp b/src/libs/kdtools/kdselfrestarter.cpp deleted file mode 100644 index 358076506..000000000 --- a/src/libs/kdtools/kdselfrestarter.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "kdselfrestarter.h" - -#include -#include -#include - -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"); - delete d; - 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/src/libs/kdtools/kdselfrestarter.h b/src/libs/kdtools/kdselfrestarter.h deleted file mode 100644 index 3808ac207..000000000 --- a/src/libs/kdtools/kdselfrestarter.h +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef KDTOOLS_KDSELFRESTARTER_H -#define KDTOOLS_KDSELFRESTARTER_H - -#include "kdtoolsglobal.h" - -class KDTOOLS_EXPORT KDSelfRestarter -{ -public: - KDSelfRestarter(int argc, char *argv[]); - ~KDSelfRestarter(); - - static bool restartOnQuit(); - static void setRestartOnQuit(bool restart); - -private: - Q_DISABLE_COPY(KDSelfRestarter) - class Private; - Private *d; -}; - -#endif // KDTOOLS_KDSELFRESTARTER_H diff --git a/src/libs/kdtools/kdsysinfo.cpp b/src/libs/kdtools/kdsysinfo.cpp deleted file mode 100644 index c56e4c98f..000000000 --- a/src/libs/kdtools/kdsysinfo.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "kdsysinfo.h" - -#include -#include - -using namespace KDUpdater; - -struct PathLongerThan -{ - bool operator()(const VolumeInfo &lhs, const VolumeInfo &rhs) const - { - return lhs.mountPath().length() > rhs.mountPath().length(); - } -}; - -VolumeInfo::VolumeInfo() - : m_size(0) - , m_availableSize(0) -{ -} - -VolumeInfo VolumeInfo::fromPath(const QString &path) -{ - QDir targetPath(QDir::cleanPath(path)); - QList volumes = mountedVolumes(); - - // sort by length to get the longest mount point (not just "/") first - std::sort(volumes.begin(), volumes.end(), PathLongerThan()); - foreach (const VolumeInfo &volume, volumes) { - const QDir volumePath(volume.mountPath()); - if (targetPath == volumePath) - return volume; -#ifdef Q_OS_WIN - if (QDir::toNativeSeparators(path).toLower().startsWith(volume.mountPath().toLower())) -#else - // we need to take some care here, as canonical path might return an empty string if the target - // does not exist yet - if (targetPath.exists()) { - // the target exist, we can solve the path and if it fits return - if (targetPath.canonicalPath().startsWith(volume.mountPath())) - return volume; - continue; - } - - // the target directory does not exist yet, we need to cd up till we find the first existing dir - QStringList parts = targetPath.absolutePath().split(QDir::separator(),QString::SkipEmptyParts); - while (targetPath.absolutePath() != QDir::rootPath()) { - if (targetPath.exists()) - break; - parts.pop_back(); - if (parts.isEmpty()) - targetPath = QDir(QDir::rootPath()); - else - targetPath = QDir(QLatin1Char('/') + parts.join(QDir::separator())); - } - - if (targetPath.canonicalPath().startsWith(volume.mountPath())) -#endif - return volume; - } - return VolumeInfo(); -} - -QString VolumeInfo::mountPath() const -{ - return m_mountPath; -} - -void VolumeInfo::setMountPath(const QString &path) -{ - m_mountPath = path; -} - -QString VolumeInfo::fileSystemType() const -{ - return m_fileSystemType; -} - -void VolumeInfo::setFileSystemType(const QString &type) -{ - m_fileSystemType = type; -} - -QString VolumeInfo::volumeDescriptor() const -{ - return m_volumeDescriptor; -} - -void VolumeInfo::setVolumeDescriptor(const QString &descriptor) -{ - m_volumeDescriptor = descriptor; -} - -quint64 VolumeInfo::size() const -{ - return m_size; -} - -void VolumeInfo::setSize(const quint64 &size) -{ - m_size = size; -} - -quint64 VolumeInfo::availableSize() const -{ - return m_availableSize; -} - -void VolumeInfo::setAvailableSize(const quint64 &available) -{ - m_availableSize = available; -} - -bool VolumeInfo::operator==(const VolumeInfo &other) const -{ - return m_volumeDescriptor == other.m_volumeDescriptor; -} - -QDebug operator<<(QDebug dbg, VolumeInfo volume) -{ - return dbg << "KDUpdater::Volume(" << volume.mountPath() << ")"; -} - -QDebug operator<<(QDebug dbg, ProcessInfo process) -{ - return dbg << "KDUpdater::ProcessInfo(" << process.id << ", " << process.name << ")"; -} diff --git a/src/libs/kdtools/kdsysinfo.h b/src/libs/kdtools/kdsysinfo.h deleted file mode 100644 index 4b8f24fa1..000000000 --- a/src/libs/kdtools/kdsysinfo.h +++ /dev/null @@ -1,97 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef KDSYSINFO_H -#define KDSYSINFO_H - -#include - -#include - -namespace KDUpdater { - -class KDTOOLS_EXPORT VolumeInfo -{ -public: - VolumeInfo(); - static VolumeInfo fromPath(const QString &path); - - QString mountPath() const; - void setMountPath(const QString &path); - - QString fileSystemType() const; - void setFileSystemType(const QString &type); - - QString volumeDescriptor() const; - void setVolumeDescriptor(const QString &descriptor); - - quint64 size() const; - void setSize(const quint64 &size); - - quint64 availableSize() const; - void setAvailableSize(const quint64 &available); - - bool operator==(const VolumeInfo &other) const; - -private: - QString m_mountPath; - QString m_fileSystemType; - QString m_volumeDescriptor; - - quint64 m_size; - quint64 m_availableSize; -}; - -struct ProcessInfo -{ - quint32 id; - QString name; -}; - -quint64 installedMemory(); -QList mountedVolumes(); -QList runningProcesses(); -bool killProcess(const ProcessInfo &process, int msecs = 30000); -bool pathIsOnLocalDevice(const QString &path); - -} // namespace KDUpdater - -QT_BEGIN_NAMESPACE -class QDebug; -QT_END_NAMESPACE - -QDebug operator<<(QDebug dbg, KDUpdater::VolumeInfo volume); -QDebug operator<<(QDebug dbg, KDUpdater::ProcessInfo process); - -#endif // KDSYSINFO_H diff --git a/src/libs/kdtools/kdsysinfo_mac.cpp b/src/libs/kdtools/kdsysinfo_mac.cpp deleted file mode 100644 index 8c25bde42..000000000 --- a/src/libs/kdtools/kdsysinfo_mac.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "kdsysinfo.h" - -#include - -#include -#include -#include - -#include - -namespace KDUpdater { - -quint64 installedMemory() -{ - SInt32 mb = 0; - Gestalt(gestaltPhysicalRAMSizeInMegabytes, &mb); - return quint64(static_cast(mb) * 1024LL * 1024LL); -} - -QList mountedVolumes() -{ - QList 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) { - FSGetVolumeInfo(volume, 0, 0, kFSVolInfoSizes, &info, 0, 0); - - VolumeInfo v; - v.setSize(quint64(info.totalBytes)); - v.setAvailableSize(quint64(info.freeBytes)); - v.setMountPath(QString::fromLocal8Bit(reinterpret_cast< char* >(path))); - - struct statfs data; - if (statfs(qPrintable(v.mountPath() + QLatin1String("/.")), &data) == 0) { - v.setFileSystemType(QLatin1String(data.f_fstypename)); - v.setVolumeDescriptor(QLatin1String(data.f_mntfromname)); - } - result.append(v); - } - } - return result; -} - -QList runningProcesses() -{ - int mib[4] = { - CTL_KERN, - KERN_ARGMAX, - 0, - 0 - }; - - int argMax = 0; - size_t argMaxSize = sizeof(argMax); - // fetch the maximum process arguments size - sysctl(mib, 2, &argMax, &argMaxSize, NULL, 0); - char *processArguments = (char*) malloc(argMax); - - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_ALL; - size_t processTableSize = 0; - // fetch the kernel process table size - sysctl(mib, 4, NULL, &processTableSize, NULL, 0); - struct kinfo_proc *processTable = (kinfo_proc*) malloc(processTableSize); - - // fetch the process table - sysctl(mib, 4, processTable, &processTableSize, NULL, 0); - - QList processes; - for (size_t i = 0; i < (processTableSize / sizeof(struct kinfo_proc)); ++i) { - struct kinfo_proc *process = processTable + i; - - ProcessInfo processInfo; - processInfo.id = process->kp_proc.p_pid; - - mib[1] = KERN_PROCARGS2; - mib[2] = process->kp_proc.p_pid; - mib[3] = 0; - - size_t size = argMax; - // fetch the process arguments - if (sysctl(mib, 3, processArguments, &size, NULL, 0) != -1) { - /* - * |-----------------| <-- data returned by sysctl() - * | argc | - * |-----------------| - * | executable path | - * |-----------------| - * | arguments | - * ~~~~~~~~~~~~~~~~~~~ - * |-----------------| - */ - processInfo.name = QString::fromLocal8Bit(processArguments + sizeof(int)); - } else { - // if we fail, use the name from the process table - processInfo.name = QString::fromLocal8Bit(process->kp_proc.p_comm); - } - processes.append(processInfo); - } - free(processTable); - free(processArguments); - - return processes; -} - -bool pathIsOnLocalDevice(const QString &path) -{ - Q_UNUSED(path); - - return true; -} - -bool killProcess(const ProcessInfo &process, int msecs) -{ - Q_UNUSED(process); - Q_UNUSED(msecs); - - return true; -} - -} // namespace KDUpdater diff --git a/src/libs/kdtools/kdsysinfo_win.cpp b/src/libs/kdtools/kdsysinfo_win.cpp index 545cc6aad..c7358dbf1 100644 --- a/src/libs/kdtools/kdsysinfo_win.cpp +++ b/src/libs/kdtools/kdsysinfo_win.cpp @@ -32,7 +32,7 @@ ** ****************************************************************************/ -#include "kdsysinfo.h" +#include "sysinfo.h" #include #include diff --git a/src/libs/kdtools/kdsysinfo_x11.cpp b/src/libs/kdtools/kdsysinfo_x11.cpp deleted file mode 100644 index 41575f775..000000000 --- a/src/libs/kdtools/kdsysinfo_x11.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "kdsysinfo.h" - -#include -#include - -#include -#include -#include -#include - -namespace KDUpdater { - -quint64 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 quint64(); - - const QStringList parts = s.split(QLatin1Char(' '), QString::SkipEmptyParts); - return quint64(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 quint64(physmem); -#endif - return 0; -} - -QList mountedVolumes() -{ - QList result; - - QFile f(QLatin1String("/etc/mtab")); - if (!f.open(QIODevice::ReadOnly)) { - qCritical("%s: Cannot open %s: %s", Q_FUNC_INFO, qPrintable(f.fileName()), qPrintable(f.errorString())); - return result; //better error-handling? - } - - QTextStream stream(&f); - while (true) { - const QString s = stream.readLine(); - if (s.isNull()) - return result; - - if (!s.startsWith(QLatin1Char('/')) && !s.startsWith(QLatin1String("tmpfs ") + QDir::tempPath())) - continue; - - const QStringList parts = s.split(QLatin1Char(' '), QString::SkipEmptyParts); - - VolumeInfo v; - v.setMountPath(parts.at(1)); - v.setVolumeDescriptor(parts.at(0)); - v.setFileSystemType(parts.value(2)); - - struct statvfs data; - if (statvfs(qPrintable(v.mountPath() + QLatin1String("/.")), &data) == 0) { - v.setSize(quint64(static_cast(data.f_blocks) * data.f_bsize)); - v.setAvailableSize(quint64(static_cast(data.f_bavail) * data.f_bsize)); - } - result.append(v); - } - return result; -} - -QList runningProcesses() -{ - QList 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()) { - ProcessInfo processInfo; - processInfo.name = linkInfo.symLinkTarget(); - processInfo.id = info.fileName().toInt(); - processes.append(processInfo); - } - } - } - return processes; -} - -bool pathIsOnLocalDevice(const QString &path) -{ - Q_UNUSED(path); - - return true; -} - -bool killProcess(const ProcessInfo &process, int msecs) -{ - Q_UNUSED(process); - Q_UNUSED(msecs); - - return true; -} - -} // namespace KDUpdater diff --git a/src/libs/kdtools/kdtools.pri b/src/libs/kdtools/kdtools.pri index 80a569d86..eaa391e0f 100644 --- a/src/libs/kdtools/kdtools.pri +++ b/src/libs/kdtools/kdtools.pri @@ -5,49 +5,54 @@ DEFINES += BUILD_SHARED_KDTOOLS FORMS += $$PWD/authenticationdialog.ui HEADERS += $$PWD/kdtoolsglobal.h \ - $$PWD/kdjob.h \ - $$PWD/kdgenericfactory.h \ - $$PWD/kdselfrestarter.h \ - $$PWD/kdrunoncechecker.h \ - $$PWD/kdlockfile.h \ - $$PWD/kdsysinfo.h - -SOURCES += $$PWD/kdjob.cpp \ - $$PWD/kdselfrestarter.cpp \ - $$PWD/kdrunoncechecker.cpp \ - $$PWD/kdlockfile.cpp \ - $$PWD/kdsysinfo.cpp - - -HEADERS += $$PWD/kdupdater.h \ - $$PWD/kdupdaterfiledownloader.h \ - $$PWD/kdupdaterfiledownloader_p.h \ - $$PWD/kdupdaterfiledownloaderfactory.h \ + $$PWD/job.h \ + $$PWD/genericfactory.h \ + $$PWD/selfrestarter.h \ + $$PWD/runoncechecker.h \ + $$PWD/lockfile.h \ + $$PWD/sysinfo.h + +SOURCES += $$PWD/job.cpp \ + $$PWD/selfrestarter.cpp \ + $$PWD/runoncechecker.cpp \ + $$PWD/lockfile.cpp \ + $$PWD/sysinfo.cpp + + +HEADERS += $$PWD/updater.h \ + $$PWD/filedownloader.h \ + $$PWD/filedownloader_p.h \ + $$PWD/filedownloaderfactory.h \ $$PWD/localpackagehub.h \ - $$PWD/kdupdaterupdate.h \ - $$PWD/kdupdaterupdateoperation.h \ - $$PWD/kdupdaterupdateoperationfactory.h \ - $$PWD/kdupdaterupdateoperations.h \ - $$PWD/kdupdatertask.h \ - $$PWD/kdupdaterupdatefinder.h \ - $$PWD/kdupdaterupdatesinfo_p.h \ + $$PWD/update.h \ + $$PWD/updateoperation.h \ + $$PWD/updateoperationfactory.h \ + $$PWD/updateoperations.h \ + $$PWD/task.h \ + $$PWD/updatefinder.h \ + $$PWD/updatesinfo_p.h \ $$PWD/environment.h \ - $$PWD/kdupdaterupdatesinfodata_p.h + $$PWD/updatesinfodata_p.h -SOURCES += $$PWD/kdupdaterfiledownloader.cpp \ - $$PWD/kdupdaterfiledownloaderfactory.cpp \ +SOURCES += $$PWD/filedownloader.cpp \ + $$PWD/filedownloaderfactory.cpp \ $$PWD/localpackagehub.cpp \ - $$PWD/kdupdaterupdate.cpp \ - $$PWD/kdupdaterupdateoperation.cpp \ - $$PWD/kdupdaterupdateoperationfactory.cpp \ - $$PWD/kdupdaterupdateoperations.cpp \ - $$PWD/kdupdatertask.cpp \ - $$PWD/kdupdaterupdatefinder.cpp \ - $$PWD/kdupdaterupdatesinfo.cpp \ + $$PWD/update.cpp \ + $$PWD/updateoperation.cpp \ + $$PWD/updateoperationfactory.cpp \ + $$PWD/updateoperations.cpp \ + $$PWD/task.cpp \ + $$PWD/updatefinder.cpp \ + $$PWD/updatesinfo.cpp \ $$PWD/environment.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 +win32 { + SOURCES += $$PWD/lockfile_win.cpp \ + $$PWD/kdsysinfo_win.cpp +} + +unix { + SOURCES += $$PWD/lockfile_unix.cpp + osx: SOURCES += $$PWD/sysinfo_mac.cpp + else: SOURCES += $$PWD/sysinfo_x11.cpp +} diff --git a/src/libs/kdtools/kdupdater.h b/src/libs/kdtools/kdupdater.h deleted file mode 100644 index bd873227a..000000000 --- a/src/libs/kdtools/kdupdater.h +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef KD_UPDATER_H -#define KD_UPDATER_H - -#include "kdtoolsglobal.h" - -namespace KDUpdater -{ - enum Error - { - ENoError = 0, - ECannotStartTask, - ECannotPauseTask, - ECannotResumeTask, - ECannotStopTask, - EUnknown - }; - KDTOOLS_EXPORT int compareVersion(const QString &v1, const QString &v2); -} - -#endif diff --git a/src/libs/kdtools/kdupdaterfiledownloader.cpp b/src/libs/kdtools/kdupdaterfiledownloader.cpp deleted file mode 100644 index 919a0a20e..000000000 --- a/src/libs/kdtools/kdupdaterfiledownloader.cpp +++ /dev/null @@ -1,1407 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "kdupdaterfiledownloader_p.h" -#include "kdupdaterfiledownloaderfactory.h" -#include "ui_authenticationdialog.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace KDUpdater; -using namespace QInstaller; - -static double calcProgress(qint64 done, qint64 total) -{ - return total ? (double(done) / double(total)) : 0; -} - - -// -- KDUpdater::FileDownloader - -/*! - \inmodule kdupdater - \class KDUpdater::FileDownloader - \brief The FileDownloader class is the 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 files from a specific category of sources (such as - \c local, \c ftp, \c http). - - This is an internal class, not a part of the public API. Currently we have the - following subclasses of FileDownloader: - \list - \li HttpDownloader to download files over FTP, HTTP, or HTTPS if Qt is built with SSL. - \li LocalFileDownloader to copy files from the local file system. - \li ResourceFileDownloader to download resource files. - \endlist -*/ - -/*! - \property FileDownloader::autoRemoveDownloadedFile - \brief Whether the downloaded file should be automatically removed after it - is downloaded and the class goes out of scope. -*/ - -/*! - \property FileDownloader::url - \brief The URL to download files from. -*/ - -/*! - \property FileDownloader::scheme - \brief The scheme to use for downloading files. - */ - -/*! - \fn FileDownloader::authenticatorChanged(const QAuthenticator &authenticator) - This signal is emitted when the authenticator changes to \a authenticator. -*/ - -/*! - \fn FileDownloader::canDownload() const = 0 - Returns \c true if the file exists and is readable. -*/ - -/*! - \fn FileDownloader::clone(QObject *parent=0) const = 0 - Clones the local file downloader and assigns it the parent \a parent. -*/ - -/*! - \fn FileDownloader::downloadCanceled() - This signal is emitted if downloading a file is canceled. -*/ - -/*! - \fn FileDownloader::downloadedFileName() const = 0 - Returns the file name of the downloaded file. -*/ - -/*! - \fn FileDownloader::downloadProgress(double progress) - This signal is emitted with the current download \a progress. -*/ - -/*! - \fn FileDownloader::downloadProgress(qint64 bytesReceived, qint64 bytesToReceive) - This signal is emitted with the download progress as the number of received bytes, - \a bytesReceived, and the total size of the file to download, \a bytesToReceive. -*/ - -/*! - \fn FileDownloader::downloadSpeed(qint64 bytesPerSecond) - This signal is emitted with the download speed in bytes per second as \a bytesPerSecond. -*/ - -/*! - \fn FileDownloader::downloadStarted() - This signal is emitted when downloading a file starts. -*/ - -/*! - \fn FileDownloader::downloadStatus(const QString &status) - This signal is emitted with textual representation of the current download \a status in the - following format: "100 MiB of 150 MiB - (DAYS) (HOURS) (MINUTES) (SECONDS) remaining". -*/ - -/*! - \fn FileDownloader::estimatedDownloadTime(int seconds) - This signal is emitted with the estimated download time in \a seconds. -*/ - -/*! - \fn FileDownloader::isDownloaded() const = 0 - Returns \c true if the file is downloaded. -*/ - -/*! - \fn FileDownloader::onError() = 0 - Closes the destination file if an error occurs during copying and stops - the download speed timer. -*/ - -/*! - \fn FileDownloader::onSuccess() = 0 - Closes the destination file after it has been successfully copied and stops - the download speed timer. -*/ - -/*! - \fn FileDownloader::setDownloadedFileName(const QString &name) = 0 - Sets the file name of the downloaded file to \a name. -*/ - -struct KDUpdater::FileDownloader::Private -{ - Private() - : m_hash(QCryptographicHash::Sha1) - , m_assumedSha1Sum("") - , autoRemove(true) - , m_speedTimerInterval(100) - , m_bytesReceived(0) - , m_bytesToReceive(0) - , m_currentSpeedBin(0) - , m_sampleIndex(0) - , m_downloadSpeed(0) - , m_factory(0) - , m_ignoreSslErrors(false) - { - memset(m_samples, 0, sizeof(m_samples)); - } - - ~Private() - { - delete m_factory; - } - - QUrl url; - QString scheme; - - QCryptographicHash m_hash; - QByteArray m_assumedSha1Sum; - - QString errorString; - bool autoRemove; - bool followRedirect; - - QBasicTimer m_timer; - int m_speedTimerInterval; - - qint64 m_bytesReceived; - qint64 m_bytesToReceive; - - mutable qint64 m_samples[50]; - mutable qint64 m_currentSpeedBin; - mutable quint32 m_sampleIndex; - mutable qint64 m_downloadSpeed; - - QAuthenticator m_authenticator; - FileDownloaderProxyFactory *m_factory; - bool m_ignoreSslErrors; -}; - -/*! - Creates a file downloader with the scheme \a scheme and parent \a parent. -*/ -KDUpdater::FileDownloader::FileDownloader(const QString &scheme, QObject *parent) - : QObject(parent) - , d(new Private) -{ - d->scheme = scheme; - d->followRedirect = false; -} - -/*! - Destroys the file downloader. -*/ -KDUpdater::FileDownloader::~FileDownloader() -{ - delete d; -} - -void KDUpdater::FileDownloader::setUrl(const QUrl &url) -{ - d->url = url; -} - -QUrl KDUpdater::FileDownloader::url() const -{ - return d->url; -} - -/*! - Returns the SHA-1 checksum of the downloaded file. -*/ -QByteArray KDUpdater::FileDownloader::sha1Sum() const -{ - return d->m_hash.result(); -} - -/*! - Returns the assumed SHA-1 checksum of the file to download. -*/ -QByteArray KDUpdater::FileDownloader::assumedSha1Sum() const -{ - return d->m_assumedSha1Sum; -} - -/*! - Sets the assumed SHA-1 checksum of the file to download to \a sum. -*/ -void KDUpdater::FileDownloader::setAssumedSha1Sum(const QByteArray &sum) -{ - d->m_assumedSha1Sum = sum; -} - -/*! - Returns an error message. -*/ -QString FileDownloader::errorString() const -{ - return d->errorString; -} - -/*! - Sets the human readable description of the last error that occurred to \a error. Emits the - downloadStatus() and downloadAborted() signals. -*/ -void FileDownloader::setDownloadAborted(const QString &error) -{ - d->errorString = error; - emit downloadStatus(error); - emit downloadAborted(error); -} - -/*! - Sets the download status to \c completed and displays a status message. - - If an assumed SHA-1 checksum is set and the actual calculated checksum does not match it, sets - the status to \c error. If no SHA-1 is assumed, no check is performed, and status is set to - \c success. - - Emits the downloadCompleted() and downloadStatus() signals on success. -*/ -void KDUpdater::FileDownloader::setDownloadCompleted() -{ - if (d->m_assumedSha1Sum.isEmpty() || (d->m_assumedSha1Sum == sha1Sum())) { - onSuccess(); - emit downloadCompleted(); - emit downloadStatus(tr("Download finished.")); - } else { - onError(); - setDownloadAborted(tr("Cryptographic hashes do not match.")); - } -} - -/*! - Emits the downloadCanceled() and downloadStatus() signals. -*/ -void KDUpdater::FileDownloader::setDownloadCanceled() -{ - emit downloadCanceled(); - emit downloadStatus(tr("Download canceled.")); -} - -QString KDUpdater::FileDownloader::scheme() const -{ - return d->scheme; -} - -void KDUpdater::FileDownloader::setScheme(const QString &scheme) -{ - d->scheme = scheme; -} - -void KDUpdater::FileDownloader::setAutoRemoveDownloadedFile(bool val) -{ - d->autoRemove = val; -} - -/*! - Determines that redirects should be followed if \a val is \c true. -*/ -void KDUpdater::FileDownloader::setFollowRedirects(bool val) -{ - d->followRedirect = val; -} - -/*! - Returns whether redirects should be followed. -*/ -bool KDUpdater::FileDownloader::followRedirects() const -{ - return d->followRedirect; -} - -bool KDUpdater::FileDownloader::isAutoRemoveDownloadedFile() const -{ - return d->autoRemove; -} - -/*! - Downloads files. -*/ -void KDUpdater::FileDownloader::download() -{ - QMetaObject::invokeMethod(this, "doDownload", Qt::QueuedConnection); -} - -/*! - Cancels file download. -*/ -void KDUpdater::FileDownloader::cancelDownload() -{ - // Do nothing -} - -/*! - Starts the download speed timer. -*/ -void KDUpdater::FileDownloader::runDownloadSpeedTimer() -{ - if (!d->m_timer.isActive()) - d->m_timer.start(d->m_speedTimerInterval, this); -} - -/*! - Stops the download speed timer. -*/ -void KDUpdater::FileDownloader::stopDownloadSpeedTimer() -{ - d->m_timer.stop(); -} - -/*! - Adds \a sample to the current speed bin. -*/ -void KDUpdater::FileDownloader::addSample(qint64 sample) -{ - d->m_currentSpeedBin += sample; -} - -/*! - Returns the download speed timer ID. -*/ -int KDUpdater::FileDownloader::downloadSpeedTimerId() const -{ - return d->m_timer.timerId(); -} - -/*! - Sets the file download progress to the number of received bytes, \a bytesReceived, - and the number of total bytes to receive, \a bytesToReceive. -*/ -void KDUpdater::FileDownloader::setProgress(qint64 bytesReceived, qint64 bytesToReceive) -{ - d->m_bytesReceived = bytesReceived; - d->m_bytesToReceive = bytesToReceive; -} - -/*! - Calculates the download speed in bytes per second and emits the downloadSpeed() signal. -*/ -void KDUpdater::FileDownloader::emitDownloadSpeed() -{ - unsigned int windowSize = sizeof(d->m_samples) / sizeof(qint64); - - // add speed of last time bin to the window - d->m_samples[d->m_sampleIndex % windowSize] = d->m_currentSpeedBin; - d->m_currentSpeedBin = 0; // reset bin for next time interval - - // advance the sample index - d->m_sampleIndex++; - d->m_downloadSpeed = 0; - - // dynamic window size until the window is completely filled - if (d->m_sampleIndex < windowSize) - windowSize = d->m_sampleIndex; - - for (unsigned int i = 0; i < windowSize; ++i) - d->m_downloadSpeed += d->m_samples[i]; - - d->m_downloadSpeed /= windowSize; // computer average - d->m_downloadSpeed *= 1000.0 / d->m_speedTimerInterval; // rescale to bytes/second - - emit downloadSpeed(d->m_downloadSpeed); -} - -/*! - Builds a textual representation of the download status in the following format: - "100 MiB of 150 MiB - (DAYS) (HOURS) (MINUTES) (SECONDS) remaining". - - Emits the downloadStatus() signal. -*/ -void KDUpdater::FileDownloader::emitDownloadStatus() -{ - QString status; - if (d->m_bytesToReceive > 0) { - QString bytesReceived = humanReadableSize(d->m_bytesReceived); - const QString bytesToReceive = humanReadableSize(d->m_bytesToReceive); - - // remove the unit from the bytesReceived value if bytesToReceive has the same - const QString tmp = bytesToReceive.mid(bytesToReceive.indexOf(QLatin1Char(' '))); - if (bytesReceived.endsWith(tmp)) - bytesReceived.chop(tmp.length()); - - status = tr("%1 of %2").arg(bytesReceived).arg(bytesToReceive); - } else { - if (d->m_bytesReceived > 0) - status = tr("%1 downloaded.").arg(humanReadableSize(d->m_bytesReceived)); - } - - status += QLatin1Char(' ') + tr("(%1/sec)").arg(humanReadableSize(d->m_downloadSpeed)); - if (d->m_bytesToReceive > 0 && d->m_downloadSpeed > 0) { - const qint64 time = (d->m_bytesToReceive - d->m_bytesReceived) / d->m_downloadSpeed; - - int s = time % 60; - const int d = time / 86400; - const int h = (time / 3600) - (d * 24); - const int m = (time / 60) - (d * 1440) - (h * 60); - - QString days; - if (d > 0) - days = tr("%n day(s), ", "", d); - - QString hours; - if (h > 0) - hours = tr("%n hour(s), ", "", h); - - QString minutes; - if (m > 0) - minutes = tr("%n minute(s)", "", m); - - QString seconds; - if (s >= 0 && minutes.isEmpty()) { - s = (s <= 0 ? 1 : s); - seconds = tr("%n second(s)", "", s); - } - status += tr(" - %1%2%3%4 remaining.").arg(days).arg(hours).arg(minutes).arg(seconds); - } else { - status += tr(" - unknown time remaining."); - } - - emit downloadStatus(status); -} - -/*! - Emits dowload progress. -*/ -void KDUpdater::FileDownloader::emitDownloadProgress() -{ - emit downloadProgress(d->m_bytesReceived, d->m_bytesToReceive); -} - -/*! - Emits the estimated download time. -*/ -void KDUpdater::FileDownloader::emitEstimatedDownloadTime() -{ - if (d->m_bytesToReceive <= 0 || d->m_downloadSpeed <= 0) { - emit estimatedDownloadTime(-1); - return; - } - emit estimatedDownloadTime((d->m_bytesToReceive - d->m_bytesReceived) / d->m_downloadSpeed); -} - -/*! - \overload addCheckSumData() -*/ -void KDUpdater::FileDownloader::addCheckSumData(const QByteArray &data) -{ - d->m_hash.addData(data); -} - -/*! - Adds the \a length of characters of \a data to the cryptographic hash of the downloaded file. -*/ -void KDUpdater::FileDownloader::addCheckSumData(const char *data, int length) -{ - d->m_hash.addData(data, length); -} - -/*! - Resets SHA-1 checksum data of the downloaded file. -*/ -void KDUpdater::FileDownloader::resetCheckSumData() -{ - d->m_hash.reset(); -} - - -/*! - Returns a copy of the proxy factory that this FileDownloader object is using to determine the - proxies to be used for requests. -*/ -FileDownloaderProxyFactory *KDUpdater::FileDownloader::proxyFactory() const -{ - if (d->m_factory) - return d->m_factory->clone(); - return 0; -} - -/*! - Sets the proxy factory for this class to be \a factory. A proxy factory is used to determine a - more specific list of proxies to be used for a given request, instead of trying to use the same - proxy value for all requests. This might only be of use for HTTP or FTP requests. -*/ -void KDUpdater::FileDownloader::setProxyFactory(FileDownloaderProxyFactory *factory) -{ - delete d->m_factory; - d->m_factory = factory; -} - -/*! - Returns a copy of the authenticator that this FileDownloader object is using to set the username - and password for a download request. -*/ -QAuthenticator KDUpdater::FileDownloader::authenticator() const -{ - return d->m_authenticator; -} - -/*! - Sets the authenticator object for this class to be \a authenticator. An authenticator is used to - pass on the required authentication information. This might only be of use for HTTP or FTP - requests. Emits the authenticator changed signal with the new authenticator in use. -*/ -void KDUpdater::FileDownloader::setAuthenticator(const QAuthenticator &authenticator) -{ - if (d->m_authenticator.isNull() || (d->m_authenticator != authenticator)) { - d->m_authenticator = authenticator; - emit authenticatorChanged(authenticator); - } -} - -/*! - Returns \c true if SSL errors should be ignored. -*/ -bool KDUpdater::FileDownloader::ignoreSslErrors() -{ - return d->m_ignoreSslErrors; -} - -/*! - Determines that SSL errors should be ignored if \a ignore is \c true. -*/ -void KDUpdater::FileDownloader::setIgnoreSslErrors(bool ignore) -{ - d->m_ignoreSslErrors = ignore; -} - -// -- KDUpdater::LocalFileDownloader - -/*! - \inmodule kdupdater - \class KDUpdater::LocalFileDownloader - \brief The LocalFileDownloader class is used to copy files from the local - file system. - - The user of KDUpdater might be simultaneously downloading several files; - sometimes in parallel to other file downloaders. If copying a local file takes - a long time, it will make the other downloads hang. Therefore, a timer is used - and one block of data is copied per unit time, even though QFile::copy() does the - task of copying local files from one place to another. -*/ - -struct KDUpdater::LocalFileDownloader::Private -{ - Private() - : source(0) - , destination(0) - , downloaded(false) - , timerId(-1) - {} - - QFile *source; - QFile *destination; - QString destFileName; - bool downloaded; - int timerId; -}; - -/*! - Creates a local file downloader with the parent \a parent. -*/ -KDUpdater::LocalFileDownloader::LocalFileDownloader(QObject *parent) - : KDUpdater::FileDownloader(QLatin1String("file"), parent) - , d (new Private) -{ -} - -/*! - Destroys the local file downloader. -*/ -KDUpdater::LocalFileDownloader::~LocalFileDownloader() -{ - if (this->isAutoRemoveDownloadedFile() && !d->destFileName.isEmpty()) - QFile::remove(d->destFileName); - - delete d; -} - -/*! - Returns \c true if the file exists and is readable. -*/ -bool KDUpdater::LocalFileDownloader::canDownload() const -{ - QFileInfo fi(url().toLocalFile()); - return fi.exists() && fi.isReadable(); -} - -/*! - Returns \c true if the file is copied. -*/ -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); - if (!d->source->open(QFile::ReadOnly)) { - onError(); - setDownloadAborted(tr("Cannot open file \"%1\" for reading: %2").arg(QFileInfo(localFile) - .fileName(), d->source->errorString())); - return; - } - - if (d->destFileName.isEmpty()) { - QTemporaryFile *file = new QTemporaryFile(this); - file->open(); - d->destination = file; - } else { - d->destination = new QFile(d->destFileName, this); - d->destination->open(QIODevice::ReadWrite | QIODevice::Truncate); - } - - if (!d->destination->isOpen()) { - onError(); - setDownloadAborted(tr("Cannot open file \"%1\" for writing: %2") - .arg(QFileInfo(d->destination->fileName()).fileName(), d->destination->errorString())); - return; - } - - runDownloadSpeedTimer(); - // Start a timer and kickoff the copy process - d->timerId = startTimer(0); // as fast as possible - - emit downloadStarted(); - emit downloadProgress(0); -} - -/*! - Returns the file name of the copied file. -*/ -QString KDUpdater::LocalFileDownloader::downloadedFileName() const -{ - return d->destFileName; -} - -/*! - Sets the file name of the copied file to \a name. -*/ -void KDUpdater::LocalFileDownloader::setDownloadedFileName(const QString &name) -{ - d->destFileName = name; -} - -/*! - Clones the local file downloader and assigns it the parent \a parent. Returns - the new local file downloader. -*/ -KDUpdater::LocalFileDownloader *KDUpdater::LocalFileDownloader::clone(QObject *parent) const -{ - return new LocalFileDownloader(parent); -} - -/*! - Cancels copying the file. -*/ -void KDUpdater::LocalFileDownloader::cancelDownload() -{ - if (d->timerId < 0) - return; - - killTimer(d->timerId); - d->timerId = -1; - - onError(); - setDownloadCanceled(); -} - -/*! - Called when the download timer event \a event occurs. -*/ -void KDUpdater::LocalFileDownloader::timerEvent(QTimerEvent *event) -{ - if (event->timerId() == d->timerId) { - 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 file \"%1\" failed: %2").arg( - QDir::toNativeSeparators(d->destination->fileName()), - d->destination->errorString())); - return; - } - toWrite -= numWritten; - } - addSample(numRead); - addCheckSumData(buffer.data(), numRead); - - if (numRead > 0) { - setProgress(d->source->pos(), d->source->size()); - emit downloadProgress(calcProgress(d->source->pos(), d->source->size())); - return; - } - - d->destination->flush(); - - killTimer(d->timerId); - d->timerId = -1; - - setDownloadCompleted(); - } else if (event->timerId() == downloadSpeedTimerId()) { - emitDownloadSpeed(); - emitDownloadStatus(); - emitDownloadProgress(); - emitEstimatedDownloadTime(); - } -} - -/*! - Closes the destination file after it has been successfully copied and stops - the download speed timer. -*/ -void LocalFileDownloader::onSuccess() -{ - d->downloaded = true; - d->destFileName = d->destination->fileName(); - if (QTemporaryFile *file = dynamic_cast(d->destination)) - file->setAutoRemove(false); - d->destination->close(); - delete d->destination; - d->destination = 0; - delete d->source; - d->source = 0; - stopDownloadSpeedTimer(); -} - -/*! - Clears the destination file if an error occurs during copying and stops - the download speed timer. -*/ -void LocalFileDownloader::onError() -{ - d->downloaded = false; - d->destFileName.clear(); - delete d->destination; - d->destination = 0; - delete d->source; - d->source = 0; - stopDownloadSpeedTimer(); -} - - -// -- ResourceFileDownloader - -/*! - \inmodule kdupdater - \class KDUpdater::ResourceFileDownloader - \brief The ResourceFileDownloader class can be used to download resource files. -*/ -struct KDUpdater::ResourceFileDownloader::Private -{ - Private() - : timerId(-1) - , downloaded(false) - {} - - int timerId; - QFile destFile; - bool downloaded; -}; - -/*! - Creates a resource file downloader with the parent \a parent. -*/ -KDUpdater::ResourceFileDownloader::ResourceFileDownloader(QObject *parent) - : KDUpdater::FileDownloader(QLatin1String("resource"), parent) - , d(new Private) -{ -} - -/*! - Destroys the resource file downloader. -*/ -KDUpdater::ResourceFileDownloader::~ResourceFileDownloader() -{ - delete d; -} - -/*! - Returns \c true if the file exists and is readable. -*/ -bool KDUpdater::ResourceFileDownloader::canDownload() const -{ - const QFileInfo fi(QInstaller::pathFromUrl(url())); - return fi.exists() && fi.isReadable(); -} - -/*! - Returns \c true if the file is downloaded. -*/ -bool KDUpdater::ResourceFileDownloader::isDownloaded() const -{ - return d->downloaded; -} - -/*! - Downloads a resource file. -*/ -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->destFile.setFileName(QString::fromLatin1(":%1").arg(url.toLocalFile())); - - emit downloadStarted(); - emit downloadProgress(0); - - d->destFile.open(QIODevice::ReadOnly); - d->timerId = startTimer(0); // start as fast as possible -} - -/*! - Returns the file name of the downloaded file. -*/ -QString KDUpdater::ResourceFileDownloader::downloadedFileName() const -{ - return d->destFile.fileName(); -} - -/*! - Sets the file name of the downloaded file to \a name. -*/ -void KDUpdater::ResourceFileDownloader::setDownloadedFileName(const QString &/*name*/) -{ - // Not supported! -} - -/*! - Clones the resource file downloader and assigns it the parent \a parent. Returns - the new resource file downloader. -*/ -KDUpdater::ResourceFileDownloader *KDUpdater::ResourceFileDownloader::clone(QObject *parent) const -{ - return new ResourceFileDownloader(parent); -} - -/*! - Cancels downloading the file. -*/ -void KDUpdater::ResourceFileDownloader::cancelDownload() -{ - if (d->timerId < 0) - return; - - killTimer(d->timerId); - d->timerId = -1; - - setDownloadCanceled(); -} - -/*! - Called when the download timer event \a event occurs. -*/ -void KDUpdater::ResourceFileDownloader::timerEvent(QTimerEvent *event) -{ - if (event->timerId() == d->timerId) { - if (!d->destFile.isOpen()) { - onError(); - killTimer(d->timerId); - emit downloadProgress(1); - setDownloadAborted(tr("Cannot read resource file \"%1\": %2").arg(downloadedFileName(), - d->destFile.errorString())); - return; - } - - QByteArray buffer; - buffer.resize(32768); - const qint64 numRead = d->destFile.read(buffer.data(), buffer.size()); - - addSample(numRead); - addCheckSumData(buffer.data(), numRead); - - if (numRead > 0) { - setProgress(d->destFile.pos(), d->destFile.size()); - emit downloadProgress(calcProgress(d->destFile.pos(), d->destFile.size())); - return; - } - - killTimer(d->timerId); - d->timerId = -1; - setDownloadCompleted(); - } else if (event->timerId() == downloadSpeedTimerId()) { - emitDownloadSpeed(); - emitDownloadStatus(); - emitDownloadProgress(); - emitEstimatedDownloadTime(); - } -} - -/*! - Closes the destination file after it has been successfully copied and stops - the download speed timer. -*/ -void KDUpdater::ResourceFileDownloader::onSuccess() -{ - d->destFile.close(); - d->downloaded = true; - stopDownloadSpeedTimer(); -} - -/*! - Closes the destination file if an error occurs during copying and stops - the download speed timer. -*/ -void KDUpdater::ResourceFileDownloader::onError() -{ - d->destFile.close(); - d->downloaded = false; - stopDownloadSpeedTimer(); - d->destFile.setFileName(QString()); -} - - -// -- KDUpdater::HttpDownloader - -/*! - \inmodule kdupdater - \class KDUpdater::HttpDownloader - \brief The HttpDownloader class is used to download files over FTP, HTTP, or HTTPS. - - HTTPS is supported if Qt is built with SSL. -*/ -struct KDUpdater::HttpDownloader::Private -{ - explicit Private(HttpDownloader *qq) - : q(qq) - , http(0) - , destination(0) - , downloaded(false) - , aborted(false) - , m_authenticationCount(0) - {} - - HttpDownloader *const q; - QNetworkAccessManager manager; - QNetworkReply *http; - QFile *destination; - QString destFileName; - bool downloaded; - bool aborted; - int m_authenticationCount; - - void shutDown() - { - disconnect(http, &QNetworkReply::finished, q, &HttpDownloader::httpReqFinished); - http->deleteLater(); - http = 0; - destination->close(); - destination->deleteLater(); - destination = 0; - q->resetCheckSumData(); - } -}; - -/*! - Creates an HTTP downloader with the parent \a parent. -*/ -KDUpdater::HttpDownloader::HttpDownloader(QObject *parent) - : KDUpdater::FileDownloader(QLatin1String("http"), parent) - , d(new Private(this)) -{ -#ifndef QT_NO_SSL - connect(&d->manager, &QNetworkAccessManager::sslErrors, - this, &HttpDownloader::onSslErrors); -#endif - connect(&d->manager, &QNetworkAccessManager::authenticationRequired, - this, &HttpDownloader::onAuthenticationRequired); -} - -/*! - Destroys an HTTP downloader. - - Removes the downloaded file if FileDownloader::isAutoRemoveDownloadedFile() returns \c true or - FileDownloader::setAutoRemoveDownloadedFile() was called with \c true. -*/ -KDUpdater::HttpDownloader::~HttpDownloader() -{ - if (this->isAutoRemoveDownloadedFile() && !d->destFileName.isEmpty()) - QFile::remove(d->destFileName); - delete d; -} - -/*! - Returns \c true if the file exists and is readable. -*/ -bool KDUpdater::HttpDownloader::canDownload() const -{ - // TODO: Check whether the http file actually exists or not. - return true; -} - -/*! - Returns \c true if the file is downloaded. -*/ -bool KDUpdater::HttpDownloader::isDownloaded() const -{ - return d->downloaded; -} - -void KDUpdater::HttpDownloader::doDownload() -{ - if (d->downloaded) - return; - - if (d->http) - return; - - startDownload(url()); - runDownloadSpeedTimer(); -} - -/*! - Returns the file name of the downloaded file. -*/ -QString KDUpdater::HttpDownloader::downloadedFileName() const -{ - return d->destFileName; -} - -/*! - Sets the file name of the downloaded file to \a name. -*/ -void KDUpdater::HttpDownloader::setDownloadedFileName(const QString &name) -{ - d->destFileName = name; -} - -/*! - Clones the HTTP downloader and assigns it the parent \a parent. Returns the new - HTTP downloader. -*/ -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 error = d->destination->errorString(); - const QString fileName = d->destination->fileName(); - d->shutDown(); - setDownloadAborted(tr("Cannot download %1. Writing to file \"%2\" failed: %3") - .arg(url().toString(), fileName, error)); - return; - } - written += numWritten; - } - addSample(written); - addCheckSumData(buffer.data(), read); - } -} - -void KDUpdater::HttpDownloader::httpError(QNetworkReply::NetworkError) -{ - if (!d->aborted) - httpDone(true); -} - -/*! - Cancels downloading the file. -*/ -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; - setDownloadCanceled(); - } else { - setDownloadAborted(err); - } - } - //PENDING: what about the non-error case?? -} - -/*! - Closes the destination file if an error occurs during copying and stops - the download speed timer. -*/ -void KDUpdater::HttpDownloader::onError() -{ - d->downloaded = false; - d->destFileName.clear(); - delete d->destination; - d->destination = 0; - stopDownloadSpeedTimer(); -} - -/*! - Closes the destination file after it has been successfully copied and stops - the download speed timer. -*/ -void KDUpdater::HttpDownloader::onSuccess() -{ - d->downloaded = true; - d->destFileName = d->destination->fileName(); - if (QTemporaryFile *file = dynamic_cast(d->destination)) - file->setAutoRemove(false); - delete d->destination; - d->destination = 0; - stopDownloadSpeedTimer(); -} - -void KDUpdater::HttpDownloader::httpReqFinished() -{ - const QVariant redirect = d->http == 0 ? QVariant() - : d->http->attribute(QNetworkRequest::RedirectionTargetAttribute); - - const QUrl redirectUrl = redirect.toUrl(); - if (followRedirects() && redirectUrl.isValid()) { - d->shutDown(); // clean the previous download - startDownload(redirectUrl); - } else { - if (d->http == 0) - return; - - httpReadyRead(); - d->destination->flush(); - setDownloadCompleted(); - d->http->deleteLater(); - d->http = 0; - } -} - -void KDUpdater::HttpDownloader::httpReadProgress(qint64 done, qint64 total) -{ - if (d->http) { - const QUrl redirectUrl = d->http->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); - if (followRedirects() && redirectUrl.isValid()) - return; // if we are a redirection, do not emit the progress - } - - setProgress(done, total); - emit downloadProgress(calcProgress(done, total)); -} - -/*! - Called when the download timer event \a event occurs. -*/ -void KDUpdater::HttpDownloader::timerEvent(QTimerEvent *event) -{ - if (event->timerId() == downloadSpeedTimerId()) { - emitDownloadSpeed(); - emitDownloadStatus(); - emitDownloadProgress(); - emitEstimatedDownloadTime(); - } -} - -void KDUpdater::HttpDownloader::startDownload(const QUrl &url) -{ - d->m_authenticationCount = 0; - d->manager.setProxyFactory(proxyFactory()); - d->http = d->manager.get(QNetworkRequest(url)); - - connect(d->http, &QIODevice::readyRead, this, &HttpDownloader::httpReadyRead); - connect(d->http, &QNetworkReply::downloadProgress, - this, &HttpDownloader::httpReadProgress); - connect(d->http, &QNetworkReply::finished, this, &HttpDownloader::httpReqFinished); - void (QNetworkReply::*errorSignal)(QNetworkReply::NetworkError) = &QNetworkReply::error; - connect(d->http, errorSignal, this, &HttpDownloader::httpError); - - if (d->destFileName.isEmpty()) { - QTemporaryFile *file = new QTemporaryFile(this); - file->open(); - d->destination = file; - } else { - d->destination = new QFile(d->destFileName, this); - d->destination->open(QIODevice::ReadWrite | QIODevice::Truncate); - } - - if (!d->destination->isOpen()) { - const QString error = d->destination->errorString(); - const QString fileName = d->destination->fileName(); - d->shutDown(); - setDownloadAborted(tr("Cannot download %1. Cannot create file \"%2\": %3").arg( - url.toString(), fileName, error)); - } -} - -void KDUpdater::HttpDownloader::onAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator) -{ - Q_UNUSED(reply) - // first try with the information we have already - if (d->m_authenticationCount == 0) { - d->m_authenticationCount++; - authenticator->setUser(this->authenticator().user()); - authenticator->setPassword(this->authenticator().password()); - } else if (d->m_authenticationCount == 1) { - // we failed to authenticate, ask for new credentials - QDialog dlg; - Ui::Dialog ui; - ui.setupUi(&dlg); - dlg.adjustSize(); - ui.siteDescription->setText(tr("%1 at %2").arg(authenticator->realm()).arg(url().host())); - - ui.userEdit->setText(this->authenticator().user()); - ui.passwordEdit->setText(this->authenticator().password()); - - if (dlg.exec() == QDialog::Accepted) { - authenticator->setUser(ui.userEdit->text()); - authenticator->setPassword(ui.passwordEdit->text()); - - // update the authenticator we used initially - QAuthenticator auth; - auth.setUser(ui.userEdit->text()); - auth.setPassword(ui.passwordEdit->text()); - emit authenticatorChanged(auth); - } else { - d->shutDown(); - setDownloadAborted(tr("Authentication request canceled.")); - emit downloadCanceled(); - } - d->m_authenticationCount++; - } -} - -#ifndef QT_NO_SSL - -#include "messageboxhandler.h" - -void KDUpdater::HttpDownloader::onSslErrors(QNetworkReply* reply, const QList &errors) -{ - Q_UNUSED(reply) - QString errorString; - foreach (const QSslError &error, errors) { - if (!errorString.isEmpty()) - errorString += QLatin1String(", "); - errorString += error.errorString(); - } - qDebug() << errorString; - - const QStringList arguments = QCoreApplication::arguments(); - if (arguments.contains(QLatin1String("--script")) || arguments.contains(QLatin1String("Script")) - || ignoreSslErrors()) { - reply->ignoreSslErrors(); - return; - } - // TODO: Remove above code once we have a proper implementation for message box handler supporting - // methods used in the following code, right now we return here cause the message box is not scriptable. - - QMessageBox msgBox(MessageBoxHandler::currentBestSuitParent()); - msgBox.setDetailedText(errorString); - msgBox.setIcon(QMessageBox::Warning); - msgBox.setWindowModality(Qt::WindowModal); - msgBox.setWindowTitle(tr("Secure Connection Failed")); - msgBox.setText(tr("There was an error during connection to: %1.").arg(url().toString())); - msgBox.setInformativeText(QString::fromLatin1("
  • %1
  • %2
").arg(tr("This could be " - "a problem with the server's configuration, or it could be someone trying to impersonate the " - "server."), tr("If you have connected to this server successfully in the past or trust this server, " - "the error may be temporary and you can try again."))); - - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel); - msgBox.setButtonText(QMessageBox::Yes, tr("Try again")); - msgBox.setDefaultButton(QMessageBox::Cancel); - - if (msgBox.exec() == QMessageBox::Cancel) { - if (!d->aborted) - httpDone(true); - } else { - reply->ignoreSslErrors(); - KDUpdater::FileDownloaderFactory::instance().setIgnoreSslErrors(true); - } -} -#endif diff --git a/src/libs/kdtools/kdupdaterfiledownloader.h b/src/libs/kdtools/kdupdaterfiledownloader.h deleted file mode 100644 index a74097625..000000000 --- a/src/libs/kdtools/kdupdaterfiledownloader.h +++ /dev/null @@ -1,147 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef KD_UPDATER_FILE_DOWNLOADER_H -#define KD_UPDATER_FILE_DOWNLOADER_H - -#include "kdtoolsglobal.h" - -#include -#include - -#include - -namespace KDUpdater { - -class FileDownloaderProxyFactory; - -class KDTOOLS_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 WRITE setScheme) - -public: - explicit FileDownloader(const QString &scheme, QObject *parent = 0); - ~FileDownloader(); - - QUrl url() const; - void setUrl(const QUrl &url); - - QByteArray sha1Sum() const; - - QByteArray assumedSha1Sum() const; - void setAssumedSha1Sum(const QByteArray &sha1); - - QString scheme() const; - void setScheme(const QString &scheme); - - QString errorString() const; - - virtual bool canDownload() const = 0; - virtual bool isDownloaded() const = 0; - virtual QString downloadedFileName() const = 0; - virtual void setDownloadedFileName(const QString &name) = 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; - - FileDownloaderProxyFactory *proxyFactory() const; - void setProxyFactory(FileDownloaderProxyFactory *factory); - - QAuthenticator authenticator() const; - void setAuthenticator(const QAuthenticator &authenticator); - - bool ignoreSslErrors(); - void setIgnoreSslErrors(bool ignore); - -public Q_SLOTS: - virtual void cancelDownload(); - -protected: - virtual void onError() = 0; - virtual void onSuccess() = 0; - -Q_SIGNALS: - void downloadStarted(); - void downloadCanceled(); - - void downloadProgress(double progress); - void estimatedDownloadTime(int seconds); - void downloadSpeed(qint64 bytesPerSecond); - void downloadStatus(const QString &status); - void downloadProgress(qint64 bytesReceived, qint64 bytesToReceive); - void authenticatorChanged(const QAuthenticator &authenticator); - void downloadCompleted(); - void downloadAborted(const QString &errorMessage); - -protected: - void setDownloadCanceled(); - void setDownloadCompleted(); - void setDownloadAborted(const QString &error); - - void runDownloadSpeedTimer(); - void stopDownloadSpeedTimer(); - - void addSample(qint64 sample); - int downloadSpeedTimerId() const; - void setProgress(qint64 bytesReceived, qint64 bytesToReceive); - - void emitDownloadSpeed(); - void emitDownloadStatus(); - void emitDownloadProgress(); - void emitEstimatedDownloadTime(); - - void addCheckSumData(const QByteArray &data); - void addCheckSumData(const char *data, int length); - void resetCheckSumData(); - -private Q_SLOTS: - virtual void doDownload() = 0; - -private: - struct Private; - Private *d; -}; - -} // namespace KDUpdater - -#endif // KD_UPDATER_FILE_DOWNLOADER_H diff --git a/src/libs/kdtools/kdupdaterfiledownloader_p.h b/src/libs/kdtools/kdupdaterfiledownloader_p.h deleted file mode 100644 index e3be06ae4..000000000 --- a/src/libs/kdtools/kdupdaterfiledownloader_p.h +++ /dev/null @@ -1,150 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef KD_UPDATER_FILE_DOWNLOADER_P_H -#define KD_UPDATER_FILE_DOWNLOADER_P_H - -#include "kdupdaterfiledownloader.h" - -#include - -// these classes are not a part of the public API - -namespace KDUpdater { - -class LocalFileDownloader : public FileDownloader -{ - Q_OBJECT - -public: - explicit LocalFileDownloader(QObject *parent = 0); - ~LocalFileDownloader(); - - bool canDownload() const; - bool isDownloaded() const; - QString downloadedFileName() const; - void setDownloadedFileName(const QString &name); - LocalFileDownloader *clone(QObject *parent = 0) const; - -public Q_SLOTS: - void cancelDownload(); - -protected: - void timerEvent(QTimerEvent *te); - void onError(); - void onSuccess(); - -private Q_SLOTS: - void doDownload(); - -private: - struct Private; - Private *d; -}; - -class ResourceFileDownloader : public FileDownloader -{ - Q_OBJECT - -public: - explicit ResourceFileDownloader(QObject *parent = 0); - ~ResourceFileDownloader(); - - bool canDownload() const; - bool isDownloaded() const; - QString downloadedFileName() const; - void setDownloadedFileName(const QString &name); - ResourceFileDownloader *clone(QObject *parent = 0) const; - -public Q_SLOTS: - void cancelDownload(); - -protected: - void timerEvent(QTimerEvent *te); - void onError(); - void onSuccess(); - -private Q_SLOTS: - void doDownload(); - -private: - struct Private; - Private *d; -}; - -class HttpDownloader : public FileDownloader -{ - Q_OBJECT - -public: - explicit HttpDownloader(QObject *parent = 0); - ~HttpDownloader(); - - bool canDownload() const; - bool isDownloaded() const; - QString downloadedFileName() const; - void setDownloadedFileName(const QString &name); - HttpDownloader *clone(QObject *parent = 0) const; - -public Q_SLOTS: - void cancelDownload(); - -protected: - void onError(); - void onSuccess(); - void timerEvent(QTimerEvent *event); - -private Q_SLOTS: - void doDownload(); - - void httpReadyRead(); - void httpReadProgress(qint64 done, qint64 total); - void httpError(QNetworkReply::NetworkError); - void httpDone(bool error); - void httpReqFinished(); - void onAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator); -#ifndef QT_NO_SSL - void onSslErrors(QNetworkReply* reply, const QList &errors); -#endif -private: - void startDownload(const QUrl &url); - -private: - struct Private; - Private *d; -}; - -} // namespace KDUpdater - -#endif // KD_UPDATER_FILE_DOWNLOADER_P_H diff --git a/src/libs/kdtools/kdupdaterfiledownloaderfactory.cpp b/src/libs/kdtools/kdupdaterfiledownloaderfactory.cpp deleted file mode 100644 index 73eb4c02f..000000000 --- a/src/libs/kdtools/kdupdaterfiledownloaderfactory.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "kdupdaterfiledownloaderfactory.h" -#include "kdupdaterfiledownloader_p.h" - -#include - -using namespace KDUpdater; - -/*! - \inmodule kdupdater - \class KDUpdater::FileDownloaderFactory - \brief The FileDownloaderFactory class acts as a factory for KDUpdater::FileDownloader. - - You can register one or more file downloaders with this factory and query them based on their - scheme. The class follows the singleton design pattern. Only one instance of this class can - be created and its reference can be fetched from the instance() method. -*/ - -/*! - Returns the file downloader factory instance. -*/ -FileDownloaderFactory& FileDownloaderFactory::instance() -{ - static KDUpdater::FileDownloaderFactory theFactory; - return theFactory; -} - -/*! - Constructs a file downloader factory and registers the default file downloader set. -*/ -FileDownloaderFactory::FileDownloaderFactory() - : d (new FileDownloaderFactoryData) -{ - // Register the default file downloader set - registerFileDownloader( QLatin1String("file")); - registerFileDownloader(QLatin1String("ftp")); - registerFileDownloader(QLatin1String("http")); - registerFileDownloader(QLatin1String("resource")); - -#ifndef QT_NO_SSL - if (QSslSocket::supportsSsl()) - registerFileDownloader(QLatin1String("https")); - else - qWarning() << "Cannot register file downloader for https protocol: QSslSocket::supportsSsl() returns false"; -#endif - - d->m_followRedirects = false; -} - -/*! - Returns whether redirects should be followed. -*/ -bool FileDownloaderFactory::followRedirects() -{ - return FileDownloaderFactory::instance().d->m_followRedirects; -} - -/*! - Determines that redirects should be followed if \a val is \c true. -*/ -void FileDownloaderFactory::setFollowRedirects(bool val) -{ - FileDownloaderFactory::instance().d->m_followRedirects = val; -} - -/*! - Sets \a factory as the file downloader proxy factory. -*/ -void FileDownloaderFactory::setProxyFactory(FileDownloaderProxyFactory *factory) -{ - delete FileDownloaderFactory::instance().d->m_factory; - FileDownloaderFactory::instance().d->m_factory = factory; -} - -/*! - Returns \c true if SSL errors should be ignored. -*/ -bool FileDownloaderFactory::ignoreSslErrors() -{ - return FileDownloaderFactory::instance().d->m_ignoreSslErrors; -} - -/*! - Determines that SSL errors should be ignored if \a ignore is \c true. -*/ -void FileDownloaderFactory::setIgnoreSslErrors(bool ignore) -{ - FileDownloaderFactory::instance().d->m_ignoreSslErrors = ignore; -} - -/*! - Destroys the file downloader factory. -*/ -FileDownloaderFactory::~FileDownloaderFactory() -{ - delete d; -} - -/*! - Returns a list of supported schemes. -*/ -QStringList FileDownloaderFactory::supportedSchemes() -{ - return FileDownloaderFactory::instance().d->m_supportedSchemes; -} - -/*! - Returns \c true if \a scheme is a supported scheme. -*/ -bool FileDownloaderFactory::isSupportedScheme(const QString &scheme) -{ - return FileDownloaderFactory::instance().d->m_supportedSchemes.contains(scheme - , Qt::CaseInsensitive); -} - -/*! - Returns a new instance of a KDUpdater::FileDownloader subclass. The - instantiation of a subclass depends on the communication protocol string - stored in \a scheme with the parent \a parent. - - \note Ownership of the created object remains with the programmer. -*/ -FileDownloader *FileDownloaderFactory::create(const QString &scheme, QObject *parent) const -{ - FileDownloader *downloader = - KDGenericFactory::create(scheme, parent); - if (downloader != 0) { - downloader->setFollowRedirects(d->m_followRedirects); - downloader->setIgnoreSslErrors(d->m_ignoreSslErrors); - if (d->m_factory) - downloader->setProxyFactory(d->m_factory->clone()); - } - return downloader; -} - -/*! - \fn void KDUpdater::FileDownloaderFactory::registerFileDownloader(const QString &scheme) - - Registers a new file downloader with the factory based on \a scheme. If there is already - a downloader with the same scheme, the downloader is replaced. When create() is called - with that \a scheme, the file downloader is constructed using its default constructor. -*/ - -/*! - \inmodule kdupdater - \class KDUpdater::FileDownloaderProxyFactory - \brief The FileDownloaderProxyFactory class provides fine-grained proxy selection. - - File downloader objects use a proxy factory to determine a more specific - list of proxies to be used for a given request, instead of trying to use the - same proxy value for all requests. This might only be of use for HTTP or FTP - requests. -*/ - -/*! - \fn FileDownloaderProxyFactory::~FileDownloaderProxyFactory() - - Destroys the file downloader proxy factory. -*/ - -/*! - \fn FileDownloaderProxyFactory::clone() const - - Clones a file downloader proxy factory. -*/ diff --git a/src/libs/kdtools/kdupdaterfiledownloaderfactory.h b/src/libs/kdtools/kdupdaterfiledownloaderfactory.h deleted file mode 100644 index ad0aa00d0..000000000 --- a/src/libs/kdtools/kdupdaterfiledownloaderfactory.h +++ /dev/null @@ -1,107 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef KD_UPDATER_FILE_DOWNLOADER_FACTORY_H -#define KD_UPDATER_FILE_DOWNLOADER_FACTORY_H - -#include "kdupdater.h" -#include - -#include -#include - -#include - -QT_BEGIN_NAMESPACE -class QObject; -QT_END_NAMESPACE - -namespace KDUpdater { - -class FileDownloader; - -class KDTOOLS_EXPORT FileDownloaderProxyFactory : public QNetworkProxyFactory -{ -public: - virtual ~FileDownloaderProxyFactory() {} - virtual FileDownloaderProxyFactory *clone() const = 0; -}; - -class KDTOOLS_EXPORT FileDownloaderFactory : public KDGenericFactory -{ - Q_DISABLE_COPY(FileDownloaderFactory) - struct FileDownloaderFactoryData { - FileDownloaderFactoryData() : m_factory(0) {} - ~FileDownloaderFactoryData() { delete m_factory; } - - bool m_followRedirects; - bool m_ignoreSslErrors; - QStringList m_supportedSchemes; - FileDownloaderProxyFactory *m_factory; - }; - -public: - static FileDownloaderFactory &instance(); - ~FileDownloaderFactory(); - - template - void registerFileDownloader(const QString &scheme) - { - registerProduct(scheme); - d->m_supportedSchemes.append(scheme); - } - FileDownloader *create(const QString &scheme, QObject *parent = 0) const; - - static bool followRedirects(); - static void setFollowRedirects(bool val); - - static void setProxyFactory(FileDownloaderProxyFactory *factory); - - static bool ignoreSslErrors(); - static void setIgnoreSslErrors(bool ignore); - - static QStringList supportedSchemes(); - static bool isSupportedScheme(const QString &scheme); - -private: - FileDownloaderFactory(); - -private: - FileDownloaderFactoryData *d; -}; - -} // namespace KDUpdater - -#endif // KD_UPDATER_FILE_DOWNLOADER_FACTORY_H diff --git a/src/libs/kdtools/kdupdatertask.cpp b/src/libs/kdtools/kdupdatertask.cpp deleted file mode 100644 index 8278ff6a6..000000000 --- a/src/libs/kdtools/kdupdatertask.cpp +++ /dev/null @@ -1,455 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "kdupdatertask.h" - -using namespace KDUpdater; - -/*! - \inmodule kdupdater - \class KDUpdater::Task - \brief The Task class is the base class for all tasks 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. - - User should be careful of these points: - \list - \li Task classes can be started only once. - \li Instances of this class cannot be created. Only instances of the subclasses can. - \endlist -*/ - -/*! - \enum Task::Capability - This enum value sets the capabilities of the task. - - \value NoCapability - The task has no capabilities, so it cannot be paused or stopped. - \value Pausable - The task can be paused. - \value Stoppable - The task can be stopped. -*/ - -/*! - \internal -*/ -KDUpdater::Task::Task(const QString &name, int caps, QObject *parent) - : QObject(parent) - , m_caps(caps) - , m_name(name) - , m_errorCode(0) - , m_started(false) - , m_finished(false) - , m_paused(false) - , m_stopped(false) - , m_progressPc(0) - , m_autoDelete(true) -{ -} - -/*! - \internal -*/ -Task::~Task() -{} - -/*! - Returns the name of the task. -*/ -QString Task::name() const -{ - return m_name; -} - -/*! - Returns the capabilities of the task. It is a combination of one or more - Task::Capability flags. -*/ -int Task::capabilities() const -{ - return m_caps; -} - -/*! - Returns the last reported error code. -*/ -int Task::error() const -{ - return m_errorCode; -} - -/*! - Returns the last reported error message text. -*/ -QString Task::errorString() const -{ - return m_errorText; -} - -/*! - Returns whether the task has started and is running. -*/ -bool Task::isRunning() const -{ - return m_started; -} - -/*! - Returns whether the task has finished or not. - - \note Stopped (or canceled) tasks are not finished tasks. -*/ -bool Task::isFinished() const -{ - return m_finished; -} - -/*! - Returns whether the task is paused or not. -*/ -bool Task::isPaused() const -{ - return m_paused; -} - -/*! - Returns whether the task is stopped or not. - - \note Finished tasks are not stopped classes. -*/ -bool Task::isStopped() const -{ - return m_stopped; -} - -/*! - Returns the progress in percentage made by this task. -*/ -int Task::progressPercent() const -{ - return m_progressPc; -} - -/*! - Returns a string that describes the progress made by this task as a string. -*/ -QString Task::progressText() const -{ - return m_progressText; -} - -/*! - Starts the task. -*/ -void Task::run() -{ - if (m_started) { - qDebug("Trying to start an already started task"); - return; - } - - if (m_finished || m_stopped) { - qDebug("Trying to start a finished or canceled task"); - return; - } - - m_stopped = false; - m_finished = false; // for the sake of completeness - m_started = true; - emit started(); - reportProgress(0, tr("%1 started").arg(m_name)); - - doRun(); -} - -/*! - Stops the task, provided the task has the Task::Stoppable capability. - - \note Once the task is stopped, it cannot be restarted. -*/ -void Task::stop() -{ - if (!(m_caps & Stoppable)) { - const QString errorMsg = tr("%1 cannot be stopped").arg(m_name); - reportError(ECannotStopTask, errorMsg); - return; - } - - if (!m_started) { - qDebug("Trying to stop an unstarted task"); - return; - } - - if(m_finished || m_stopped) - { - qDebug("Trying to stop a finished or canceled task"); - return; - } - - m_stopped = doStop(); - if (!m_stopped) { - const QString errorMsg = tr("Cannot stop task %1").arg(m_name); - reportError(ECannotStopTask, errorMsg); - return; - } - - m_started = false; // the task is not running - m_finished = false; // the task is not finished, but was canceled half-way through - - emit stopped(); - if (m_autoDelete) - deleteLater(); -} - -/*! - Pauses the task, provided the task has the Task::Pausable capability. -*/ -void Task::pause() -{ - if (!(m_caps & Pausable)) { - const QString errorMsg = tr("%1 cannot be paused").arg(m_name); - reportError(ECannotPauseTask, errorMsg); - return; - } - - if (!m_started) { - qDebug("Trying to pause an unstarted task"); - return; - } - - if (m_finished || m_stopped) { - qDebug("Trying to pause a finished or canceled task"); - return; - } - - m_paused = doPause(); - - if (!m_paused) { - const QString errorMsg = tr("Cannot pause task %1").arg(m_name); - reportError(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() ??? - m_started = true; - m_finished = false; - m_stopped = false; - - emit paused(); -} - -/*! - Resumes the task if it was paused. -*/ -void Task::resume() -{ - if (!m_paused) { - qDebug("Trying to resume an unpaused task"); - return; - } - - const bool val = doResume(); - - if (!val) { - const QString errorMsg = tr("Cannot resume task %1").arg(m_name); - reportError(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() ??? - m_started = true; - m_paused = false; - m_finished = false; - m_stopped = false; - - emit resumed(); -} - -/*! - \internal -*/ -void Task::reportProgress(int percent, const QString &text) -{ - if (m_progressPc == percent) - return; - - m_progressPc = percent; - m_progressText = text; - emit progressValue(m_progressPc); - emit progressText(m_progressText); -} - -/*! - \internal -*/ -void Task::reportError(int errorCode, const QString &errorText) -{ - m_errorCode = errorCode; - m_errorText = errorText; - - emit error(m_errorCode, m_errorText); - if (m_autoDelete) - deleteLater(); -} - -/*! - \internal -*/ -void Task::reportError(const QString &errorText) -{ - reportError(EUnknown, errorText); -} - -/*! - \internal -*/ -void Task::reportDone() -{ - QString msg = tr("%1 done"); - reportProgress(100, msg); - - // State should be finished, but not started, paused or stopped. - m_finished = true; - m_started = false; - m_paused = false; - m_stopped = false; - m_errorCode = 0; - m_errorText.clear(); - - emit finished(); - if (m_autoDelete) - deleteLater(); -} - -/*! - Returns \c true if the task will be automatically deleted. -*/ -bool Task::autoDelete() const -{ - return m_autoDelete; -} - -/*! - Automatically deletes the task if \a autoDelete is \c true. -*/ -void Task::setAutoDelete(bool autoDelete) -{ - m_autoDelete = autoDelete; -} - -/*! - \fn virtual void KDUpdater::Task::doRun() = 0; - - Returns \c 0 if the task is run. -*/ - -/*! - \fn virtual bool KDUpdater::Task::doStop() = 0; - - Returns \c true if the task is stopped. -*/ - -/*! - \fn virtual bool KDUpdater::Task::doPause() = 0; - - Returns \c true if the task is paused. -*/ - -/*! - \fn virtual bool KDUpdater::Task::doResume() = 0; - - Returns \c true if the task is resumed. -*/ - -/*! - \fn void Task::error(int code, const QString &errorText) - - This signal is emitted to notify an error during the execution of this task. - - The \a code parameter indicates the error that was found during the execution of the - task, while the \a errorText is the human-readable description of the last error that occurred. -*/ - -/*! - \fn void Task::progressValue(int percent) - - This signal is emitted to report progress made by the task. The \a percent parameter gives - the progress made as a percentage. -*/ - -/*! - \fn void Task::progressText(const QString &progressText) - - This signal is emitted to report the progress made by the task. The \a progressText parameter - represents the progress made in a human-readable form. -*/ - -/*! - \fn void Task::started() - - This signal is emitted when the task has started. -*/ - -/*! - \fn void Task::paused() - - This signal is emitted when the task has paused. -*/ - -/*! - \fn void Task::resumed() - - This signal is emitted when the task has resumed. -*/ - -/*! - \fn void Task::stopped() - - This signal is emitted when the task has stopped (or canceled). -*/ - -/*! - \fn void Task::finished() - - This signal is emitted when the task has finished. -*/ diff --git a/src/libs/kdtools/kdupdatertask.h b/src/libs/kdtools/kdupdatertask.h deleted file mode 100644 index 5eea26348..000000000 --- a/src/libs/kdtools/kdupdatertask.h +++ /dev/null @@ -1,120 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef KD_UPDATER_TASK_H -#define KD_UPDATER_TASK_H - -#include "kdupdater.h" - -#include - -namespace KDUpdater { - -class KDTOOLS_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; - - bool autoDelete() const; - void setAutoDelete(bool autoDelete); - -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 reportError(const QString &errorText); - void reportDone(); - - // Task interface - virtual void doRun() = 0; - virtual bool doStop() = 0; - virtual bool doPause() = 0; - virtual bool doResume() = 0; - -private: - int m_caps; - QString m_name; - int m_errorCode; - QString m_errorText; - bool m_started; - bool m_finished; - bool m_paused; - bool m_stopped; - int m_progressPc; - QString m_progressText; - bool m_autoDelete; -}; - -} // namespace KDUpdater - -#endif // KD_UPDATER_TASK_H diff --git a/src/libs/kdtools/kdupdaterupdate.cpp b/src/libs/kdtools/kdupdaterupdate.cpp deleted file mode 100644 index 9b6f7b3d9..000000000 --- a/src/libs/kdtools/kdupdaterupdate.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "kdupdaterupdate.h" - -using namespace KDUpdater; - -/*! - \inmodule kdupdater - \class KDUpdater::Update - \brief Represents a single update - - The KDUpdater::Update class contains information about an update. It is created by KDUpdater::UpdateFinder - corresponding to the update. - - 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. -*/ - - -/*! - \internal -*/ -Update::Update(const QInstaller::PackageSource &packageSource, const UpdateInfo &updateInfo) - : m_packageSource(packageSource) - , m_updateInfo(updateInfo) -{ -} - -/*! - Returns the data specified by \a name, or an invalid \a defaultValue if the - data does not exist. -*/ -QVariant Update::data(const QString &name, const QVariant &defaultValue) const -{ - return m_updateInfo.data.value(name, defaultValue); -} diff --git a/src/libs/kdtools/kdupdaterupdate.h b/src/libs/kdtools/kdupdaterupdate.h deleted file mode 100644 index ecd5508f5..000000000 --- a/src/libs/kdtools/kdupdaterupdate.h +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef KD_UPDATER_UPDATE_H -#define KD_UPDATER_UPDATE_H - -#include -#include -#include - -namespace KDUpdater { - -class Update -{ -public: - QVariant data(const QString &name, const QVariant &defaultValue = QVariant()) const; - - QInstaller::PackageSource packageSource() const {return m_packageSource; } - -private: - friend class UpdateFinder; - Update(const QInstaller::PackageSource &packageSource, const UpdateInfo &updateInfo); - -private: - QInstaller::PackageSource m_packageSource; - UpdateInfo m_updateInfo; -}; - -} // namespace KDUpdater - -#endif // KD_UPDATER_UPDATE_H diff --git a/src/libs/kdtools/kdupdaterupdatefinder.cpp b/src/libs/kdtools/kdupdaterupdatefinder.cpp deleted file mode 100644 index 9791ca454..000000000 --- a/src/libs/kdtools/kdupdaterupdatefinder.cpp +++ /dev/null @@ -1,640 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "kdupdaterupdatefinder.h" -#include "kdupdaterupdate.h" -#include "kdupdaterfiledownloader.h" -#include "kdupdaterfiledownloaderfactory.h" -#include "kdupdaterupdatesinfo_p.h" -#include "localpackagehub.h" - -#include "fileutils.h" -#include "globals.h" - -#include -#include - -using namespace KDUpdater; -using namespace QInstaller; - -/*! - \inmodule kdupdater - \class KDUpdater::UpdateFinder - \brief The UpdaterFinder class finds updates applicable for installed packages. - - The KDUpdater::UpdateFinder class helps in searching for updates and installing them on the - application. The class basically processes the application's KDUpdater::PackagesInfo and the - UpdateXMLs it aggregates from all the update sources and populates a list of KDUpdater::Update - objects. -*/ - -// -// Private -// -class UpdateFinder::Private -{ -public: - enum struct Resolution { - AddPackage, - KeepExisting, - RemoveExisting - }; - - Private(UpdateFinder *qq) - : q(qq) - , downloadCompleteCount(0) - , m_downloadsToComplete(0) - {} - - ~Private() - { - clear(); - } - - struct Data { - Data() - : downloader(0) {} - Data(const PackageSource &i, FileDownloader *d = 0) - : info(i), downloader(d) {} - - PackageSource info; - FileDownloader *downloader; - }; - UpdateFinder *q; - QHash updates; - - // Temporary structure that notes down information about updates. - bool cancel; - int downloadCompleteCount; - int m_downloadsToComplete; - QHash m_updatesInfoList; - - void clear(); - void computeUpdates(); - void cancelComputeUpdates(); - bool downloadUpdateXMLFiles(); - bool computeApplicableUpdates(); - - QList applicableUpdates(UpdatesInfo *updatesInfo); - void createUpdateObjects(const PackageSource &source, const QList &updateInfoList); - Resolution checkPriorityAndVersion(const PackageSource &source, const QVariantHash &data) const; - void slotDownloadDone(); - - QSet packageSources; - std::weak_ptr m_localPackageHub; -}; - - -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 UpdateFinder::Private::clear() -{ - qDeleteAll(updates); - updates.clear(); - - const QList values = m_updatesInfoList.values(); - foreach (const Data &data, values) - delete data.downloader; - - qDeleteAll(m_updatesInfoList.keys()); - m_updatesInfoList.clear(); - - downloadCompleteCount = 0; - m_downloadsToComplete = 0; -} - -/*! - \internal - - This method computes the updates that can be applied on the application by - studying the application's KDUpdater::PackagesInfo object and the UpdateXML files - from each of the update sources described in QInstaller::PackageSource. - - This function can take a long time to complete. The following signals are emitted - during the execution of this function - - The function creates 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 QInstaller::PackageSource object associated with - the application. Package information is extracted from the 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 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 - - clear(); - cancel = false; - - // First do some quick sanity checks on the packages info - std::shared_ptr packages = m_localPackageHub.lock(); - if (!packages) { - q->reportError(tr("Cannot access the package information of this application.")); - return; - } - - if (!packages->isValid()) { - q->reportError(packages->errorString()); - return; - } - - // Now do some quick sanity checks on the package sources. - if (packageSources.count() <= 0) { - q->reportError(tr("No package sources set for this application.")); - 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("%n update(s) found.", "", updates.count())); - q->reportDone(); -} - -/*! - \internal - - Cancels the computation of updates. - - \sa computeUpdates() -*/ -void UpdateFinder::Private::cancelComputeUpdates() -{ - cancel = true; -} - -/*! - \internal - - This function downloads Updates.xml from all the update sources except local files. - 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 UpdateFinder::Private::downloadUpdateXMLFiles() -{ - // create UpdatesInfo for each update source - foreach (const PackageSource &info, packageSources) { - const QUrl url = QString::fromLatin1("%1/Updates.xml").arg(info.url.toString()); - if (url.scheme() != QLatin1String("resource") && url.scheme() != QLatin1String("file")) { - // create FileDownloader (except for local files and resources) - FileDownloader *downloader = FileDownloaderFactory::instance().create(url.scheme(), q); - if (!downloader) - break; - - downloader->setUrl(url); - downloader->setAutoRemoveDownloadedFile(true); - connect(downloader, SIGNAL(downloadCanceled()), q, SLOT(slotDownloadDone())); - connect(downloader, SIGNAL(downloadCompleted()), q, SLOT(slotDownloadDone())); - connect(downloader, SIGNAL(downloadAborted(QString)), q, SLOT(slotDownloadDone())); - m_updatesInfoList.insert(new UpdatesInfo, Data(info, downloader)); - } else { - UpdatesInfo *updatesInfo = new UpdatesInfo; - updatesInfo->setFileName(QInstaller::pathFromUrl(url)); - m_updatesInfoList.insert(updatesInfo, Data(info)); - } - } - - // Trigger download of Updates.xml file - downloadCompleteCount = 0; - m_downloadsToComplete = 0; - foreach (const Data &data, m_updatesInfoList) { - if (data.downloader) { - m_downloadsToComplete++; - data.downloader->download(); - } - } - - // Wait until all downloaders have completed their downloads. - while (true) { - QCoreApplication::processEvents(); - if (cancel) - return false; - - if (downloadCompleteCount == m_downloadsToComplete) - break; - - q->reportProgress(computePercent(downloadCompleteCount, m_downloadsToComplete), - tr("Downloading Updates.xml from update sources.")); - } - - // Setup the update info objects with the files from download. - foreach (UpdatesInfo *updatesInfo, m_updatesInfoList.keys()) { - const Data data = m_updatesInfoList.value(updatesInfo); - if (data.downloader) { - if (!data.downloader->isDownloaded()) { - q->reportError(tr("Cannot download package source %1 from \"%2\".").arg(data - .downloader->url().fileName(), data.info.url.toString())); - } else { - updatesInfo->setFileName(data.downloader->downloadedFileName()); - } - } - } - - // Remove all invalid update info objects. - QMutableHashIterator it(m_updatesInfoList); - while (it.hasNext()) { - UpdatesInfo *info = it.next().key(); - if (info->isValid()) - continue; - - q->reportError(info->errorString()); - delete info; - it.remove(); - } - - if (m_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. Thereby figures out whether an update is applicable for - this application or not. -*/ -bool UpdateFinder::Private::computeApplicableUpdates() -{ - int i = 0; - foreach (UpdatesInfo *updatesInfo, m_updatesInfoList.keys()) { - // Fetch updates applicable to this application. - QList updates = applicableUpdates(updatesInfo); - if (!updates.count()) - continue; - - if (cancel) - return false; - const PackageSource updateSource = m_updatesInfoList.value(updatesInfo).info; - - // Create Update objects for updates that have a valid - // UpdateFile - createUpdateObjects(updateSource, updates); - if (cancel) - return false; - - // Report progress - q->reportProgress(computeProgressPercentage(51, 100, computePercent(i, - m_updatesInfoList.count())), tr("Computing applicable updates.")); - ++i; - } - - q->reportProgress(99, tr("Application updates computed.")); - return true; -} - -QList UpdateFinder::Private::applicableUpdates(UpdatesInfo *updatesInfo) -{ - const QList dummy; - if (!updatesInfo || updatesInfo->updateInfoCount() == 0) - return dummy; - - std::shared_ptr packages = m_localPackageHub.lock(); - if (!packages) - return dummy; - - // Check to see if the updates info contains updates for any application - if (updatesInfo->applicationName() != QLatin1String("{AnyApplication}")) { - // 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() - // If the application appName isn't one of the app names, then the updates are not applicable. - const QStringList apps = appName.split(QInstaller::commaRegExp(), QString::SkipEmptyParts); - if (apps.indexOf([&packages] { return packages->isValid() ? packages->applicationName() - : QCoreApplication::applicationName(); } ()) < 0) { - return dummy; - } - } - return updatesInfo->updatesInfo(); -} - -void UpdateFinder::Private::createUpdateObjects(const PackageSource &source, - const QList &updateInfoList) -{ - foreach (const UpdateInfo &info, updateInfoList) { - const Resolution value = checkPriorityAndVersion(source, info.data); - if (value == Resolution::KeepExisting) - continue; - - const QString name = info.data.value(QLatin1String("Name")).toString(); - if (value == Resolution::RemoveExisting) - delete updates.take(name); - - // Create and register the update - updates.insert(name, new Update(source, info)); - } -} - -/* - If a package of the same name exists, always use the one with the higher - version. If the new package has the same version but a higher - priority, use the new new package, otherwise keep the already existing package. -*/ -UpdateFinder::Private::Resolution UpdateFinder::Private::checkPriorityAndVersion( - const PackageSource &source, const QVariantHash &newPackage) const -{ - const QString name = newPackage.value(QLatin1String("Name")).toString(); - if (Update *existingPackage = updates.value(name)) { - // Bingo, package was previously found elsewhere. - - const int match = compareVersion(newPackage.value(QLatin1String("Version")).toString(), - existingPackage->data(QLatin1String("Version")).toString()); - - if (match > 0) { - // new package has higher version, use - qDebug().nospace() << "Remove Package 'Name: " << name << ", Version: " - << existingPackage->data(QLatin1String("Version")).toString() - << ", Source: " << QFileInfo(existingPackage->packageSource().url.toLocalFile()).fileName() - << "' found a package with higher version 'Name: " - << name << ", Version: " << newPackage.value(QLatin1String("Version")).toString() - << ", Source: " << QFileInfo(source.url.toLocalFile()).fileName() << "'"; - return Resolution::RemoveExisting; - } - - if ((match == 0) && (source.priority > existingPackage->packageSource().priority)) { - // new package version equals but priority is higher, use - qDebug().nospace() << "Remove Package 'Name: " << name << ", Priority: " - << existingPackage->packageSource().priority - << ", Source: " << QFileInfo(existingPackage->packageSource().url.toLocalFile()).fileName() - << "' found a package with higher priority 'Name: " - << name << ", Priority: " << source.priority - << ", Source: " << QFileInfo(source.url.toLocalFile()).fileName() << "'"; - return Resolution::RemoveExisting; - } - return Resolution::KeepExisting; // otherwise keep existing - } - return Resolution::AddPackage; -} - -// -// UpdateFinder -// - -/*! - Constructs an update finder. -*/ -UpdateFinder::UpdateFinder() - : Task(QLatin1String("UpdateFinder"), Stoppable), - d(new Private(this)) -{ -} - -/*! - Destructor -*/ -UpdateFinder::~UpdateFinder() -{ - delete d; -} - -/*! - Returns a list of KDUpdater::Update objects. -*/ -QList UpdateFinder::updates() const -{ - return d->updates.values(); -} - -void UpdateFinder::setLocalPackageHub(std::weak_ptr hub) -{ - d->m_localPackageHub = std::move(hub); -} - -/*! - Sets the package sources information to use when searching for applicable packages. -*/ -void UpdateFinder::setPackageSources(const QSet &sources) -{ - d->packageSources = sources; -} - -/*! - \internal - - Implemented from KDUpdater::Task::doRun(). -*/ -void UpdateFinder::doRun() -{ - d->computeUpdates(); -} - -/*! - \internal - - Implemented from KDUpdater::Task::doStop(). -*/ -bool 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 from KDUpdater::Task::doStop(). -*/ -bool UpdateFinder::doPause() -{ - // Not a pausable task - return false; -} - -/*! - \internal - - Implemented from KDUpdater::Task::doStop(). -*/ -bool UpdateFinder::doResume() -{ - // Not a pausable task, hence it is not resumable as well - return false; -} - -/*! - \internal -*/ -void UpdateFinder::Private::slotDownloadDone() -{ - ++downloadCompleteCount; - - int pc = computePercent(downloadCompleteCount, m_downloadsToComplete); - pc = computeProgressPercentage(0, 45, pc); - q->reportProgress( pc, tr("Downloading Updates.xml from update sources.") ); -} - - -/*! - \inmodule kdupdater - - This function compares two version strings \c v1 and \c v2 and returns - -1, 0 or +1 based on the following rule - - \list - \li Returns 0 if v1 == v2 - \li Returns -1 if v1 < v2 - \li Returns +1 if v1 > v2 - \endlist - - 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 (true) { - if (index == v1_comps.count() && index < v2_comps.count()) - return -1; - if (index < v1_comps.count() && index == v2_comps.count()) - return +1; - 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/src/libs/kdtools/kdupdaterupdatefinder.h b/src/libs/kdtools/kdupdaterupdatefinder.h deleted file mode 100644 index 5994bb685..000000000 --- a/src/libs/kdtools/kdupdaterupdatefinder.h +++ /dev/null @@ -1,76 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef KD_UPDATER_UPDATE_FINDER_H -#define KD_UPDATER_UPDATE_FINDER_H - -#include "kdupdatertask.h" -#include "packagesource.h" - -#include - -namespace KDUpdater { - -class LocalPackageHub; -class Update; - -class KDTOOLS_EXPORT UpdateFinder : public Task -{ - Q_OBJECT - class Private; - -public: - UpdateFinder(); - ~UpdateFinder(); - - QList updates() const; - - void setLocalPackageHub(std::weak_ptr hub); - void setPackageSources(const QSet &sources); - -private: - void doRun(); - bool doStop(); - bool doPause(); - bool doResume(); - -private: - Private *d; - Q_PRIVATE_SLOT(d, void slotDownloadDone()) -}; - -} // namespace KDUpdater - -#endif // KD_UPDATER_UPDATE_FINDER_H diff --git a/src/libs/kdtools/kdupdaterupdateoperation.cpp b/src/libs/kdtools/kdupdaterupdateoperation.cpp deleted file mode 100644 index f4505d6da..000000000 --- a/src/libs/kdtools/kdupdaterupdateoperation.cpp +++ /dev/null @@ -1,528 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "kdupdaterupdateoperation.h" - -#include "constants.h" -#include "fileutils.h" -#include "packagemanagercore.h" - -#include -#include -#include -#include -#include - -using namespace KDUpdater; - -/*! - \inmodule kdupdater - \class KDUpdater::UpdateOperation - \brief The UpdateOperation class is an abstract base class for update operations. - - The KDUpdater::UpdateOperation is an abstract class that specifies an interface for - update operations. Concrete implementations of this class must perform a single update - operation, such as copy, move, or delete. - - \note Two separate threads cannot be using a single instance of KDUpdater::UpdateOperation - at the same time. -*/ - -/*! - \enum UpdateOperation::Error - This enum code specifies error codes related to operation arguments and - operation runtime failures. - - \value NoError - No error occurred. - \value InvalidArguments - Number of arguments does not match or an invalid argument was set. - \value UserDefinedError - An error occurred during operation run. Use UpdateOperation::errorString() - to get the human-readable description of the error that occurred. -*/ - -/* - \internal - Returns a filename for a temporary file based on \a templateName. -*/ -static QString backupFileName(const QString &templateName) -{ - const QFileInfo templ(templateName); - QTemporaryFile file( QDir::temp().absoluteFilePath(templ.fileName())); - file.open(); - const QString name = file.fileName(); - file.close(); - file.remove(); - return name; -} - -/*! - \internal -*/ -UpdateOperation::UpdateOperation(QInstaller::PackageManagerCore *core) - : m_error(0) - , m_core(core) -{ - // Store the value for compatibility reasons. - m_values[QLatin1String("installer")] = QVariant::fromValue(core); -} - -/*! - \internal -*/ -UpdateOperation::~UpdateOperation() -{ - if (auto *core = packageManager()) - core->addFilesForDelayedDeletion(filesForDelayedDeletion()); -} - -/*! - Returns the update operation name. - - \sa setName() -*/ -QString UpdateOperation::name() const -{ - return m_name; -} - -/*! - Returns a command line string that describes the update operation. The returned string will be - of the form: - - \c{ ....} -*/ -QString UpdateOperation::operationCommand() const -{ - QString argsStr = m_arguments.join(QLatin1String( " " )); - return QString::fromLatin1( "%1 %2" ).arg(m_name, argsStr); -} - -/*! - Returns \c true if a value called \a name exists, otherwise returns \c false. -*/ -bool UpdateOperation::hasValue(const QString &name) const -{ - return m_values.contains(name); -} - -/*! - Clears the value of \a name and removes it. -*/ -void UpdateOperation::clearValue(const QString &name) -{ - m_values.remove(name); -} - -/*! - Returns the value of \a name. If the value does not exist, returns an empty QVariant. -*/ -QVariant UpdateOperation::value(const QString &name) const -{ - return m_values.value(name); -} - -/*! - Sets the value of \a name to \a value. -*/ -void UpdateOperation::setValue(const QString &name, const QVariant &value) -{ - m_values[name] = value; -} - -/*! - Sets the name of the operation to \a name. Subclasses will have to provide a unique name to - describe the operation. -*/ -void UpdateOperation::setName(const QString &name) -{ - m_name = name; -} - -/*! - Sets the arguments for the update operation to \a args. -*/ -void UpdateOperation::setArguments(const QStringList &args) -{ - m_arguments = args; -} - -/*! - Returns the arguments of the update operation. -*/ -QStringList UpdateOperation::arguments() const -{ - return m_arguments; -} - -bool UpdateOperation::checkArgumentCount(int minArgCount, int maxArgCount, - const QString &argDescription) -{ - const int argCount = arguments().count(); - if (argCount < minArgCount || argCount > maxArgCount) { - setError(InvalidArguments); - QString countRange; - if (minArgCount == maxArgCount) - countRange = tr("exactly %1").arg(minArgCount); - else if (maxArgCount == INT_MAX) - countRange = tr("at least %1").arg(minArgCount); - else if (minArgCount == 0) - countRange = tr("not more than %1").arg(maxArgCount); - else if (minArgCount == maxArgCount - 1) - countRange = tr("%1 or %2").arg(minArgCount).arg(maxArgCount); - else - countRange = tr("%1 to %2").arg(minArgCount).arg(maxArgCount); - - if (argDescription.isEmpty()) - setErrorString(tr("Invalid arguments in %1: %n arguments given, " - "%2 arguments expected.", 0, argCount) - .arg(name(), countRange)); - else - setErrorString(tr("Invalid arguments in %1: %n arguments given, " - "%2 arguments expected in the form: %3.", 0, argCount) - .arg(name(), countRange, argDescription)); - return false; - } - return true; -} - -bool UpdateOperation::checkArgumentCount(int argCount) -{ - return checkArgumentCount(argCount, argCount); -} - -struct StartsWith -{ - StartsWith(const QString &searchTerm) - : m_searchTerm(searchTerm) {} - - bool operator()(const QString &searchString) - { - return searchString.startsWith(m_searchTerm); - } - - QString m_searchTerm; -}; - -/*! - Searches the arguments for the key specified by \a key. If it can find the - key, it returns the value set for it. Otherwise, it returns \a defaultValue. - Arguments are specified in the following form: \c{key=value}. -*/ -QString UpdateOperation::argumentKeyValue(const QString &key, const QString &defaultValue) const -{ - const QString keySeparater(key + QLatin1String("=")); - const QStringList tArguments(arguments()); - QStringList::const_iterator it = std::find_if(tArguments.begin(), tArguments.end(), - StartsWith(keySeparater)); - if (it == tArguments.end()) - return defaultValue; - - const QString value = it->mid(keySeparater.size()); - - it = std::find_if(++it, tArguments.end(), StartsWith(keySeparater)); - if (it != tArguments.end()) { - qWarning().nospace() << "There are multiple keys in the arguments calling " << name() << ". " - << "Only the first found " << key << " is used: " - << arguments().join(QLatin1String("; ")); - } - return value; -} - -/*! - Returns a human-readable description of the last error that occurred. -*/ -QString UpdateOperation::errorString() const -{ - return m_errorString; -} - -/*! - Returns the error that was found during the processing of the operation. If no - error was found, returns NoError. Subclasses can set more detailed error codes (optional). - - \note To check if an operation was successful, use the return value of performOperation(), - undoOperation(), or testOperation(). -*/ -int UpdateOperation::error() const -{ - return m_error; -} - -/*! - Sets the human-readable description of the last error that occurred to \a str. -*/ -void UpdateOperation::setErrorString(const QString &str) -{ - m_errorString = str; -} - -/*! - Sets the error condition to be \a error. The human-readable message is set to \a errorString. - - \sa UpdateOperation::error() - \sa UpdateOperation::errorString() -*/ -void UpdateOperation::setError(int error, const QString &errorString) -{ - m_error = error; - if (!errorString.isNull()) - m_errorString = errorString; -} - -/*! - Clears the previously set arguments. -*/ -void UpdateOperation::clear() -{ - m_arguments.clear(); -} - -/*! - Returns the list of files that are scheduled for later deletion. -*/ -QStringList UpdateOperation::filesForDelayedDeletion() const -{ - return m_delayedDeletionFiles; -} - -/*! - Returns the package manager core this operation belongs to. -*/ -QInstaller::PackageManagerCore *UpdateOperation::packageManager() const -{ - return m_core; -} - -/*! - Registers a list of \a files to be deleted later once the application was restarted and the - file or files are not used anymore. -*/ -void UpdateOperation::registerForDelayedDeletion(const QStringList &files) -{ - m_delayedDeletionFiles << files; -} - -/*! - Tries to delete \a file. If \a file cannot be deleted, it is registered for delayed deletion. - - If a backup copy of the file cannot be created, returns \c false and displays the error - message specified by \a errorString. -*/ -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 = tr("Renaming file \"%1\" to \"%2\" failed: %3").arg( - QDir::toNativeSeparators(file), QDir::toNativeSeparators(backup), f.errorString()); - return false; - } - registerForDelayedDeletion(QStringList(backup)); - return true; -} - -/*! - \fn virtual void KDUpdater::UpdateOperation::backup() = 0; - - Subclasses must implement this function to back up any data before performing the action. -*/ - -/*! - \fn virtual bool KDUpdater::UpdateOperation::performOperation() = 0; - - Subclasses must implement this function to perform the update operation. - - Returns \c true if the operation is successful. -*/ - -/*! - \fn virtual bool KDUpdater::UpdateOperation::undoOperation() = 0; - - Subclasses must implement this function to perform the undo of the update operation. - - Returns \c true if the operation is successful. -*/ - -/*! - \fn virtual bool KDUpdater::UpdateOperation::testOperation() = 0; - - Subclasses must implement this function to perform the test operation. - - Returns \c true if the operation is successful. -*/ - -/*! - Saves operation arguments and values as an XML document and returns the - document. You can override this method to store your - own extra-data. Extra-data can be any data that you need to store to perform or undo the - operation. The default implementation is taking care of arguments and values set via - UpdateOperation::setValue(). -*/ -QDomDocument UpdateOperation::toXml() const -{ - QDomDocument doc; - QDomElement root = doc.createElement(QLatin1String("operation")); - doc.appendChild(root); - - QDomElement args = doc.createElement(QLatin1String("arguments")); - const QString target = m_core ? m_core->value(QInstaller::scTargetDir) : QString(); - Q_FOREACH (const QString &s, arguments()) { - QDomElement arg = doc.createElement(QLatin1String("argument")); - arg.appendChild(doc.createTextNode(QInstaller::replacePath(s, target, - QLatin1String(QInstaller::scRelocatable)))); - args.appendChild(arg); - } - root.appendChild(args); - if (m_values.isEmpty()) - return doc; - - // append all values set with setValue - QDomElement values = doc.createElement(QLatin1String("values")); - for (QVariantMap::const_iterator it = m_values.constBegin(); it != m_values.constEnd(); ++it) { - // the installer can't be put into XML, ignore - if (it.key() == QLatin1String("installer")) - continue; - - QDomElement value = doc.createElement(QLatin1String("value")); - QVariant variant = it.value(); - value.setAttribute(QLatin1String("name"), it.key()); - value.setAttribute(QLatin1String("type"), QLatin1String(variant.typeName())); - - if (variant.type() != QVariant::List && variant.type() != QVariant::StringList - && variant.canConvert(QVariant::String)) { - // it can convert to string? great! - value.appendChild(doc.createTextNode(QInstaller::replacePath(variant.toString(), - target, QLatin1String(QInstaller::scRelocatable)))); - } else { - // no? then we have to go the hard way... - if (variant.type() == QVariant::StringList) { - QStringList list = variant.toStringList(); - for (int i = 0; i < list.count(); ++i) { - list[i] = QInstaller::replacePath(list.at(i), target, - QLatin1String(QInstaller::scRelocatable)); - } - variant = QVariant::fromValue(list); - } - 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 operation arguments and values from the XML document \a doc. Returns \c true on - success, otherwise \c false. \note: Clears all previously set values and arguments. -*/ -bool UpdateOperation::fromXml(const QDomDocument &doc) -{ - QString target = QCoreApplication::applicationDirPath(); - QInstaller::isInBundle(target, &target); // Does not change target on non OSX platforms. - - 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 << QInstaller::replacePath(e.text(), QLatin1String(QInstaller::scRelocatable), - target); - } - } - setArguments(args); - - m_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; - if (t == QVariant::StringList) { - QStringList list = var.toStringList(); - for (int i = 0; i < list.count(); ++i) { - list[i] = QInstaller::replacePath(list.at(i), - QLatin1String(QInstaller::scRelocatable), target); - } - var = QVariant::fromValue(list); - } - } - - m_values[name] = var; - } - - return true; -} - -/*! - \overload - - Restores operation arguments and values from the XML file at path \a xml. Returns \c true on - success, otherwise \c false. -*/ -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/src/libs/kdtools/kdupdaterupdateoperation.h b/src/libs/kdtools/kdupdaterupdateoperation.h deleted file mode 100644 index 76b6fc6eb..000000000 --- a/src/libs/kdtools/kdupdaterupdateoperation.h +++ /dev/null @@ -1,113 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef KD_UPDATER_UPDATE_OPERATION_H -#define KD_UPDATER_UPDATE_OPERATION_H - -#include "kdupdater.h" - -#include -#include -#include -#include - -namespace QInstaller { -class PackageManagerCore; -} - -namespace KDUpdater { - -class KDTOOLS_EXPORT UpdateOperation -{ - Q_DECLARE_TR_FUNCTIONS(UpdateOperation) - -public: - enum Error { - NoError = 0, - InvalidArguments = 1, - UserDefinedError = 128 - }; - - explicit UpdateOperation(QInstaller::PackageManagerCore *core); - 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); - QStringList arguments() const; - QString argumentKeyValue(const QString & key, const QString &defaultValue = QString()) const; - void clear(); - QString errorString() const; - int error() const; - QStringList filesForDelayedDeletion() const; - - QInstaller::PackageManagerCore *packageManager() const; - - virtual void backup() = 0; - virtual bool performOperation() = 0; - virtual bool undoOperation() = 0; - virtual bool testOperation() = 0; - - virtual QDomDocument toXml() const; - virtual bool fromXml(const QString &xml); - virtual bool fromXml(const QDomDocument &doc); - -protected: - void setName(const QString &name); - 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); - bool checkArgumentCount(int minArgCount, int maxArgCount, const QString &argDescription = QString()); - bool checkArgumentCount(int argCount); - -private: - QString m_name; - QStringList m_arguments; - QString m_errorString; - int m_error; - QVariantMap m_values; - QStringList m_delayedDeletionFiles; - QInstaller::PackageManagerCore *m_core; -}; - -} // namespace KDUpdater - -#endif // KD_UPDATER_UPDATE_OPERATION_H diff --git a/src/libs/kdtools/kdupdaterupdateoperationfactory.cpp b/src/libs/kdtools/kdupdaterupdateoperationfactory.cpp deleted file mode 100644 index a74658cc2..000000000 --- a/src/libs/kdtools/kdupdaterupdateoperationfactory.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "kdupdaterupdateoperationfactory.h" - -#include "kdupdaterupdateoperations.h" - -using namespace KDUpdater; - -/*! - \inmodule kdupdater - \class KDUpdater::UpdateOperationFactory - \brief The UpdateOperationFactory class is used to create update operations based on their name. - - This class acts as a factory for \c 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 instance() method. - - The following operations are registered by default: - \list - \li Copy operation - \li Move operation - \li Delete operation - \li Mkdir operation - \li Rmdir operation - \li AppendFile operation - \li PrependFile operation - \endlist -*/ - -/*! - \obsolete - \fn void KDUpdater::UpdateOperationFactory::registerUpdateOperation(const QString &name) - - Registers a new update operation with the factory based on \a name. When create() is called - with that \a name, the update operation is constructed using its default constructor. - - Deprecated. Use registerProduct() instead. -*/ - -/*! - Returns the UpdateOperationFactory instance. The instance is created if needed. -*/ -UpdateOperationFactory &UpdateOperationFactory::instance() -{ - static UpdateOperationFactory theFactory; - return theFactory; -} - -/*! - Constructor -*/ -UpdateOperationFactory::UpdateOperationFactory() -{ - // Register the default update operation set - registerUpdateOperation(QLatin1String("Copy")); - registerUpdateOperation(QLatin1String("Move")); - registerUpdateOperation(QLatin1String("Delete")); - registerUpdateOperation(QLatin1String("Mkdir")); - registerUpdateOperation(QLatin1String("Rmdir")); - registerUpdateOperation(QLatin1String("AppendFile")); - registerUpdateOperation(QLatin1String("PrependFile")); -} diff --git a/src/libs/kdtools/kdupdaterupdateoperationfactory.h b/src/libs/kdtools/kdupdaterupdateoperationfactory.h deleted file mode 100644 index 03a2ba047..000000000 --- a/src/libs/kdtools/kdupdaterupdateoperationfactory.h +++ /dev/null @@ -1,70 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef KD_UPDATER_UPDATE_OPERATION_FACTORY_H -#define KD_UPDATER_UPDATE_OPERATION_FACTORY_H - -#include "kdgenericfactory.h" - -#include "kdupdater.h" - -namespace QInstaller { -class PackageManagerCore; -} - -namespace KDUpdater { - -class UpdateOperation; - -class KDTOOLS_EXPORT UpdateOperationFactory : public KDGenericFactory -{ - Q_DISABLE_COPY(UpdateOperationFactory) - -public: - static UpdateOperationFactory &instance(); - - template - void registerUpdateOperation(const QString &name) - { - registerProduct(name); - } - -private: - UpdateOperationFactory(); -}; - -} // namespace KDUpdater - -#endif // KD_UPDATER_UPDATE_OPERATION_FACTORY_H diff --git a/src/libs/kdtools/kdupdaterupdateoperations.cpp b/src/libs/kdtools/kdupdaterupdateoperations.cpp deleted file mode 100644 index cc5c5ba8d..000000000 --- a/src/libs/kdtools/kdupdaterupdateoperations.cpp +++ /dev/null @@ -1,786 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "kdupdaterupdateoperations.h" -#include "errors.h" -#include "fileutils.h" - -#include -#include -#include -#include -#include - -#include - -using namespace KDUpdater; - -static QString errnoToQString(int error) -{ -#if defined(Q_OS_WIN) && !defined(Q_CC_MINGW) - char msg[128]; - if (strerror_s(msg, sizeof msg, error) != 0) - return QString::fromLocal8Bit(msg); - return QString(); -#else - return QString::fromLocal8Bit(strerror(error)); -#endif -} - -static bool removeDirectory(const QString &path, QString *errorString, bool force) -{ - Q_ASSERT(errorString); - - QDir dir = path; - const QFileInfoList entries = dir.entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries | QDir::Hidden); - foreach (const QFileInfo &entry, entries) { - if (entry.isDir() && (!entry.isSymLink())) - removeDirectory(entry.filePath(), errorString, force); - else if (force && (!QFile(entry.filePath()).remove())) - return false; - } - - // even remove some hidden, OS-created files in there - QInstaller::removeSystemGeneratedFiles(path); - - errno = 0; - const bool success = dir.rmdir(path); - if (errno) - *errorString = errnoToQString(errno); - return success; -} - -/* - * \internal - * Returns a filename for a temporary file based on \a templateName - */ -static QString backupFileName(const QString &templateName) -{ - QTemporaryFile file(templateName); - file.open(); - const QString name = file.fileName(); - file.close(); - file.remove(); - return name; -} - -//////////////////////////////////////////////////////////////////////////// -// KDUpdater::CopyOperation -//////////////////////////////////////////////////////////////////////////// - -CopyOperation::CopyOperation(QInstaller::PackageManagerCore *core) - : UpdateOperation(core) -{ - setName(QLatin1String("Copy")); -} - -CopyOperation::~CopyOperation() -{ - deleteFileNowOrLater(value(QLatin1String("backupOfExistingDestination")).toString()); -} - -QString CopyOperation::sourcePath() -{ - return arguments().first(); -} - -QString CopyOperation::destinationPath() -{ - QString destination = arguments().last(); - - // if the target is a directory use the source filename to complete the destination path - if (QFileInfo(destination).isDir()) - destination = QDir(destination).filePath(QFileInfo(sourcePath()).fileName()); - return destination; -} - - -void CopyOperation::backup() -{ - QString destination = destinationPath(); - - if (!QFile::exists(destination)) { - clearValue(QLatin1String("backupOfExistingDestination")); - return; - } - - setValue(QLatin1String("backupOfExistingDestination"), backupFileName(destination)); - - // race condition: The backup file could get created by another process right now. But this is the same - // in QFile::copy... - if (!QFile::rename(destination, value(QLatin1String("backupOfExistingDestination")).toString())) - setError(UserDefinedError, tr("Cannot backup file \"%1\".").arg(QDir::toNativeSeparators(destination))); -} - -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 - if (!checkArgumentCount(2)) - return false; - - QString source = sourcePath(); - QString destination = destinationPath(); - - QFile sourceFile(source); - if (!sourceFile.exists()) { - setError(UserDefinedError); - setErrorString(tr("Cannot copy a non-existent file: %1").arg(QDir::toNativeSeparators(source))); - return false; - } - // If destination file exists, we cannot use QFile::copy() because it does not overwrite an existing - // file. So we remove the destination file. - QFile destinationFile(destination); - if (destinationFile.exists()) { - if (!destinationFile.remove()) { - setError(UserDefinedError); - setErrorString(tr("Cannot remove file \"%1\": %2").arg( - QDir::toNativeSeparators(destination), destinationFile.errorString())); - return false; - } - } - - const bool copied = sourceFile.copy(destination); - if (!copied) { - setError(UserDefinedError); - setErrorString(tr("Cannot copy file \"%1\" to \"%2\": %3").arg( - QDir::toNativeSeparators(source), QDir::toNativeSeparators(destination), - sourceFile.errorString())); - } - return copied; -} - -bool CopyOperation::undoOperation() -{ - QString source = sourcePath(); - QString destination = destinationPath(); - - // if the target is a directory use the source filename to complete the destination path - if (QFileInfo(destination).isDir()) - destination = destination + QDir::separator() + QFileInfo(source).fileName(); - - QFile destFile(destination); - // first remove the dest - if (destFile.exists() && !destFile.remove()) { - setError(UserDefinedError, tr("Cannot delete file \"%1\": %2").arg( - QDir::toNativeSeparators(destination), destFile.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 backupFile(value(QLatin1String("backupOfExistingDestination")).toString()); - // otherwise we have to copy the backup back: - const bool success = backupFile.rename(destination); - if (!success) - setError(UserDefinedError, tr("Cannot restore backup file into \"%1\": %2").arg( - QDir::toNativeSeparators(destination), backupFile.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(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; -} - - -//////////////////////////////////////////////////////////////////////////// -// KDUpdater::MoveOperation -//////////////////////////////////////////////////////////////////////////// - -MoveOperation::MoveOperation(QInstaller::PackageManagerCore *core) - : UpdateOperation(core) -{ - 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... - if (!QFile::rename(dest, value(QLatin1String("backupOfExistingDestination")).toString())) - setError(UserDefinedError, tr("Cannot backup file \"%1\".").arg(QDir::toNativeSeparators(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 - if (!checkArgumentCount(2)) - return false; - - const QStringList args = arguments(); - const QString dest = args.at(1); - // 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("Cannot remove file \"%1\": %2").arg( - QDir::toNativeSeparators(dest), file.errorString())); - return false; - } - } - - // Copy source to destination. - QFile file(args.at(0)); - if (!file.copy(dest)) { - setError(UserDefinedError); - setErrorString(tr("Cannot copy file \"%1\" to \"%2\": %3").arg(QDir::toNativeSeparators(file.fileName()), - QDir::toNativeSeparators(dest), file.errorString())); - return false; - } - return deleteFileNowOrLater(file.fileName()); -} - -bool MoveOperation::undoOperation() -{ - const QStringList args = arguments(); - const QString dest = args.last(); - // first: copy back the destination to source - QFile destF(dest); - if (!destF.copy(args.first())) { - setError(UserDefinedError, tr("Cannot copy file \"%1\" to \"%2\": %3").arg( - QDir::toNativeSeparators(dest), QDir::toNativeSeparators(args.first()), destF.errorString())); - return false; - } - - // second: delete the move destination - if (!deleteFileNowOrLater(dest)) { - setError(UserDefinedError, tr("Cannot remove file \"%1\".").arg(QDir::toNativeSeparators(dest))); - 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( - QDir::toNativeSeparators(dest), backupF.errorString())); - - return success; -} - -bool MoveOperation::testOperation() -{ - // TODO - return true; -} - - -//////////////////////////////////////////////////////////////////////////// -// KDUpdater::DeleteOperation -//////////////////////////////////////////////////////////////////////////// - -DeleteOperation::DeleteOperation(QInstaller::PackageManagerCore *core) - : UpdateOperation(core) -{ - 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); - if (!file.copy(value(QLatin1String("backupOfExistingFile")).toString())) - setError(UserDefinedError, tr("Cannot create backup of file \"%1\": %2").arg( - QDir::toNativeSeparators(fileName), file.errorString())); -} - -bool DeleteOperation::performOperation() -{ - // Requires only one parameter. That is the name of the file to remove. - if (!checkArgumentCount(1)) - return false; - - return deleteFileNowOrLater(arguments().at(0)); -} - -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( - QDir::toNativeSeparators(fileName), backupF.errorString())); - return success; -} - -bool DeleteOperation::testOperation() -{ - // TODO - return true; -} - -/*! - \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(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(QInstaller::PackageManagerCore *core) - : UpdateOperation(core) -{ - setName(QLatin1String("Mkdir")); -} - -void MkdirOperation::backup() -{ - QString path = arguments().first(); - path.replace(QLatin1Char('\\'), QLatin1Char('/')); - - 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(QLatin1Char('/'), 0, ++end); - createdDir = QDir(p); - if (!createdDir.exists()) - break; - 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 path which should be created - if (!checkArgumentCount(1)) - return false; - - const QString dirName = arguments().at(0); - const bool created = QDir::root().mkpath(dirName); - if (!created) { - setError(UserDefinedError); - setErrorString(tr("Cannot create directory \"%1\": %2").arg( - QDir::toNativeSeparators(dirName), tr("Unknown error."))); - } - return created; -} - -bool MkdirOperation::undoOperation() -{ - Q_ASSERT(arguments().count() == 1); - - QString createdDirValue = value(QLatin1String("createddir")).toString(); - if (createdDirValue.isEmpty()) - createdDirValue = arguments().first(); - QDir createdDir = QDir(createdDirValue); - const bool forceremoval = QVariant(value(QLatin1String("forceremoval"))).toBool(); - - // Since refactoring we know the mkdir operation which is creating the target path. If we do a full - // uninstall prevent removing the full path including target, instead remove the target only. (QTIFW-46) - if (hasValue(QLatin1String("uninstall-only")) && value(QLatin1String("uninstall-only")).toBool()) - createdDir = QDir(arguments().first()); - - if (createdDir == QDir::root()) - return true; - - if (!createdDir.exists()) - return true; - - QString errorString; - - const bool result = removeDirectory(createdDir.path(), &errorString, forceremoval); - - if (!result) { - if (errorString.isEmpty()) - setError(UserDefinedError, tr("Cannot remove directory \"%1\": %2").arg( - QDir::toNativeSeparators(createdDir.path()), errorString)); - else - setError(UserDefinedError, tr("Cannot remove directory \"%1\": %2").arg( - QDir::toNativeSeparators(createdDir.path()), errnoToQString(errno))); - } - return result; -} - -bool KDUpdater::MkdirOperation::testOperation() -{ - // TODO - return true; -} - - -//////////////////////////////////////////////////////////////////////////// -// KDUpdater::RmdirOperation -//////////////////////////////////////////////////////////////////////////// - -RmdirOperation::RmdirOperation(QInstaller::PackageManagerCore *core) - : UpdateOperation(core) -{ - setName(QLatin1String("Rmdir")); - setValue(QLatin1String("removed"), false); -} - -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. - if (!checkArgumentCount(1)) - return false; - - const QString firstArg = arguments().at(0); - QDir dir(firstArg); - if (!dir.exists()) { - setError(UserDefinedError); - setErrorString(tr("Cannot remove directory \"%1\": %2").arg( - QDir::toNativeSeparators(firstArg), tr("The directory does not exist."))); - return false; - } - - errno = 0; - const bool removed = dir.rmdir(firstArg); - setValue(QLatin1String("removed"), removed); - if (!removed) { - setError(UserDefinedError); - setErrorString(tr("Cannot remove directory \"%1\": %2").arg( - QDir::toNativeSeparators(firstArg), errnoToQString(errno))); - } - return removed; -} - -bool RmdirOperation::undoOperation() -{ - if (!value(QLatin1String("removed")).toBool()) - return true; - - errno = 0; - const QFileInfo fi(arguments().first()); - const bool success = fi.dir().mkdir(fi.fileName()); - if( !success) - setError(UserDefinedError, tr("Cannot recreate directory \"%1\": %2").arg( - QDir::toNativeSeparators(fi.fileName()), errnoToQString(errno))); - - return success; -} - -bool RmdirOperation::testOperation() -{ - // TODO - return true; -} - - -//////////////////////////////////////////////////////////////////////////// -// KDUpdater::AppendFileOperation -//////////////////////////////////////////////////////////////////////////// - -AppendFileOperation::AppendFileOperation(QInstaller::PackageManagerCore *core) - : UpdateOperation(core) -{ - setName(QLatin1String("AppendFile")); -} - -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( - QDir::toNativeSeparators(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. - if (!checkArgumentCount(2)) - return false; - - const QStringList args = this->arguments(); - const QString fName = args.at(0); - 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 - bool error = false; - const QString newName = backupFileName(fName); - - if (!QFile::rename(fName, newName)) - error = true; - - if (!error && !QFile::copy(newName, fName)) { - error = true; - QFile::rename(newName, fName); - } - - if (!error && !file.open(QFile::Append)) { - error = true; - deleteFileNowOrLater(newName); - } - - if (error) { - setError(UserDefinedError); - setErrorString(tr("Cannot open file \"%1\" for writing: %2").arg( - QDir::toNativeSeparators(file.fileName()), file.errorString())); - return false; - } - deleteFileNowOrLater(newName); - } - - QTextStream ts(&file); - ts << args.at(1); - 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( - QDir::toNativeSeparators(filename))); - return false; - } - - const bool removed = deleteFileNowOrLater(filename); - if (!removed) { - setError(UserDefinedError, tr("Cannot restore backup file for \"%1\".").arg( - QDir::toNativeSeparators(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("Cannot restore backup file for \"%1\": %2").arg( - QDir::toNativeSeparators(filename), backupFile.errorString())); - return success; -} - -bool AppendFileOperation::testOperation() -{ - // TODO - return true; -} - - -//////////////////////////////////////////////////////////////////////////// -// KDUpdater::PrependFileOperation -//////////////////////////////////////////////////////////////////////////// - -PrependFileOperation::PrependFileOperation(QInstaller::PackageManagerCore *core) - : UpdateOperation(core) -{ - setName(QLatin1String("PrependFile")); -} - -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( - QDir::toNativeSeparators(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. - if (!checkArgumentCount(2)) - return false; - - const QStringList args = this->arguments(); - const QString fName = args.at(0); - // Load the file first. - QFile file(fName); - if (!file.open(QFile::ReadOnly)) { - setError(UserDefinedError); - setErrorString(tr("Cannot open file \"%1\" for reading: %2").arg( - QDir::toNativeSeparators(file.fileName()), file.errorString())); - return false; - } - - // TODO: fix this, use a text stream - QString fContents(QLatin1String(file.readAll())); - file.close(); - - // Prepend text to the file text - fContents = args.at(1) + 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("Cannot open file \"%1\" for writing: %2").arg( - QDir::toNativeSeparators(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(QDir::toNativeSeparators(filename))); - return false; - } - - if (!deleteFileNowOrLater(filename)) { - setError(UserDefinedError, - tr("Cannot restore backup file for \"%1\".").arg(QDir::toNativeSeparators(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( - QDir::toNativeSeparators(filename), backupF.errorString())); - - return success; -} - -bool PrependFileOperation::testOperation() -{ - // TODO - return true; -} diff --git a/src/libs/kdtools/kdupdaterupdateoperations.h b/src/libs/kdtools/kdupdaterupdateoperations.h deleted file mode 100644 index 5114196a9..000000000 --- a/src/libs/kdtools/kdupdaterupdateoperations.h +++ /dev/null @@ -1,131 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef KD_UPDATER_UPDATE_OPERATIONS_H -#define KD_UPDATER_UPDATE_OPERATIONS_H - -#include "kdupdaterupdateoperation.h" - -namespace KDUpdater { - -class KDTOOLS_EXPORT CopyOperation : public UpdateOperation -{ -public: - explicit CopyOperation(QInstaller::PackageManagerCore *core = 0); - ~CopyOperation(); - - void backup(); - bool performOperation(); - bool undoOperation(); - bool testOperation(); - - QDomDocument toXml() const; -private: - QString sourcePath(); - QString destinationPath(); -}; - -class KDTOOLS_EXPORT MoveOperation : public UpdateOperation -{ -public: - explicit MoveOperation(QInstaller::PackageManagerCore *core = 0); - ~MoveOperation(); - - void backup(); - bool performOperation(); - bool undoOperation(); - bool testOperation(); -}; - -class KDTOOLS_EXPORT DeleteOperation : public UpdateOperation -{ -public: - explicit DeleteOperation(QInstaller::PackageManagerCore *core = 0); - ~DeleteOperation(); - - void backup(); - bool performOperation(); - bool undoOperation(); - bool testOperation(); - - QDomDocument toXml() const; -}; - -class KDTOOLS_EXPORT MkdirOperation : public UpdateOperation -{ -public: - explicit MkdirOperation(QInstaller::PackageManagerCore *core = 0); - - void backup(); - bool performOperation(); - bool undoOperation(); - bool testOperation(); -}; - -class KDTOOLS_EXPORT RmdirOperation : public UpdateOperation -{ -public: - RmdirOperation(QInstaller::PackageManagerCore *core = 0); - - void backup(); - bool performOperation(); - bool undoOperation(); - bool testOperation(); -}; - -class KDTOOLS_EXPORT AppendFileOperation : public UpdateOperation -{ -public: - explicit AppendFileOperation(QInstaller::PackageManagerCore *core = 0); - - void backup(); - bool performOperation(); - bool undoOperation(); - bool testOperation(); -}; - -class KDTOOLS_EXPORT PrependFileOperation : public UpdateOperation -{ -public: - explicit PrependFileOperation(QInstaller::PackageManagerCore *core = 0); - - void backup(); - bool performOperation(); - bool undoOperation(); - bool testOperation(); -}; - -} // namespace KDUpdater - -#endif // KD_UPDATER_UPDATE_OPERATIONS_H diff --git a/src/libs/kdtools/kdupdaterupdatesinfo.cpp b/src/libs/kdtools/kdupdaterupdatesinfo.cpp deleted file mode 100644 index 48003279b..000000000 --- a/src/libs/kdtools/kdupdaterupdatesinfo.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "kdupdaterupdatesinfo_p.h" - -#include -#include -#include -#include - -using namespace KDUpdater; - -UpdatesInfoData::UpdatesInfoData() - : error(UpdatesInfo::NotYetReadError) -{ -} - -UpdatesInfoData::~UpdatesInfoData() -{ -} - -void UpdatesInfoData::setInvalidContentError(const QString &detail) -{ - error = UpdatesInfo::InvalidContentError; - errorMessage = tr("Updates.xml contains invalid content: %1").arg(detail); -} - -void UpdatesInfoData::parseFile(const QString &updateXmlFile) -{ - QFile file(updateXmlFile); - if (!file.open(QFile::ReadOnly)) { - error = UpdatesInfo::CouldNotReadUpdateInfoFileError; - errorMessage = tr("Cannot read \"%1\"").arg(updateXmlFile); - return; - } - - QDomDocument doc; - QString parseErrorMessage; - int parseErrorLine, 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++) { - const QDomElement childE = childNodes.at(i).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("PackageUpdate")) { - if (!parsePackageUpdateElement(childE)) - return; //error handled in subroutine - } - } - - if (applicationName.isEmpty()) { - setInvalidContentError(tr("ApplicationName element is missing.")); - return; - } - - if (applicationVersion.isEmpty()) { - setInvalidContentError(tr("ApplicationVersion element is missing.")); - return; - } - - errorMessage.clear(); - error = UpdatesInfo::NoError; -} - -bool UpdatesInfoData::parsePackageUpdateElement(const QDomElement &updateE) -{ - if (updateE.isNull()) - return false; - - UpdateInfo info; - for (int i = 0; i < updateE.childNodes().count(); i++) { - QDomElement childE = updateE.childNodes().at(i).toElement(); - if (childE.isNull()) - continue; - - if (childE.tagName() == QLatin1String("ReleaseNotes")) { - info.data[childE.tagName()] = QUrl(childE.text()); - } else if (childE.tagName() == QLatin1String("Licenses")) { - QHash 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 if (childE.tagName() == QLatin1String("Version")) { - info.data.insert(QLatin1String("inheritVersionFrom"), - childE.attribute(QLatin1String("inheritVersionFrom"))); - info.data[childE.tagName()] = childE.text(); - } else if (childE.tagName() == QLatin1String("DisplayName")) { - processLocalizedTag(childE, info.data); - } else if (childE.tagName() == QLatin1String("Description")) { - processLocalizedTag(childE, info.data); - } else if (childE.tagName() == QLatin1String("UpdateFile")) { - info.data[QLatin1String("CompressedSize")] = childE.attribute(QLatin1String("CompressedSize")); - info.data[QLatin1String("UncompressedSize")] = childE.attribute(QLatin1String("UncompressedSize")); - } else { - info.data[childE.tagName()] = childE.text(); - } - } - - if (!info.data.contains(QLatin1String("Name"))) { - setInvalidContentError(tr("PackageUpdate element without Name")); - return false; - } - if (!info.data.contains(QLatin1String("Version"))) { - setInvalidContentError(tr("PackageUpdate element without Version")); - return false; - } - if (!info.data.contains(QLatin1String("ReleaseDate"))) { - setInvalidContentError(tr("PackageUpdate element without ReleaseDate")); - return false; - } - - updateInfoList.append(info); - return true; -} - -void UpdatesInfoData::processLocalizedTag(const QDomElement &childE, QHash &info) const -{ - QString languageAttribute = childE.attribute(QLatin1String("xml:lang")).toLower(); - if (!info.contains(childE.tagName()) && (languageAttribute.isEmpty())) - info[childE.tagName()] = childE.text(); - - // overwrite default if we have a language specific description - if (QLocale().name().startsWith(languageAttribute, Qt::CaseInsensitive)) - info[childE.tagName()] = childE.text(); -} - - -// -// UpdatesInfo -// -UpdatesInfo::UpdatesInfo() - : d(new UpdatesInfoData) -{ -} - -UpdatesInfo::~UpdatesInfo() -{ -} - -bool UpdatesInfo::isValid() const -{ - return d->error == NoError; -} - -QString UpdatesInfo::errorString() const -{ - return d->errorMessage; -} - -void 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 UpdatesInfo::fileName() const -{ - return d->updateXmlFile; -} - -QString UpdatesInfo::applicationName() const -{ - return d->applicationName; -} - -QString UpdatesInfo::applicationVersion() const -{ - return d->applicationVersion; -} - -int UpdatesInfo::updateInfoCount() const -{ - return d->updateInfoList.count(); -} - -UpdateInfo UpdatesInfo::updateInfo(int index) const -{ - if (index < 0 || index >= d->updateInfoList.count()) - return UpdateInfo(); - return d->updateInfoList.at(index); -} - -QList UpdatesInfo::updatesInfo() const -{ - return d->updateInfoList; -} diff --git a/src/libs/kdtools/kdupdaterupdatesinfo_p.h b/src/libs/kdtools/kdupdaterupdatesinfo_p.h deleted file mode 100644 index 716bc4fcf..000000000 --- a/src/libs/kdtools/kdupdaterupdatesinfo_p.h +++ /dev/null @@ -1,91 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef KD_UPDATER_UPDATE_INFO_H -#define KD_UPDATER_UPDATE_INFO_H - -#include "kdupdater.h" -#include "kdupdaterupdatesinfodata_p.h" - -#include -#include -#include - -// They are not a part of the public API -// Classes and structures in this header file are for internal use only but still exported for auto tests. - -namespace KDUpdater { - -struct KDTOOLS_EXPORT UpdateInfo -{ - QHash data; -}; - -class KDTOOLS_EXPORT UpdatesInfo -{ -public: - enum Error - { - NoError = 0, - NotYetReadError, - CouldNotReadUpdateInfoFileError, - InvalidXmlError, - InvalidContentError - }; - - UpdatesInfo(); - ~UpdatesInfo(); - - bool isValid() const; - - Error error() const; - QString errorString() const; - - QString fileName() const; - void setFileName(const QString &updateXmlFile); - - QString applicationName() const; - QString applicationVersion() const; - - int updateInfoCount() const; - UpdateInfo updateInfo(int index) const; - QList updatesInfo() const; - -private: - QSharedDataPointer d; -}; - -} // namespace KDUpdater - -#endif // KD_UPDATER_UPDATE_INFO_H diff --git a/src/libs/kdtools/kdupdaterupdatesinfodata_p.h b/src/libs/kdtools/kdupdaterupdatesinfodata_p.h deleted file mode 100644 index 402c25567..000000000 --- a/src/libs/kdtools/kdupdaterupdatesinfodata_p.h +++ /dev/null @@ -1,73 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef KD_UPDATER_UPDATE_INFO_DATA_H -#define KD_UPDATER_UPDATE_INFO_DATA_H - -#include -#include - -QT_FORWARD_DECLARE_CLASS(QDomElement) - -namespace KDUpdater { - -struct UpdateInfo; - -struct UpdatesInfoData : public QSharedData -{ - Q_DECLARE_TR_FUNCTIONS(KDUpdater::UpdatesInfoData) - -public: - UpdatesInfoData(); - ~UpdatesInfoData(); - - int error; - QString errorMessage; - QString updateXmlFile; - QString applicationName; - QString applicationVersion; - QList updateInfoList; - - void parseFile(const QString &updateXmlFile); - bool parsePackageUpdateElement(const QDomElement &updateE); - - void setInvalidContentError(const QString &detail); - -private: - void processLocalizedTag(const QDomElement &childE, QHash &info) const; -}; - -} // namespace KDUpdater - -#endif // KD_UPDATER_UPDATE_INFO_DATA_H diff --git a/src/libs/kdtools/localpackagehub.h b/src/libs/kdtools/localpackagehub.h index 4e2f6634f..540b24481 100644 --- a/src/libs/kdtools/localpackagehub.h +++ b/src/libs/kdtools/localpackagehub.h @@ -36,7 +36,7 @@ #ifndef KD_UPDATER_PACKAGES_INFO_H #define KD_UPDATER_PACKAGES_INFO_H -#include "kdupdater.h" +#include "updater.h" #include #include diff --git a/src/libs/kdtools/lockfile.cpp b/src/libs/kdtools/lockfile.cpp new file mode 100644 index 000000000..5923dc07e --- /dev/null +++ b/src/libs/kdtools/lockfile.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "lockfile.h" +#include "lockfile_p.h" + +KDLockFile::KDLockFile(const QString &name) + : d(new Private(name)) +{ +} + +KDLockFile::~KDLockFile() +{ + delete d; +} + +bool KDLockFile::lock() +{ + return d->lock(); +} + +QString KDLockFile::errorString() const +{ + return d->errorString; +} + +bool KDLockFile::unlock() +{ + return d->unlock(); +} diff --git a/src/libs/kdtools/lockfile.h b/src/libs/kdtools/lockfile.h new file mode 100644 index 000000000..9a762a716 --- /dev/null +++ b/src/libs/kdtools/lockfile.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef KDLOCKFILE_H +#define KDLOCKFILE_H + +#include "kdtoolsglobal.h" + +class KDTOOLS_EXPORT KDLockFile +{ + Q_DISABLE_COPY(KDLockFile) + +public: + explicit KDLockFile(const QString &name); + ~KDLockFile(); + + QString errorString() const; + + bool lock(); + bool unlock(); + +private: + class Private; + Private *d; +}; + +#endif // KDLOCKFILE_H diff --git a/src/libs/kdtools/lockfile_p.h b/src/libs/kdtools/lockfile_p.h new file mode 100644 index 000000000..7bdd74494 --- /dev/null +++ b/src/libs/kdtools/lockfile_p.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef KDLOCKFILE_P_H +#define KDLOCKFILE_P_H + +#include "lockfile.h" + +#include + +#ifdef Q_OS_WIN +# include +#endif + +class KDLockFile::Private +{ +public: + explicit Private(const QString& name) + : filename(name) + , handle(0) + , locked(false) + {} + + bool lock(); + bool unlock(); + + QString errorString; + +private: + QString filename; +#ifdef Q_OS_WIN + HANDLE handle; +#else + int handle; +#endif + bool locked; +}; + +#endif // KDLOCKFILE_P_H diff --git a/src/libs/kdtools/lockfile_unix.cpp b/src/libs/kdtools/lockfile_unix.cpp new file mode 100644 index 000000000..d37fc8fb1 --- /dev/null +++ b/src/libs/kdtools/lockfile_unix.cpp @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "lockfile_p.h" + +#include +#include + +#include +#include +#include + +bool KDLockFile::Private::lock() +{ + if (locked) + return true; + + errorString.clear(); + errno = 0; + handle = open(filename.toLatin1().constData(), O_CREAT | O_RDWR | O_NONBLOCK, 0600); + if (handle == -1) { + errorString = QCoreApplication::translate("KDLockFile", "Cannot create lock file \"%1\": " + "%2").arg(QDir::toNativeSeparators(filename), QString::fromLocal8Bit(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 = QCoreApplication::translate("KDLockFile", "Cannot write PID to lock " + "file \"%1\": %2").arg(QDir::toNativeSeparators(filename), QString::fromLocal8Bit(strerror(errno))); + return false; + } + written += n; + } + errno = 0; + locked = flock(handle, LOCK_NB | LOCK_EX) != -1; + if (!locked) { + errorString = QCoreApplication::translate("KDLockFile", "Cannot obtain the lock for " + "file \"%1\": %2").arg(QDir::toNativeSeparators(filename), QString::fromLocal8Bit(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 = QCoreApplication::translate("KDLockFile", "Cannot release the lock for " + "file \"%1\": %2").arg(QDir::toNativeSeparators(filename), QString::fromLocal8Bit(strerror(errno))); + } else { + unlink(filename.toLatin1()); + } + return !locked; +} diff --git a/src/libs/kdtools/lockfile_win.cpp b/src/libs/kdtools/lockfile_win.cpp new file mode 100644 index 000000000..137cf3cf4 --- /dev/null +++ b/src/libs/kdtools/lockfile_win.cpp @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "lockfile.h" +#include "lockfile_p.h" + +#include "utils.h" + +#include +#include +#include + +bool KDLockFile::Private::lock() +{ + if (locked) + return locked; + + errorString.clear(); + handle = CreateFile(filename.toStdWString().data(), GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ, NULL, QFileInfo(filename).exists() ? OPEN_EXISTING : CREATE_NEW, + FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, NULL); + + if (handle == INVALID_HANDLE_VALUE) { + errorString = QCoreApplication::translate("KDLockFile", "Cannot create lock file \"%1\": " + "%2").arg(QDir::toNativeSeparators(filename), QInstaller::windowsErrorString(GetLastError())); + return false; + } + + DWORD bytesWritten; + const QByteArray pid = QString::number(QCoreApplication::applicationPid()).toLatin1(); + if (!WriteFile(handle, pid.data(), pid.size(), &bytesWritten, NULL)) { + errorString = QCoreApplication::translate("KDLockFile", "Cannot write PID to lock file " + "\"%1\": %2").arg(QDir::toNativeSeparators(filename), QInstaller::windowsErrorString(GetLastError())); + return false; + } + FlushFileBuffers(handle); + + if (!LockFile(handle, 0, 0, QFileInfo(filename).size(), 0)) { + errorString = QCoreApplication::translate("KDLockFile", "Cannot obtain the lock for " + "file \"%1\": %2").arg(QDir::toNativeSeparators(filename), QInstaller::windowsErrorString(GetLastError())); + } else { + locked = true; + } + return locked; +} + +bool KDLockFile::Private::unlock() +{ + errorString.clear(); + if (!locked) + return true; + + if (!UnlockFile(handle, 0, 0, QFileInfo(filename).size(), 0)) { + errorString = QCoreApplication::translate("KDLockFile", "Cannot release the lock for " + "file \"%1\": %2").arg(QDir::toNativeSeparators(filename), QInstaller::windowsErrorString(GetLastError())); + } else { + locked = false; + CloseHandle(handle); + } + return !locked; +} diff --git a/src/libs/kdtools/runoncechecker.cpp b/src/libs/kdtools/runoncechecker.cpp new file mode 100644 index 000000000..741708a69 --- /dev/null +++ b/src/libs/kdtools/runoncechecker.cpp @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "runoncechecker.h" +#include "lockfile.h" +#include "sysinfo.h" + +#include +#include +#include +#include +#include + +#include + +using namespace KDUpdater; + +KDRunOnceChecker::KDRunOnceChecker(const QString &filename) + : m_lockfile(filename) +{ +} + +KDRunOnceChecker::~KDRunOnceChecker() +{ + if (!m_lockfile.unlock()) + qWarning().noquote() << m_lockfile.errorString(); +} + +class ProcessnameEquals +{ +public: + ProcessnameEquals(const QString &name) +#ifdef Q_OS_WIN + : m_name(name.toLower()) +#else + : m_name(name) +#endif + {} + + bool operator()(const ProcessInfo &info) + { +#ifdef Q_OS_WIN + const QString infoName = info.name.toLower(); + if (infoName == QDir::toNativeSeparators(m_name)) + return true; +#else + const QString infoName = info.name; +#endif + if (infoName == m_name) + return true; + + const QFileInfo fi(infoName); + if (fi.fileName() == m_name || fi.baseName() == m_name) + return true; + return false; + } + +private: + QString m_name; +}; + +bool KDRunOnceChecker::isRunning(KDRunOnceChecker::ConditionFlags flags) +{ + if (flags.testFlag(ConditionFlag::ProcessList)) { + const QList allProcesses = runningProcesses(); + const int count = std::count_if(allProcesses.constBegin(), allProcesses.constEnd(), + ProcessnameEquals(QCoreApplication::applicationFilePath())); + return (count > 1); + } + + if (flags.testFlag(ConditionFlag::Lockfile)) { + const bool locked = m_lockfile.lock(); + if (!locked) + qWarning().noquote() << m_lockfile.errorString(); + return !locked; + } + return false; +} diff --git a/src/libs/kdtools/runoncechecker.h b/src/libs/kdtools/runoncechecker.h new file mode 100644 index 000000000..cc64e9d06 --- /dev/null +++ b/src/libs/kdtools/runoncechecker.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef KDTOOLS_RUNONCECHECKER_H +#define KDTOOLS_RUNONCECHECKER_H + +#include "lockfile.h" + +#include + +class KDTOOLS_EXPORT KDRunOnceChecker +{ + Q_DISABLE_COPY(KDRunOnceChecker) + +public: + enum struct ConditionFlag { + Lockfile = 0x01, + ProcessList = 0x02 + }; + Q_DECLARE_FLAGS(ConditionFlags, ConditionFlag) + + explicit KDRunOnceChecker(const QString &filename = QString()); + ~KDRunOnceChecker(); + + bool isRunning(KDRunOnceChecker::ConditionFlags flags); + +private: + KDLockFile m_lockfile; +}; + +#endif // KDTOOLS_RUNONCECHECKER_H diff --git a/src/libs/kdtools/selfrestarter.cpp b/src/libs/kdtools/selfrestarter.cpp new file mode 100644 index 000000000..915f55c43 --- /dev/null +++ b/src/libs/kdtools/selfrestarter.cpp @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "selfrestarter.h" + +#include +#include +#include + +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"); + delete d; + 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/src/libs/kdtools/selfrestarter.h b/src/libs/kdtools/selfrestarter.h new file mode 100644 index 000000000..3808ac207 --- /dev/null +++ b/src/libs/kdtools/selfrestarter.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef KDTOOLS_KDSELFRESTARTER_H +#define KDTOOLS_KDSELFRESTARTER_H + +#include "kdtoolsglobal.h" + +class KDTOOLS_EXPORT KDSelfRestarter +{ +public: + KDSelfRestarter(int argc, char *argv[]); + ~KDSelfRestarter(); + + static bool restartOnQuit(); + static void setRestartOnQuit(bool restart); + +private: + Q_DISABLE_COPY(KDSelfRestarter) + class Private; + Private *d; +}; + +#endif // KDTOOLS_KDSELFRESTARTER_H diff --git a/src/libs/kdtools/sysinfo.cpp b/src/libs/kdtools/sysinfo.cpp new file mode 100644 index 000000000..ea3326499 --- /dev/null +++ b/src/libs/kdtools/sysinfo.cpp @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "sysinfo.h" + +#include +#include + +using namespace KDUpdater; + +struct PathLongerThan +{ + bool operator()(const VolumeInfo &lhs, const VolumeInfo &rhs) const + { + return lhs.mountPath().length() > rhs.mountPath().length(); + } +}; + +VolumeInfo::VolumeInfo() + : m_size(0) + , m_availableSize(0) +{ +} + +VolumeInfo VolumeInfo::fromPath(const QString &path) +{ + QDir targetPath(QDir::cleanPath(path)); + QList volumes = mountedVolumes(); + + // sort by length to get the longest mount point (not just "/") first + std::sort(volumes.begin(), volumes.end(), PathLongerThan()); + foreach (const VolumeInfo &volume, volumes) { + const QDir volumePath(volume.mountPath()); + if (targetPath == volumePath) + return volume; +#ifdef Q_OS_WIN + if (QDir::toNativeSeparators(path).toLower().startsWith(volume.mountPath().toLower())) +#else + // we need to take some care here, as canonical path might return an empty string if the target + // does not exist yet + if (targetPath.exists()) { + // the target exist, we can solve the path and if it fits return + if (targetPath.canonicalPath().startsWith(volume.mountPath())) + return volume; + continue; + } + + // the target directory does not exist yet, we need to cd up till we find the first existing dir + QStringList parts = targetPath.absolutePath().split(QDir::separator(),QString::SkipEmptyParts); + while (targetPath.absolutePath() != QDir::rootPath()) { + if (targetPath.exists()) + break; + parts.pop_back(); + if (parts.isEmpty()) + targetPath = QDir(QDir::rootPath()); + else + targetPath = QDir(QLatin1Char('/') + parts.join(QDir::separator())); + } + + if (targetPath.canonicalPath().startsWith(volume.mountPath())) +#endif + return volume; + } + return VolumeInfo(); +} + +QString VolumeInfo::mountPath() const +{ + return m_mountPath; +} + +void VolumeInfo::setMountPath(const QString &path) +{ + m_mountPath = path; +} + +QString VolumeInfo::fileSystemType() const +{ + return m_fileSystemType; +} + +void VolumeInfo::setFileSystemType(const QString &type) +{ + m_fileSystemType = type; +} + +QString VolumeInfo::volumeDescriptor() const +{ + return m_volumeDescriptor; +} + +void VolumeInfo::setVolumeDescriptor(const QString &descriptor) +{ + m_volumeDescriptor = descriptor; +} + +quint64 VolumeInfo::size() const +{ + return m_size; +} + +void VolumeInfo::setSize(const quint64 &size) +{ + m_size = size; +} + +quint64 VolumeInfo::availableSize() const +{ + return m_availableSize; +} + +void VolumeInfo::setAvailableSize(const quint64 &available) +{ + m_availableSize = available; +} + +bool VolumeInfo::operator==(const VolumeInfo &other) const +{ + return m_volumeDescriptor == other.m_volumeDescriptor; +} + +QDebug operator<<(QDebug dbg, VolumeInfo volume) +{ + return dbg << "KDUpdater::Volume(" << volume.mountPath() << ")"; +} + +QDebug operator<<(QDebug dbg, ProcessInfo process) +{ + return dbg << "KDUpdater::ProcessInfo(" << process.id << ", " << process.name << ")"; +} diff --git a/src/libs/kdtools/sysinfo.h b/src/libs/kdtools/sysinfo.h new file mode 100644 index 000000000..34192f60e --- /dev/null +++ b/src/libs/kdtools/sysinfo.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef KDSYSINFO_H +#define KDSYSINFO_H + +#include "kdtoolsglobal.h" + +#include + +namespace KDUpdater { + +class KDTOOLS_EXPORT VolumeInfo +{ +public: + VolumeInfo(); + static VolumeInfo fromPath(const QString &path); + + QString mountPath() const; + void setMountPath(const QString &path); + + QString fileSystemType() const; + void setFileSystemType(const QString &type); + + QString volumeDescriptor() const; + void setVolumeDescriptor(const QString &descriptor); + + quint64 size() const; + void setSize(const quint64 &size); + + quint64 availableSize() const; + void setAvailableSize(const quint64 &available); + + bool operator==(const VolumeInfo &other) const; + +private: + QString m_mountPath; + QString m_fileSystemType; + QString m_volumeDescriptor; + + quint64 m_size; + quint64 m_availableSize; +}; + +struct ProcessInfo +{ + quint32 id; + QString name; +}; + +quint64 installedMemory(); +QList mountedVolumes(); +QList runningProcesses(); +bool killProcess(const ProcessInfo &process, int msecs = 30000); +bool pathIsOnLocalDevice(const QString &path); + +} // namespace KDUpdater + +QT_BEGIN_NAMESPACE +class QDebug; +QT_END_NAMESPACE + +QDebug operator<<(QDebug dbg, KDUpdater::VolumeInfo volume); +QDebug operator<<(QDebug dbg, KDUpdater::ProcessInfo process); + +#endif // KDSYSINFO_H diff --git a/src/libs/kdtools/sysinfo_mac.cpp b/src/libs/kdtools/sysinfo_mac.cpp new file mode 100644 index 000000000..437ccf29f --- /dev/null +++ b/src/libs/kdtools/sysinfo_mac.cpp @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "sysinfo.h" + +#include + +#include +#include +#include + +#include + +namespace KDUpdater { + +quint64 installedMemory() +{ + SInt32 mb = 0; + Gestalt(gestaltPhysicalRAMSizeInMegabytes, &mb); + return quint64(static_cast(mb) * 1024LL * 1024LL); +} + +QList mountedVolumes() +{ + QList 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) { + FSGetVolumeInfo(volume, 0, 0, kFSVolInfoSizes, &info, 0, 0); + + VolumeInfo v; + v.setSize(quint64(info.totalBytes)); + v.setAvailableSize(quint64(info.freeBytes)); + v.setMountPath(QString::fromLocal8Bit(reinterpret_cast< char* >(path))); + + struct statfs data; + if (statfs(qPrintable(v.mountPath() + QLatin1String("/.")), &data) == 0) { + v.setFileSystemType(QLatin1String(data.f_fstypename)); + v.setVolumeDescriptor(QLatin1String(data.f_mntfromname)); + } + result.append(v); + } + } + return result; +} + +QList runningProcesses() +{ + int mib[4] = { + CTL_KERN, + KERN_ARGMAX, + 0, + 0 + }; + + int argMax = 0; + size_t argMaxSize = sizeof(argMax); + // fetch the maximum process arguments size + sysctl(mib, 2, &argMax, &argMaxSize, NULL, 0); + char *processArguments = (char*) malloc(argMax); + + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_ALL; + size_t processTableSize = 0; + // fetch the kernel process table size + sysctl(mib, 4, NULL, &processTableSize, NULL, 0); + struct kinfo_proc *processTable = (kinfo_proc*) malloc(processTableSize); + + // fetch the process table + sysctl(mib, 4, processTable, &processTableSize, NULL, 0); + + QList processes; + for (size_t i = 0; i < (processTableSize / sizeof(struct kinfo_proc)); ++i) { + struct kinfo_proc *process = processTable + i; + + ProcessInfo processInfo; + processInfo.id = process->kp_proc.p_pid; + + mib[1] = KERN_PROCARGS2; + mib[2] = process->kp_proc.p_pid; + mib[3] = 0; + + size_t size = argMax; + // fetch the process arguments + if (sysctl(mib, 3, processArguments, &size, NULL, 0) != -1) { + /* + * |-----------------| <-- data returned by sysctl() + * | argc | + * |-----------------| + * | executable path | + * |-----------------| + * | arguments | + * ~~~~~~~~~~~~~~~~~~~ + * |-----------------| + */ + processInfo.name = QString::fromLocal8Bit(processArguments + sizeof(int)); + } else { + // if we fail, use the name from the process table + processInfo.name = QString::fromLocal8Bit(process->kp_proc.p_comm); + } + processes.append(processInfo); + } + free(processTable); + free(processArguments); + + return processes; +} + +bool pathIsOnLocalDevice(const QString &path) +{ + Q_UNUSED(path); + + return true; +} + +bool killProcess(const ProcessInfo &process, int msecs) +{ + Q_UNUSED(process); + Q_UNUSED(msecs); + + return true; +} + +} // namespace KDUpdater diff --git a/src/libs/kdtools/sysinfo_x11.cpp b/src/libs/kdtools/sysinfo_x11.cpp new file mode 100644 index 000000000..b5bd9d6a6 --- /dev/null +++ b/src/libs/kdtools/sysinfo_x11.cpp @@ -0,0 +1,145 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "sysinfo.h" + +#include +#include + +#include +#include +#include +#include + +namespace KDUpdater { + +quint64 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 quint64(); + + const QStringList parts = s.split(QLatin1Char(' '), QString::SkipEmptyParts); + return quint64(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 quint64(physmem); +#endif + return 0; +} + +QList mountedVolumes() +{ + QList result; + + QFile f(QLatin1String("/etc/mtab")); + if (!f.open(QIODevice::ReadOnly)) { + qCritical("%s: Cannot open %s: %s", Q_FUNC_INFO, qPrintable(f.fileName()), qPrintable(f.errorString())); + return result; //better error-handling? + } + + QTextStream stream(&f); + while (true) { + const QString s = stream.readLine(); + if (s.isNull()) + return result; + + if (!s.startsWith(QLatin1Char('/')) && !s.startsWith(QLatin1String("tmpfs ") + QDir::tempPath())) + continue; + + const QStringList parts = s.split(QLatin1Char(' '), QString::SkipEmptyParts); + + VolumeInfo v; + v.setMountPath(parts.at(1)); + v.setVolumeDescriptor(parts.at(0)); + v.setFileSystemType(parts.value(2)); + + struct statvfs data; + if (statvfs(qPrintable(v.mountPath() + QLatin1String("/.")), &data) == 0) { + v.setSize(quint64(static_cast(data.f_blocks) * data.f_bsize)); + v.setAvailableSize(quint64(static_cast(data.f_bavail) * data.f_bsize)); + } + result.append(v); + } + return result; +} + +QList runningProcesses() +{ + QList 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()) { + ProcessInfo processInfo; + processInfo.name = linkInfo.symLinkTarget(); + processInfo.id = info.fileName().toInt(); + processes.append(processInfo); + } + } + } + return processes; +} + +bool pathIsOnLocalDevice(const QString &path) +{ + Q_UNUSED(path); + + return true; +} + +bool killProcess(const ProcessInfo &process, int msecs) +{ + Q_UNUSED(process); + Q_UNUSED(msecs); + + return true; +} + +} // namespace KDUpdater diff --git a/src/libs/kdtools/task.cpp b/src/libs/kdtools/task.cpp new file mode 100644 index 000000000..5c56da187 --- /dev/null +++ b/src/libs/kdtools/task.cpp @@ -0,0 +1,455 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "task.h" + +using namespace KDUpdater; + +/*! + \inmodule kdupdater + \class KDUpdater::Task + \brief The Task class is the base class for all tasks 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. + + User should be careful of these points: + \list + \li Task classes can be started only once. + \li Instances of this class cannot be created. Only instances of the subclasses can. + \endlist +*/ + +/*! + \enum Task::Capability + This enum value sets the capabilities of the task. + + \value NoCapability + The task has no capabilities, so it cannot be paused or stopped. + \value Pausable + The task can be paused. + \value Stoppable + The task can be stopped. +*/ + +/*! + \internal +*/ +KDUpdater::Task::Task(const QString &name, int caps, QObject *parent) + : QObject(parent) + , m_caps(caps) + , m_name(name) + , m_errorCode(0) + , m_started(false) + , m_finished(false) + , m_paused(false) + , m_stopped(false) + , m_progressPc(0) + , m_autoDelete(true) +{ +} + +/*! + \internal +*/ +Task::~Task() +{} + +/*! + Returns the name of the task. +*/ +QString Task::name() const +{ + return m_name; +} + +/*! + Returns the capabilities of the task. It is a combination of one or more + Task::Capability flags. +*/ +int Task::capabilities() const +{ + return m_caps; +} + +/*! + Returns the last reported error code. +*/ +int Task::error() const +{ + return m_errorCode; +} + +/*! + Returns the last reported error message text. +*/ +QString Task::errorString() const +{ + return m_errorText; +} + +/*! + Returns whether the task has started and is running. +*/ +bool Task::isRunning() const +{ + return m_started; +} + +/*! + Returns whether the task has finished or not. + + \note Stopped (or canceled) tasks are not finished tasks. +*/ +bool Task::isFinished() const +{ + return m_finished; +} + +/*! + Returns whether the task is paused or not. +*/ +bool Task::isPaused() const +{ + return m_paused; +} + +/*! + Returns whether the task is stopped or not. + + \note Finished tasks are not stopped classes. +*/ +bool Task::isStopped() const +{ + return m_stopped; +} + +/*! + Returns the progress in percentage made by this task. +*/ +int Task::progressPercent() const +{ + return m_progressPc; +} + +/*! + Returns a string that describes the progress made by this task as a string. +*/ +QString Task::progressText() const +{ + return m_progressText; +} + +/*! + Starts the task. +*/ +void Task::run() +{ + if (m_started) { + qDebug("Trying to start an already started task"); + return; + } + + if (m_finished || m_stopped) { + qDebug("Trying to start a finished or canceled task"); + return; + } + + m_stopped = false; + m_finished = false; // for the sake of completeness + m_started = true; + emit started(); + reportProgress(0, tr("%1 started").arg(m_name)); + + doRun(); +} + +/*! + Stops the task, provided the task has the Task::Stoppable capability. + + \note Once the task is stopped, it cannot be restarted. +*/ +void Task::stop() +{ + if (!(m_caps & Stoppable)) { + const QString errorMsg = tr("%1 cannot be stopped").arg(m_name); + reportError(ECannotStopTask, errorMsg); + return; + } + + if (!m_started) { + qDebug("Trying to stop an unstarted task"); + return; + } + + if(m_finished || m_stopped) + { + qDebug("Trying to stop a finished or canceled task"); + return; + } + + m_stopped = doStop(); + if (!m_stopped) { + const QString errorMsg = tr("Cannot stop task %1").arg(m_name); + reportError(ECannotStopTask, errorMsg); + return; + } + + m_started = false; // the task is not running + m_finished = false; // the task is not finished, but was canceled half-way through + + emit stopped(); + if (m_autoDelete) + deleteLater(); +} + +/*! + Pauses the task, provided the task has the Task::Pausable capability. +*/ +void Task::pause() +{ + if (!(m_caps & Pausable)) { + const QString errorMsg = tr("%1 cannot be paused").arg(m_name); + reportError(ECannotPauseTask, errorMsg); + return; + } + + if (!m_started) { + qDebug("Trying to pause an unstarted task"); + return; + } + + if (m_finished || m_stopped) { + qDebug("Trying to pause a finished or canceled task"); + return; + } + + m_paused = doPause(); + + if (!m_paused) { + const QString errorMsg = tr("Cannot pause task %1").arg(m_name); + reportError(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() ??? + m_started = true; + m_finished = false; + m_stopped = false; + + emit paused(); +} + +/*! + Resumes the task if it was paused. +*/ +void Task::resume() +{ + if (!m_paused) { + qDebug("Trying to resume an unpaused task"); + return; + } + + const bool val = doResume(); + + if (!val) { + const QString errorMsg = tr("Cannot resume task %1").arg(m_name); + reportError(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() ??? + m_started = true; + m_paused = false; + m_finished = false; + m_stopped = false; + + emit resumed(); +} + +/*! + \internal +*/ +void Task::reportProgress(int percent, const QString &text) +{ + if (m_progressPc == percent) + return; + + m_progressPc = percent; + m_progressText = text; + emit progressValue(m_progressPc); + emit progressText(m_progressText); +} + +/*! + \internal +*/ +void Task::reportError(int errorCode, const QString &errorText) +{ + m_errorCode = errorCode; + m_errorText = errorText; + + emit error(m_errorCode, m_errorText); + if (m_autoDelete) + deleteLater(); +} + +/*! + \internal +*/ +void Task::reportError(const QString &errorText) +{ + reportError(EUnknown, errorText); +} + +/*! + \internal +*/ +void Task::reportDone() +{ + QString msg = tr("%1 done"); + reportProgress(100, msg); + + // State should be finished, but not started, paused or stopped. + m_finished = true; + m_started = false; + m_paused = false; + m_stopped = false; + m_errorCode = 0; + m_errorText.clear(); + + emit finished(); + if (m_autoDelete) + deleteLater(); +} + +/*! + Returns \c true if the task will be automatically deleted. +*/ +bool Task::autoDelete() const +{ + return m_autoDelete; +} + +/*! + Automatically deletes the task if \a autoDelete is \c true. +*/ +void Task::setAutoDelete(bool autoDelete) +{ + m_autoDelete = autoDelete; +} + +/*! + \fn virtual void KDUpdater::Task::doRun() = 0; + + Returns \c 0 if the task is run. +*/ + +/*! + \fn virtual bool KDUpdater::Task::doStop() = 0; + + Returns \c true if the task is stopped. +*/ + +/*! + \fn virtual bool KDUpdater::Task::doPause() = 0; + + Returns \c true if the task is paused. +*/ + +/*! + \fn virtual bool KDUpdater::Task::doResume() = 0; + + Returns \c true if the task is resumed. +*/ + +/*! + \fn void Task::error(int code, const QString &errorText) + + This signal is emitted to notify an error during the execution of this task. + + The \a code parameter indicates the error that was found during the execution of the + task, while the \a errorText is the human-readable description of the last error that occurred. +*/ + +/*! + \fn void Task::progressValue(int percent) + + This signal is emitted to report progress made by the task. The \a percent parameter gives + the progress made as a percentage. +*/ + +/*! + \fn void Task::progressText(const QString &progressText) + + This signal is emitted to report the progress made by the task. The \a progressText parameter + represents the progress made in a human-readable form. +*/ + +/*! + \fn void Task::started() + + This signal is emitted when the task has started. +*/ + +/*! + \fn void Task::paused() + + This signal is emitted when the task has paused. +*/ + +/*! + \fn void Task::resumed() + + This signal is emitted when the task has resumed. +*/ + +/*! + \fn void Task::stopped() + + This signal is emitted when the task has stopped (or canceled). +*/ + +/*! + \fn void Task::finished() + + This signal is emitted when the task has finished. +*/ diff --git a/src/libs/kdtools/task.h b/src/libs/kdtools/task.h new file mode 100644 index 000000000..66e85e662 --- /dev/null +++ b/src/libs/kdtools/task.h @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef KD_UPDATER_TASK_H +#define KD_UPDATER_TASK_H + +#include "updater.h" + +#include + +namespace KDUpdater { + +class KDTOOLS_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; + + bool autoDelete() const; + void setAutoDelete(bool autoDelete); + +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 reportError(const QString &errorText); + void reportDone(); + + // Task interface + virtual void doRun() = 0; + virtual bool doStop() = 0; + virtual bool doPause() = 0; + virtual bool doResume() = 0; + +private: + int m_caps; + QString m_name; + int m_errorCode; + QString m_errorText; + bool m_started; + bool m_finished; + bool m_paused; + bool m_stopped; + int m_progressPc; + QString m_progressText; + bool m_autoDelete; +}; + +} // namespace KDUpdater + +#endif // KD_UPDATER_TASK_H diff --git a/src/libs/kdtools/update.cpp b/src/libs/kdtools/update.cpp new file mode 100644 index 000000000..87caff878 --- /dev/null +++ b/src/libs/kdtools/update.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "update.h" + +using namespace KDUpdater; + +/*! + \inmodule kdupdater + \class KDUpdater::Update + \brief Represents a single update + + The KDUpdater::Update class contains information about an update. It is created by KDUpdater::UpdateFinder + corresponding to the update. + + 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. +*/ + + +/*! + \internal +*/ +Update::Update(const QInstaller::PackageSource &packageSource, const UpdateInfo &updateInfo) + : m_packageSource(packageSource) + , m_updateInfo(updateInfo) +{ +} + +/*! + Returns the data specified by \a name, or an invalid \a defaultValue if the + data does not exist. +*/ +QVariant Update::data(const QString &name, const QVariant &defaultValue) const +{ + return m_updateInfo.data.value(name, defaultValue); +} diff --git a/src/libs/kdtools/update.h b/src/libs/kdtools/update.h new file mode 100644 index 000000000..d301a5360 --- /dev/null +++ b/src/libs/kdtools/update.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef KD_UPDATER_UPDATE_H +#define KD_UPDATER_UPDATE_H + +#include "packagesource.h" +#include "updatesinfo_p.h" +#include + +namespace KDUpdater { + +class Update +{ +public: + QVariant data(const QString &name, const QVariant &defaultValue = QVariant()) const; + + QInstaller::PackageSource packageSource() const {return m_packageSource; } + +private: + friend class UpdateFinder; + Update(const QInstaller::PackageSource &packageSource, const UpdateInfo &updateInfo); + +private: + QInstaller::PackageSource m_packageSource; + UpdateInfo m_updateInfo; +}; + +} // namespace KDUpdater + +#endif // KD_UPDATER_UPDATE_H diff --git a/src/libs/kdtools/updatefinder.cpp b/src/libs/kdtools/updatefinder.cpp new file mode 100644 index 000000000..3472cd13e --- /dev/null +++ b/src/libs/kdtools/updatefinder.cpp @@ -0,0 +1,640 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "updatefinder.h" +#include "update.h" +#include "filedownloader.h" +#include "filedownloaderfactory.h" +#include "updatesinfo_p.h" +#include "localpackagehub.h" + +#include "fileutils.h" +#include "globals.h" + +#include +#include + +using namespace KDUpdater; +using namespace QInstaller; + +/*! + \inmodule kdupdater + \class KDUpdater::UpdateFinder + \brief The UpdaterFinder class finds updates applicable for installed packages. + + The KDUpdater::UpdateFinder class helps in searching for updates and installing them on the + application. The class basically processes the application's KDUpdater::PackagesInfo and the + UpdateXMLs it aggregates from all the update sources and populates a list of KDUpdater::Update + objects. +*/ + +// +// Private +// +class UpdateFinder::Private +{ +public: + enum struct Resolution { + AddPackage, + KeepExisting, + RemoveExisting + }; + + Private(UpdateFinder *qq) + : q(qq) + , downloadCompleteCount(0) + , m_downloadsToComplete(0) + {} + + ~Private() + { + clear(); + } + + struct Data { + Data() + : downloader(0) {} + Data(const PackageSource &i, FileDownloader *d = 0) + : info(i), downloader(d) {} + + PackageSource info; + FileDownloader *downloader; + }; + UpdateFinder *q; + QHash updates; + + // Temporary structure that notes down information about updates. + bool cancel; + int downloadCompleteCount; + int m_downloadsToComplete; + QHash m_updatesInfoList; + + void clear(); + void computeUpdates(); + void cancelComputeUpdates(); + bool downloadUpdateXMLFiles(); + bool computeApplicableUpdates(); + + QList applicableUpdates(UpdatesInfo *updatesInfo); + void createUpdateObjects(const PackageSource &source, const QList &updateInfoList); + Resolution checkPriorityAndVersion(const PackageSource &source, const QVariantHash &data) const; + void slotDownloadDone(); + + QSet packageSources; + std::weak_ptr m_localPackageHub; +}; + + +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 UpdateFinder::Private::clear() +{ + qDeleteAll(updates); + updates.clear(); + + const QList values = m_updatesInfoList.values(); + foreach (const Data &data, values) + delete data.downloader; + + qDeleteAll(m_updatesInfoList.keys()); + m_updatesInfoList.clear(); + + downloadCompleteCount = 0; + m_downloadsToComplete = 0; +} + +/*! + \internal + + This method computes the updates that can be applied on the application by + studying the application's KDUpdater::PackagesInfo object and the UpdateXML files + from each of the update sources described in QInstaller::PackageSource. + + This function can take a long time to complete. The following signals are emitted + during the execution of this function + + The function creates 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 QInstaller::PackageSource object associated with + the application. Package information is extracted from the 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 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 + + clear(); + cancel = false; + + // First do some quick sanity checks on the packages info + std::shared_ptr packages = m_localPackageHub.lock(); + if (!packages) { + q->reportError(tr("Cannot access the package information of this application.")); + return; + } + + if (!packages->isValid()) { + q->reportError(packages->errorString()); + return; + } + + // Now do some quick sanity checks on the package sources. + if (packageSources.count() <= 0) { + q->reportError(tr("No package sources set for this application.")); + 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("%n update(s) found.", "", updates.count())); + q->reportDone(); +} + +/*! + \internal + + Cancels the computation of updates. + + \sa computeUpdates() +*/ +void UpdateFinder::Private::cancelComputeUpdates() +{ + cancel = true; +} + +/*! + \internal + + This function downloads Updates.xml from all the update sources except local files. + 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 UpdateFinder::Private::downloadUpdateXMLFiles() +{ + // create UpdatesInfo for each update source + foreach (const PackageSource &info, packageSources) { + const QUrl url = QString::fromLatin1("%1/Updates.xml").arg(info.url.toString()); + if (url.scheme() != QLatin1String("resource") && url.scheme() != QLatin1String("file")) { + // create FileDownloader (except for local files and resources) + FileDownloader *downloader = FileDownloaderFactory::instance().create(url.scheme(), q); + if (!downloader) + break; + + downloader->setUrl(url); + downloader->setAutoRemoveDownloadedFile(true); + connect(downloader, SIGNAL(downloadCanceled()), q, SLOT(slotDownloadDone())); + connect(downloader, SIGNAL(downloadCompleted()), q, SLOT(slotDownloadDone())); + connect(downloader, SIGNAL(downloadAborted(QString)), q, SLOT(slotDownloadDone())); + m_updatesInfoList.insert(new UpdatesInfo, Data(info, downloader)); + } else { + UpdatesInfo *updatesInfo = new UpdatesInfo; + updatesInfo->setFileName(QInstaller::pathFromUrl(url)); + m_updatesInfoList.insert(updatesInfo, Data(info)); + } + } + + // Trigger download of Updates.xml file + downloadCompleteCount = 0; + m_downloadsToComplete = 0; + foreach (const Data &data, m_updatesInfoList) { + if (data.downloader) { + m_downloadsToComplete++; + data.downloader->download(); + } + } + + // Wait until all downloaders have completed their downloads. + while (true) { + QCoreApplication::processEvents(); + if (cancel) + return false; + + if (downloadCompleteCount == m_downloadsToComplete) + break; + + q->reportProgress(computePercent(downloadCompleteCount, m_downloadsToComplete), + tr("Downloading Updates.xml from update sources.")); + } + + // Setup the update info objects with the files from download. + foreach (UpdatesInfo *updatesInfo, m_updatesInfoList.keys()) { + const Data data = m_updatesInfoList.value(updatesInfo); + if (data.downloader) { + if (!data.downloader->isDownloaded()) { + q->reportError(tr("Cannot download package source %1 from \"%2\".").arg(data + .downloader->url().fileName(), data.info.url.toString())); + } else { + updatesInfo->setFileName(data.downloader->downloadedFileName()); + } + } + } + + // Remove all invalid update info objects. + QMutableHashIterator it(m_updatesInfoList); + while (it.hasNext()) { + UpdatesInfo *info = it.next().key(); + if (info->isValid()) + continue; + + q->reportError(info->errorString()); + delete info; + it.remove(); + } + + if (m_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. Thereby figures out whether an update is applicable for + this application or not. +*/ +bool UpdateFinder::Private::computeApplicableUpdates() +{ + int i = 0; + foreach (UpdatesInfo *updatesInfo, m_updatesInfoList.keys()) { + // Fetch updates applicable to this application. + QList updates = applicableUpdates(updatesInfo); + if (!updates.count()) + continue; + + if (cancel) + return false; + const PackageSource updateSource = m_updatesInfoList.value(updatesInfo).info; + + // Create Update objects for updates that have a valid + // UpdateFile + createUpdateObjects(updateSource, updates); + if (cancel) + return false; + + // Report progress + q->reportProgress(computeProgressPercentage(51, 100, computePercent(i, + m_updatesInfoList.count())), tr("Computing applicable updates.")); + ++i; + } + + q->reportProgress(99, tr("Application updates computed.")); + return true; +} + +QList UpdateFinder::Private::applicableUpdates(UpdatesInfo *updatesInfo) +{ + const QList dummy; + if (!updatesInfo || updatesInfo->updateInfoCount() == 0) + return dummy; + + std::shared_ptr packages = m_localPackageHub.lock(); + if (!packages) + return dummy; + + // Check to see if the updates info contains updates for any application + if (updatesInfo->applicationName() != QLatin1String("{AnyApplication}")) { + // 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() + // If the application appName isn't one of the app names, then the updates are not applicable. + const QStringList apps = appName.split(QInstaller::commaRegExp(), QString::SkipEmptyParts); + if (apps.indexOf([&packages] { return packages->isValid() ? packages->applicationName() + : QCoreApplication::applicationName(); } ()) < 0) { + return dummy; + } + } + return updatesInfo->updatesInfo(); +} + +void UpdateFinder::Private::createUpdateObjects(const PackageSource &source, + const QList &updateInfoList) +{ + foreach (const UpdateInfo &info, updateInfoList) { + const Resolution value = checkPriorityAndVersion(source, info.data); + if (value == Resolution::KeepExisting) + continue; + + const QString name = info.data.value(QLatin1String("Name")).toString(); + if (value == Resolution::RemoveExisting) + delete updates.take(name); + + // Create and register the update + updates.insert(name, new Update(source, info)); + } +} + +/* + If a package of the same name exists, always use the one with the higher + version. If the new package has the same version but a higher + priority, use the new new package, otherwise keep the already existing package. +*/ +UpdateFinder::Private::Resolution UpdateFinder::Private::checkPriorityAndVersion( + const PackageSource &source, const QVariantHash &newPackage) const +{ + const QString name = newPackage.value(QLatin1String("Name")).toString(); + if (Update *existingPackage = updates.value(name)) { + // Bingo, package was previously found elsewhere. + + const int match = compareVersion(newPackage.value(QLatin1String("Version")).toString(), + existingPackage->data(QLatin1String("Version")).toString()); + + if (match > 0) { + // new package has higher version, use + qDebug().nospace() << "Remove Package 'Name: " << name << ", Version: " + << existingPackage->data(QLatin1String("Version")).toString() + << ", Source: " << QFileInfo(existingPackage->packageSource().url.toLocalFile()).fileName() + << "' found a package with higher version 'Name: " + << name << ", Version: " << newPackage.value(QLatin1String("Version")).toString() + << ", Source: " << QFileInfo(source.url.toLocalFile()).fileName() << "'"; + return Resolution::RemoveExisting; + } + + if ((match == 0) && (source.priority > existingPackage->packageSource().priority)) { + // new package version equals but priority is higher, use + qDebug().nospace() << "Remove Package 'Name: " << name << ", Priority: " + << existingPackage->packageSource().priority + << ", Source: " << QFileInfo(existingPackage->packageSource().url.toLocalFile()).fileName() + << "' found a package with higher priority 'Name: " + << name << ", Priority: " << source.priority + << ", Source: " << QFileInfo(source.url.toLocalFile()).fileName() << "'"; + return Resolution::RemoveExisting; + } + return Resolution::KeepExisting; // otherwise keep existing + } + return Resolution::AddPackage; +} + +// +// UpdateFinder +// + +/*! + Constructs an update finder. +*/ +UpdateFinder::UpdateFinder() + : Task(QLatin1String("UpdateFinder"), Stoppable), + d(new Private(this)) +{ +} + +/*! + Destructor +*/ +UpdateFinder::~UpdateFinder() +{ + delete d; +} + +/*! + Returns a list of KDUpdater::Update objects. +*/ +QList UpdateFinder::updates() const +{ + return d->updates.values(); +} + +void UpdateFinder::setLocalPackageHub(std::weak_ptr hub) +{ + d->m_localPackageHub = std::move(hub); +} + +/*! + Sets the package sources information to use when searching for applicable packages. +*/ +void UpdateFinder::setPackageSources(const QSet &sources) +{ + d->packageSources = sources; +} + +/*! + \internal + + Implemented from KDUpdater::Task::doRun(). +*/ +void UpdateFinder::doRun() +{ + d->computeUpdates(); +} + +/*! + \internal + + Implemented from KDUpdater::Task::doStop(). +*/ +bool 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 from KDUpdater::Task::doStop(). +*/ +bool UpdateFinder::doPause() +{ + // Not a pausable task + return false; +} + +/*! + \internal + + Implemented from KDUpdater::Task::doStop(). +*/ +bool UpdateFinder::doResume() +{ + // Not a pausable task, hence it is not resumable as well + return false; +} + +/*! + \internal +*/ +void UpdateFinder::Private::slotDownloadDone() +{ + ++downloadCompleteCount; + + int pc = computePercent(downloadCompleteCount, m_downloadsToComplete); + pc = computeProgressPercentage(0, 45, pc); + q->reportProgress( pc, tr("Downloading Updates.xml from update sources.") ); +} + + +/*! + \inmodule kdupdater + + This function compares two version strings \c v1 and \c v2 and returns + -1, 0 or +1 based on the following rule + + \list + \li Returns 0 if v1 == v2 + \li Returns -1 if v1 < v2 + \li Returns +1 if v1 > v2 + \endlist + + 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 (true) { + if (index == v1_comps.count() && index < v2_comps.count()) + return -1; + if (index < v1_comps.count() && index == v2_comps.count()) + return +1; + 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_updatefinder.cpp" diff --git a/src/libs/kdtools/updatefinder.h b/src/libs/kdtools/updatefinder.h new file mode 100644 index 000000000..1cb75d05a --- /dev/null +++ b/src/libs/kdtools/updatefinder.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef KD_UPDATER_UPDATE_FINDER_H +#define KD_UPDATER_UPDATE_FINDER_H + +#include "task.h" +#include "packagesource.h" + +#include + +namespace KDUpdater { + +class LocalPackageHub; +class Update; + +class KDTOOLS_EXPORT UpdateFinder : public Task +{ + Q_OBJECT + class Private; + +public: + UpdateFinder(); + ~UpdateFinder(); + + QList updates() const; + + void setLocalPackageHub(std::weak_ptr hub); + void setPackageSources(const QSet &sources); + +private: + void doRun(); + bool doStop(); + bool doPause(); + bool doResume(); + +private: + Private *d; + Q_PRIVATE_SLOT(d, void slotDownloadDone()) +}; + +} // namespace KDUpdater + +#endif // KD_UPDATER_UPDATE_FINDER_H diff --git a/src/libs/kdtools/updateoperation.cpp b/src/libs/kdtools/updateoperation.cpp new file mode 100644 index 000000000..8bde8add1 --- /dev/null +++ b/src/libs/kdtools/updateoperation.cpp @@ -0,0 +1,528 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "updateoperation.h" + +#include "constants.h" +#include "fileutils.h" +#include "packagemanagercore.h" + +#include +#include +#include +#include +#include + +using namespace KDUpdater; + +/*! + \inmodule kdupdater + \class KDUpdater::UpdateOperation + \brief The UpdateOperation class is an abstract base class for update operations. + + The KDUpdater::UpdateOperation is an abstract class that specifies an interface for + update operations. Concrete implementations of this class must perform a single update + operation, such as copy, move, or delete. + + \note Two separate threads cannot be using a single instance of KDUpdater::UpdateOperation + at the same time. +*/ + +/*! + \enum UpdateOperation::Error + This enum code specifies error codes related to operation arguments and + operation runtime failures. + + \value NoError + No error occurred. + \value InvalidArguments + Number of arguments does not match or an invalid argument was set. + \value UserDefinedError + An error occurred during operation run. Use UpdateOperation::errorString() + to get the human-readable description of the error that occurred. +*/ + +/* + \internal + Returns a filename for a temporary file based on \a templateName. +*/ +static QString backupFileName(const QString &templateName) +{ + const QFileInfo templ(templateName); + QTemporaryFile file( QDir::temp().absoluteFilePath(templ.fileName())); + file.open(); + const QString name = file.fileName(); + file.close(); + file.remove(); + return name; +} + +/*! + \internal +*/ +UpdateOperation::UpdateOperation(QInstaller::PackageManagerCore *core) + : m_error(0) + , m_core(core) +{ + // Store the value for compatibility reasons. + m_values[QLatin1String("installer")] = QVariant::fromValue(core); +} + +/*! + \internal +*/ +UpdateOperation::~UpdateOperation() +{ + if (auto *core = packageManager()) + core->addFilesForDelayedDeletion(filesForDelayedDeletion()); +} + +/*! + Returns the update operation name. + + \sa setName() +*/ +QString UpdateOperation::name() const +{ + return m_name; +} + +/*! + Returns a command line string that describes the update operation. The returned string will be + of the form: + + \c{ ....} +*/ +QString UpdateOperation::operationCommand() const +{ + QString argsStr = m_arguments.join(QLatin1String( " " )); + return QString::fromLatin1( "%1 %2" ).arg(m_name, argsStr); +} + +/*! + Returns \c true if a value called \a name exists, otherwise returns \c false. +*/ +bool UpdateOperation::hasValue(const QString &name) const +{ + return m_values.contains(name); +} + +/*! + Clears the value of \a name and removes it. +*/ +void UpdateOperation::clearValue(const QString &name) +{ + m_values.remove(name); +} + +/*! + Returns the value of \a name. If the value does not exist, returns an empty QVariant. +*/ +QVariant UpdateOperation::value(const QString &name) const +{ + return m_values.value(name); +} + +/*! + Sets the value of \a name to \a value. +*/ +void UpdateOperation::setValue(const QString &name, const QVariant &value) +{ + m_values[name] = value; +} + +/*! + Sets the name of the operation to \a name. Subclasses will have to provide a unique name to + describe the operation. +*/ +void UpdateOperation::setName(const QString &name) +{ + m_name = name; +} + +/*! + Sets the arguments for the update operation to \a args. +*/ +void UpdateOperation::setArguments(const QStringList &args) +{ + m_arguments = args; +} + +/*! + Returns the arguments of the update operation. +*/ +QStringList UpdateOperation::arguments() const +{ + return m_arguments; +} + +bool UpdateOperation::checkArgumentCount(int minArgCount, int maxArgCount, + const QString &argDescription) +{ + const int argCount = arguments().count(); + if (argCount < minArgCount || argCount > maxArgCount) { + setError(InvalidArguments); + QString countRange; + if (minArgCount == maxArgCount) + countRange = tr("exactly %1").arg(minArgCount); + else if (maxArgCount == INT_MAX) + countRange = tr("at least %1").arg(minArgCount); + else if (minArgCount == 0) + countRange = tr("not more than %1").arg(maxArgCount); + else if (minArgCount == maxArgCount - 1) + countRange = tr("%1 or %2").arg(minArgCount).arg(maxArgCount); + else + countRange = tr("%1 to %2").arg(minArgCount).arg(maxArgCount); + + if (argDescription.isEmpty()) + setErrorString(tr("Invalid arguments in %1: %n arguments given, " + "%2 arguments expected.", 0, argCount) + .arg(name(), countRange)); + else + setErrorString(tr("Invalid arguments in %1: %n arguments given, " + "%2 arguments expected in the form: %3.", 0, argCount) + .arg(name(), countRange, argDescription)); + return false; + } + return true; +} + +bool UpdateOperation::checkArgumentCount(int argCount) +{ + return checkArgumentCount(argCount, argCount); +} + +struct StartsWith +{ + StartsWith(const QString &searchTerm) + : m_searchTerm(searchTerm) {} + + bool operator()(const QString &searchString) + { + return searchString.startsWith(m_searchTerm); + } + + QString m_searchTerm; +}; + +/*! + Searches the arguments for the key specified by \a key. If it can find the + key, it returns the value set for it. Otherwise, it returns \a defaultValue. + Arguments are specified in the following form: \c{key=value}. +*/ +QString UpdateOperation::argumentKeyValue(const QString &key, const QString &defaultValue) const +{ + const QString keySeparater(key + QLatin1String("=")); + const QStringList tArguments(arguments()); + QStringList::const_iterator it = std::find_if(tArguments.begin(), tArguments.end(), + StartsWith(keySeparater)); + if (it == tArguments.end()) + return defaultValue; + + const QString value = it->mid(keySeparater.size()); + + it = std::find_if(++it, tArguments.end(), StartsWith(keySeparater)); + if (it != tArguments.end()) { + qWarning().nospace() << "There are multiple keys in the arguments calling " << name() << ". " + << "Only the first found " << key << " is used: " + << arguments().join(QLatin1String("; ")); + } + return value; +} + +/*! + Returns a human-readable description of the last error that occurred. +*/ +QString UpdateOperation::errorString() const +{ + return m_errorString; +} + +/*! + Returns the error that was found during the processing of the operation. If no + error was found, returns NoError. Subclasses can set more detailed error codes (optional). + + \note To check if an operation was successful, use the return value of performOperation(), + undoOperation(), or testOperation(). +*/ +int UpdateOperation::error() const +{ + return m_error; +} + +/*! + Sets the human-readable description of the last error that occurred to \a str. +*/ +void UpdateOperation::setErrorString(const QString &str) +{ + m_errorString = str; +} + +/*! + Sets the error condition to be \a error. The human-readable message is set to \a errorString. + + \sa UpdateOperation::error() + \sa UpdateOperation::errorString() +*/ +void UpdateOperation::setError(int error, const QString &errorString) +{ + m_error = error; + if (!errorString.isNull()) + m_errorString = errorString; +} + +/*! + Clears the previously set arguments. +*/ +void UpdateOperation::clear() +{ + m_arguments.clear(); +} + +/*! + Returns the list of files that are scheduled for later deletion. +*/ +QStringList UpdateOperation::filesForDelayedDeletion() const +{ + return m_delayedDeletionFiles; +} + +/*! + Returns the package manager core this operation belongs to. +*/ +QInstaller::PackageManagerCore *UpdateOperation::packageManager() const +{ + return m_core; +} + +/*! + Registers a list of \a files to be deleted later once the application was restarted and the + file or files are not used anymore. +*/ +void UpdateOperation::registerForDelayedDeletion(const QStringList &files) +{ + m_delayedDeletionFiles << files; +} + +/*! + Tries to delete \a file. If \a file cannot be deleted, it is registered for delayed deletion. + + If a backup copy of the file cannot be created, returns \c false and displays the error + message specified by \a errorString. +*/ +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 = tr("Renaming file \"%1\" to \"%2\" failed: %3").arg( + QDir::toNativeSeparators(file), QDir::toNativeSeparators(backup), f.errorString()); + return false; + } + registerForDelayedDeletion(QStringList(backup)); + return true; +} + +/*! + \fn virtual void KDUpdater::UpdateOperation::backup() = 0; + + Subclasses must implement this function to back up any data before performing the action. +*/ + +/*! + \fn virtual bool KDUpdater::UpdateOperation::performOperation() = 0; + + Subclasses must implement this function to perform the update operation. + + Returns \c true if the operation is successful. +*/ + +/*! + \fn virtual bool KDUpdater::UpdateOperation::undoOperation() = 0; + + Subclasses must implement this function to perform the undo of the update operation. + + Returns \c true if the operation is successful. +*/ + +/*! + \fn virtual bool KDUpdater::UpdateOperation::testOperation() = 0; + + Subclasses must implement this function to perform the test operation. + + Returns \c true if the operation is successful. +*/ + +/*! + Saves operation arguments and values as an XML document and returns the + document. You can override this method to store your + own extra-data. Extra-data can be any data that you need to store to perform or undo the + operation. The default implementation is taking care of arguments and values set via + UpdateOperation::setValue(). +*/ +QDomDocument UpdateOperation::toXml() const +{ + QDomDocument doc; + QDomElement root = doc.createElement(QLatin1String("operation")); + doc.appendChild(root); + + QDomElement args = doc.createElement(QLatin1String("arguments")); + const QString target = m_core ? m_core->value(QInstaller::scTargetDir) : QString(); + Q_FOREACH (const QString &s, arguments()) { + QDomElement arg = doc.createElement(QLatin1String("argument")); + arg.appendChild(doc.createTextNode(QInstaller::replacePath(s, target, + QLatin1String(QInstaller::scRelocatable)))); + args.appendChild(arg); + } + root.appendChild(args); + if (m_values.isEmpty()) + return doc; + + // append all values set with setValue + QDomElement values = doc.createElement(QLatin1String("values")); + for (QVariantMap::const_iterator it = m_values.constBegin(); it != m_values.constEnd(); ++it) { + // the installer can't be put into XML, ignore + if (it.key() == QLatin1String("installer")) + continue; + + QDomElement value = doc.createElement(QLatin1String("value")); + QVariant variant = it.value(); + value.setAttribute(QLatin1String("name"), it.key()); + value.setAttribute(QLatin1String("type"), QLatin1String(variant.typeName())); + + if (variant.type() != QVariant::List && variant.type() != QVariant::StringList + && variant.canConvert(QVariant::String)) { + // it can convert to string? great! + value.appendChild(doc.createTextNode(QInstaller::replacePath(variant.toString(), + target, QLatin1String(QInstaller::scRelocatable)))); + } else { + // no? then we have to go the hard way... + if (variant.type() == QVariant::StringList) { + QStringList list = variant.toStringList(); + for (int i = 0; i < list.count(); ++i) { + list[i] = QInstaller::replacePath(list.at(i), target, + QLatin1String(QInstaller::scRelocatable)); + } + variant = QVariant::fromValue(list); + } + 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 operation arguments and values from the XML document \a doc. Returns \c true on + success, otherwise \c false. \note: Clears all previously set values and arguments. +*/ +bool UpdateOperation::fromXml(const QDomDocument &doc) +{ + QString target = QCoreApplication::applicationDirPath(); + QInstaller::isInBundle(target, &target); // Does not change target on non OSX platforms. + + 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 << QInstaller::replacePath(e.text(), QLatin1String(QInstaller::scRelocatable), + target); + } + } + setArguments(args); + + m_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; + if (t == QVariant::StringList) { + QStringList list = var.toStringList(); + for (int i = 0; i < list.count(); ++i) { + list[i] = QInstaller::replacePath(list.at(i), + QLatin1String(QInstaller::scRelocatable), target); + } + var = QVariant::fromValue(list); + } + } + + m_values[name] = var; + } + + return true; +} + +/*! + \overload + + Restores operation arguments and values from the XML file at path \a xml. Returns \c true on + success, otherwise \c false. +*/ +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/src/libs/kdtools/updateoperation.h b/src/libs/kdtools/updateoperation.h new file mode 100644 index 000000000..17c399c6f --- /dev/null +++ b/src/libs/kdtools/updateoperation.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef KD_UPDATER_UPDATE_OPERATION_H +#define KD_UPDATER_UPDATE_OPERATION_H + +#include "updater.h" + +#include +#include +#include +#include + +namespace QInstaller { +class PackageManagerCore; +} + +namespace KDUpdater { + +class KDTOOLS_EXPORT UpdateOperation +{ + Q_DECLARE_TR_FUNCTIONS(UpdateOperation) + +public: + enum Error { + NoError = 0, + InvalidArguments = 1, + UserDefinedError = 128 + }; + + explicit UpdateOperation(QInstaller::PackageManagerCore *core); + 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); + QStringList arguments() const; + QString argumentKeyValue(const QString & key, const QString &defaultValue = QString()) const; + void clear(); + QString errorString() const; + int error() const; + QStringList filesForDelayedDeletion() const; + + QInstaller::PackageManagerCore *packageManager() const; + + virtual void backup() = 0; + virtual bool performOperation() = 0; + virtual bool undoOperation() = 0; + virtual bool testOperation() = 0; + + virtual QDomDocument toXml() const; + virtual bool fromXml(const QString &xml); + virtual bool fromXml(const QDomDocument &doc); + +protected: + void setName(const QString &name); + 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); + bool checkArgumentCount(int minArgCount, int maxArgCount, const QString &argDescription = QString()); + bool checkArgumentCount(int argCount); + +private: + QString m_name; + QStringList m_arguments; + QString m_errorString; + int m_error; + QVariantMap m_values; + QStringList m_delayedDeletionFiles; + QInstaller::PackageManagerCore *m_core; +}; + +} // namespace KDUpdater + +#endif // KD_UPDATER_UPDATE_OPERATION_H diff --git a/src/libs/kdtools/updateoperationfactory.cpp b/src/libs/kdtools/updateoperationfactory.cpp new file mode 100644 index 000000000..b045532ec --- /dev/null +++ b/src/libs/kdtools/updateoperationfactory.cpp @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "updateoperationfactory.h" + +#include "packagemanagercore.h" +#include "updateoperations.h" + +using namespace KDUpdater; + +/*! + \inmodule kdupdater + \class KDUpdater::UpdateOperationFactory + \brief The UpdateOperationFactory class is used to create update operations based on their name. + + This class acts as a factory for \c 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 instance() method. + + The following operations are registered by default: + \list + \li Copy operation + \li Move operation + \li Delete operation + \li Mkdir operation + \li Rmdir operation + \li AppendFile operation + \li PrependFile operation + \endlist +*/ + +/*! + \obsolete + \fn void KDUpdater::UpdateOperationFactory::registerUpdateOperation(const QString &name) + + Registers a new update operation with the factory based on \a name. When create() is called + with that \a name, the update operation is constructed using its default constructor. + + Deprecated. Use registerProduct() instead. +*/ + +/*! + Returns the UpdateOperationFactory instance. The instance is created if needed. +*/ +UpdateOperationFactory &UpdateOperationFactory::instance() +{ + static UpdateOperationFactory theFactory; + return theFactory; +} + +/*! + Constructor +*/ +UpdateOperationFactory::UpdateOperationFactory() +{ + // Register the default update operation set + registerUpdateOperation(QLatin1String("Copy")); + registerUpdateOperation(QLatin1String("Move")); + registerUpdateOperation(QLatin1String("Delete")); + registerUpdateOperation(QLatin1String("Mkdir")); + registerUpdateOperation(QLatin1String("Rmdir")); + registerUpdateOperation(QLatin1String("AppendFile")); + registerUpdateOperation(QLatin1String("PrependFile")); +} diff --git a/src/libs/kdtools/updateoperationfactory.h b/src/libs/kdtools/updateoperationfactory.h new file mode 100644 index 000000000..22b0c7f58 --- /dev/null +++ b/src/libs/kdtools/updateoperationfactory.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef KD_UPDATER_UPDATE_OPERATION_FACTORY_H +#define KD_UPDATER_UPDATE_OPERATION_FACTORY_H + +#include "genericfactory.h" + +#include "updater.h" + +namespace QInstaller { +class PackageManagerCore; +} + +namespace KDUpdater { + +class UpdateOperation; + +class KDTOOLS_EXPORT UpdateOperationFactory : public KDGenericFactory +{ + Q_DISABLE_COPY(UpdateOperationFactory) + +public: + static UpdateOperationFactory &instance(); + + template + void registerUpdateOperation(const QString &name) + { + registerProduct(name); + } + +private: + UpdateOperationFactory(); +}; + +} // namespace KDUpdater + +#endif // KD_UPDATER_UPDATE_OPERATION_FACTORY_H diff --git a/src/libs/kdtools/updateoperations.cpp b/src/libs/kdtools/updateoperations.cpp new file mode 100644 index 000000000..f72bd100c --- /dev/null +++ b/src/libs/kdtools/updateoperations.cpp @@ -0,0 +1,786 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "updateoperations.h" +#include "errors.h" +#include "fileutils.h" + +#include +#include +#include +#include +#include + +#include + +using namespace KDUpdater; + +static QString errnoToQString(int error) +{ +#if defined(Q_OS_WIN) && !defined(Q_CC_MINGW) + char msg[128]; + if (strerror_s(msg, sizeof msg, error) != 0) + return QString::fromLocal8Bit(msg); + return QString(); +#else + return QString::fromLocal8Bit(strerror(error)); +#endif +} + +static bool removeDirectory(const QString &path, QString *errorString, bool force) +{ + Q_ASSERT(errorString); + + QDir dir = path; + const QFileInfoList entries = dir.entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries | QDir::Hidden); + foreach (const QFileInfo &entry, entries) { + if (entry.isDir() && (!entry.isSymLink())) + removeDirectory(entry.filePath(), errorString, force); + else if (force && (!QFile(entry.filePath()).remove())) + return false; + } + + // even remove some hidden, OS-created files in there + QInstaller::removeSystemGeneratedFiles(path); + + errno = 0; + const bool success = dir.rmdir(path); + if (errno) + *errorString = errnoToQString(errno); + return success; +} + +/* + * \internal + * Returns a filename for a temporary file based on \a templateName + */ +static QString backupFileName(const QString &templateName) +{ + QTemporaryFile file(templateName); + file.open(); + const QString name = file.fileName(); + file.close(); + file.remove(); + return name; +} + +//////////////////////////////////////////////////////////////////////////// +// KDUpdater::CopyOperation +//////////////////////////////////////////////////////////////////////////// + +CopyOperation::CopyOperation(QInstaller::PackageManagerCore *core) + : UpdateOperation(core) +{ + setName(QLatin1String("Copy")); +} + +CopyOperation::~CopyOperation() +{ + deleteFileNowOrLater(value(QLatin1String("backupOfExistingDestination")).toString()); +} + +QString CopyOperation::sourcePath() +{ + return arguments().first(); +} + +QString CopyOperation::destinationPath() +{ + QString destination = arguments().last(); + + // if the target is a directory use the source filename to complete the destination path + if (QFileInfo(destination).isDir()) + destination = QDir(destination).filePath(QFileInfo(sourcePath()).fileName()); + return destination; +} + + +void CopyOperation::backup() +{ + QString destination = destinationPath(); + + if (!QFile::exists(destination)) { + clearValue(QLatin1String("backupOfExistingDestination")); + return; + } + + setValue(QLatin1String("backupOfExistingDestination"), backupFileName(destination)); + + // race condition: The backup file could get created by another process right now. But this is the same + // in QFile::copy... + if (!QFile::rename(destination, value(QLatin1String("backupOfExistingDestination")).toString())) + setError(UserDefinedError, tr("Cannot backup file \"%1\".").arg(QDir::toNativeSeparators(destination))); +} + +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 + if (!checkArgumentCount(2)) + return false; + + QString source = sourcePath(); + QString destination = destinationPath(); + + QFile sourceFile(source); + if (!sourceFile.exists()) { + setError(UserDefinedError); + setErrorString(tr("Cannot copy a non-existent file: %1").arg(QDir::toNativeSeparators(source))); + return false; + } + // If destination file exists, we cannot use QFile::copy() because it does not overwrite an existing + // file. So we remove the destination file. + QFile destinationFile(destination); + if (destinationFile.exists()) { + if (!destinationFile.remove()) { + setError(UserDefinedError); + setErrorString(tr("Cannot remove file \"%1\": %2").arg( + QDir::toNativeSeparators(destination), destinationFile.errorString())); + return false; + } + } + + const bool copied = sourceFile.copy(destination); + if (!copied) { + setError(UserDefinedError); + setErrorString(tr("Cannot copy file \"%1\" to \"%2\": %3").arg( + QDir::toNativeSeparators(source), QDir::toNativeSeparators(destination), + sourceFile.errorString())); + } + return copied; +} + +bool CopyOperation::undoOperation() +{ + QString source = sourcePath(); + QString destination = destinationPath(); + + // if the target is a directory use the source filename to complete the destination path + if (QFileInfo(destination).isDir()) + destination = destination + QDir::separator() + QFileInfo(source).fileName(); + + QFile destFile(destination); + // first remove the dest + if (destFile.exists() && !destFile.remove()) { + setError(UserDefinedError, tr("Cannot delete file \"%1\": %2").arg( + QDir::toNativeSeparators(destination), destFile.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 backupFile(value(QLatin1String("backupOfExistingDestination")).toString()); + // otherwise we have to copy the backup back: + const bool success = backupFile.rename(destination); + if (!success) + setError(UserDefinedError, tr("Cannot restore backup file into \"%1\": %2").arg( + QDir::toNativeSeparators(destination), backupFile.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(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; +} + + +//////////////////////////////////////////////////////////////////////////// +// KDUpdater::MoveOperation +//////////////////////////////////////////////////////////////////////////// + +MoveOperation::MoveOperation(QInstaller::PackageManagerCore *core) + : UpdateOperation(core) +{ + 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... + if (!QFile::rename(dest, value(QLatin1String("backupOfExistingDestination")).toString())) + setError(UserDefinedError, tr("Cannot backup file \"%1\".").arg(QDir::toNativeSeparators(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 + if (!checkArgumentCount(2)) + return false; + + const QStringList args = arguments(); + const QString dest = args.at(1); + // 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("Cannot remove file \"%1\": %2").arg( + QDir::toNativeSeparators(dest), file.errorString())); + return false; + } + } + + // Copy source to destination. + QFile file(args.at(0)); + if (!file.copy(dest)) { + setError(UserDefinedError); + setErrorString(tr("Cannot copy file \"%1\" to \"%2\": %3").arg(QDir::toNativeSeparators(file.fileName()), + QDir::toNativeSeparators(dest), file.errorString())); + return false; + } + return deleteFileNowOrLater(file.fileName()); +} + +bool MoveOperation::undoOperation() +{ + const QStringList args = arguments(); + const QString dest = args.last(); + // first: copy back the destination to source + QFile destF(dest); + if (!destF.copy(args.first())) { + setError(UserDefinedError, tr("Cannot copy file \"%1\" to \"%2\": %3").arg( + QDir::toNativeSeparators(dest), QDir::toNativeSeparators(args.first()), destF.errorString())); + return false; + } + + // second: delete the move destination + if (!deleteFileNowOrLater(dest)) { + setError(UserDefinedError, tr("Cannot remove file \"%1\".").arg(QDir::toNativeSeparators(dest))); + 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( + QDir::toNativeSeparators(dest), backupF.errorString())); + + return success; +} + +bool MoveOperation::testOperation() +{ + // TODO + return true; +} + + +//////////////////////////////////////////////////////////////////////////// +// KDUpdater::DeleteOperation +//////////////////////////////////////////////////////////////////////////// + +DeleteOperation::DeleteOperation(QInstaller::PackageManagerCore *core) + : UpdateOperation(core) +{ + 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); + if (!file.copy(value(QLatin1String("backupOfExistingFile")).toString())) + setError(UserDefinedError, tr("Cannot create backup of file \"%1\": %2").arg( + QDir::toNativeSeparators(fileName), file.errorString())); +} + +bool DeleteOperation::performOperation() +{ + // Requires only one parameter. That is the name of the file to remove. + if (!checkArgumentCount(1)) + return false; + + return deleteFileNowOrLater(arguments().at(0)); +} + +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( + QDir::toNativeSeparators(fileName), backupF.errorString())); + return success; +} + +bool DeleteOperation::testOperation() +{ + // TODO + return true; +} + +/*! + \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(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(QInstaller::PackageManagerCore *core) + : UpdateOperation(core) +{ + setName(QLatin1String("Mkdir")); +} + +void MkdirOperation::backup() +{ + QString path = arguments().first(); + path.replace(QLatin1Char('\\'), QLatin1Char('/')); + + 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(QLatin1Char('/'), 0, ++end); + createdDir = QDir(p); + if (!createdDir.exists()) + break; + 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 path which should be created + if (!checkArgumentCount(1)) + return false; + + const QString dirName = arguments().at(0); + const bool created = QDir::root().mkpath(dirName); + if (!created) { + setError(UserDefinedError); + setErrorString(tr("Cannot create directory \"%1\": %2").arg( + QDir::toNativeSeparators(dirName), tr("Unknown error."))); + } + return created; +} + +bool MkdirOperation::undoOperation() +{ + Q_ASSERT(arguments().count() == 1); + + QString createdDirValue = value(QLatin1String("createddir")).toString(); + if (createdDirValue.isEmpty()) + createdDirValue = arguments().first(); + QDir createdDir = QDir(createdDirValue); + const bool forceremoval = QVariant(value(QLatin1String("forceremoval"))).toBool(); + + // Since refactoring we know the mkdir operation which is creating the target path. If we do a full + // uninstall prevent removing the full path including target, instead remove the target only. (QTIFW-46) + if (hasValue(QLatin1String("uninstall-only")) && value(QLatin1String("uninstall-only")).toBool()) + createdDir = QDir(arguments().first()); + + if (createdDir == QDir::root()) + return true; + + if (!createdDir.exists()) + return true; + + QString errorString; + + const bool result = removeDirectory(createdDir.path(), &errorString, forceremoval); + + if (!result) { + if (errorString.isEmpty()) + setError(UserDefinedError, tr("Cannot remove directory \"%1\": %2").arg( + QDir::toNativeSeparators(createdDir.path()), errorString)); + else + setError(UserDefinedError, tr("Cannot remove directory \"%1\": %2").arg( + QDir::toNativeSeparators(createdDir.path()), errnoToQString(errno))); + } + return result; +} + +bool KDUpdater::MkdirOperation::testOperation() +{ + // TODO + return true; +} + + +//////////////////////////////////////////////////////////////////////////// +// KDUpdater::RmdirOperation +//////////////////////////////////////////////////////////////////////////// + +RmdirOperation::RmdirOperation(QInstaller::PackageManagerCore *core) + : UpdateOperation(core) +{ + setName(QLatin1String("Rmdir")); + setValue(QLatin1String("removed"), false); +} + +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. + if (!checkArgumentCount(1)) + return false; + + const QString firstArg = arguments().at(0); + QDir dir(firstArg); + if (!dir.exists()) { + setError(UserDefinedError); + setErrorString(tr("Cannot remove directory \"%1\": %2").arg( + QDir::toNativeSeparators(firstArg), tr("The directory does not exist."))); + return false; + } + + errno = 0; + const bool removed = dir.rmdir(firstArg); + setValue(QLatin1String("removed"), removed); + if (!removed) { + setError(UserDefinedError); + setErrorString(tr("Cannot remove directory \"%1\": %2").arg( + QDir::toNativeSeparators(firstArg), errnoToQString(errno))); + } + return removed; +} + +bool RmdirOperation::undoOperation() +{ + if (!value(QLatin1String("removed")).toBool()) + return true; + + errno = 0; + const QFileInfo fi(arguments().first()); + const bool success = fi.dir().mkdir(fi.fileName()); + if( !success) + setError(UserDefinedError, tr("Cannot recreate directory \"%1\": %2").arg( + QDir::toNativeSeparators(fi.fileName()), errnoToQString(errno))); + + return success; +} + +bool RmdirOperation::testOperation() +{ + // TODO + return true; +} + + +//////////////////////////////////////////////////////////////////////////// +// KDUpdater::AppendFileOperation +//////////////////////////////////////////////////////////////////////////// + +AppendFileOperation::AppendFileOperation(QInstaller::PackageManagerCore *core) + : UpdateOperation(core) +{ + setName(QLatin1String("AppendFile")); +} + +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( + QDir::toNativeSeparators(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. + if (!checkArgumentCount(2)) + return false; + + const QStringList args = this->arguments(); + const QString fName = args.at(0); + 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 + bool error = false; + const QString newName = backupFileName(fName); + + if (!QFile::rename(fName, newName)) + error = true; + + if (!error && !QFile::copy(newName, fName)) { + error = true; + QFile::rename(newName, fName); + } + + if (!error && !file.open(QFile::Append)) { + error = true; + deleteFileNowOrLater(newName); + } + + if (error) { + setError(UserDefinedError); + setErrorString(tr("Cannot open file \"%1\" for writing: %2").arg( + QDir::toNativeSeparators(file.fileName()), file.errorString())); + return false; + } + deleteFileNowOrLater(newName); + } + + QTextStream ts(&file); + ts << args.at(1); + 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( + QDir::toNativeSeparators(filename))); + return false; + } + + const bool removed = deleteFileNowOrLater(filename); + if (!removed) { + setError(UserDefinedError, tr("Cannot restore backup file for \"%1\".").arg( + QDir::toNativeSeparators(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("Cannot restore backup file for \"%1\": %2").arg( + QDir::toNativeSeparators(filename), backupFile.errorString())); + return success; +} + +bool AppendFileOperation::testOperation() +{ + // TODO + return true; +} + + +//////////////////////////////////////////////////////////////////////////// +// KDUpdater::PrependFileOperation +//////////////////////////////////////////////////////////////////////////// + +PrependFileOperation::PrependFileOperation(QInstaller::PackageManagerCore *core) + : UpdateOperation(core) +{ + setName(QLatin1String("PrependFile")); +} + +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( + QDir::toNativeSeparators(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. + if (!checkArgumentCount(2)) + return false; + + const QStringList args = this->arguments(); + const QString fName = args.at(0); + // Load the file first. + QFile file(fName); + if (!file.open(QFile::ReadOnly)) { + setError(UserDefinedError); + setErrorString(tr("Cannot open file \"%1\" for reading: %2").arg( + QDir::toNativeSeparators(file.fileName()), file.errorString())); + return false; + } + + // TODO: fix this, use a text stream + QString fContents(QLatin1String(file.readAll())); + file.close(); + + // Prepend text to the file text + fContents = args.at(1) + 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("Cannot open file \"%1\" for writing: %2").arg( + QDir::toNativeSeparators(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(QDir::toNativeSeparators(filename))); + return false; + } + + if (!deleteFileNowOrLater(filename)) { + setError(UserDefinedError, + tr("Cannot restore backup file for \"%1\".").arg(QDir::toNativeSeparators(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( + QDir::toNativeSeparators(filename), backupF.errorString())); + + return success; +} + +bool PrependFileOperation::testOperation() +{ + // TODO + return true; +} diff --git a/src/libs/kdtools/updateoperations.h b/src/libs/kdtools/updateoperations.h new file mode 100644 index 000000000..b0a49a08d --- /dev/null +++ b/src/libs/kdtools/updateoperations.h @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef KD_UPDATER_UPDATE_OPERATIONS_H +#define KD_UPDATER_UPDATE_OPERATIONS_H + +#include "updateoperation.h" + +namespace KDUpdater { + +class KDTOOLS_EXPORT CopyOperation : public UpdateOperation +{ +public: + explicit CopyOperation(QInstaller::PackageManagerCore *core = 0); + ~CopyOperation(); + + void backup(); + bool performOperation(); + bool undoOperation(); + bool testOperation(); + + QDomDocument toXml() const; +private: + QString sourcePath(); + QString destinationPath(); +}; + +class KDTOOLS_EXPORT MoveOperation : public UpdateOperation +{ +public: + explicit MoveOperation(QInstaller::PackageManagerCore *core = 0); + ~MoveOperation(); + + void backup(); + bool performOperation(); + bool undoOperation(); + bool testOperation(); +}; + +class KDTOOLS_EXPORT DeleteOperation : public UpdateOperation +{ +public: + explicit DeleteOperation(QInstaller::PackageManagerCore *core = 0); + ~DeleteOperation(); + + void backup(); + bool performOperation(); + bool undoOperation(); + bool testOperation(); + + QDomDocument toXml() const; +}; + +class KDTOOLS_EXPORT MkdirOperation : public UpdateOperation +{ +public: + explicit MkdirOperation(QInstaller::PackageManagerCore *core = 0); + + void backup(); + bool performOperation(); + bool undoOperation(); + bool testOperation(); +}; + +class KDTOOLS_EXPORT RmdirOperation : public UpdateOperation +{ +public: + RmdirOperation(QInstaller::PackageManagerCore *core = 0); + + void backup(); + bool performOperation(); + bool undoOperation(); + bool testOperation(); +}; + +class KDTOOLS_EXPORT AppendFileOperation : public UpdateOperation +{ +public: + explicit AppendFileOperation(QInstaller::PackageManagerCore *core = 0); + + void backup(); + bool performOperation(); + bool undoOperation(); + bool testOperation(); +}; + +class KDTOOLS_EXPORT PrependFileOperation : public UpdateOperation +{ +public: + explicit PrependFileOperation(QInstaller::PackageManagerCore *core = 0); + + void backup(); + bool performOperation(); + bool undoOperation(); + bool testOperation(); +}; + +} // namespace KDUpdater + +#endif // KD_UPDATER_UPDATE_OPERATIONS_H diff --git a/src/libs/kdtools/updater.h b/src/libs/kdtools/updater.h new file mode 100644 index 000000000..bd873227a --- /dev/null +++ b/src/libs/kdtools/updater.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef KD_UPDATER_H +#define KD_UPDATER_H + +#include "kdtoolsglobal.h" + +namespace KDUpdater +{ + enum Error + { + ENoError = 0, + ECannotStartTask, + ECannotPauseTask, + ECannotResumeTask, + ECannotStopTask, + EUnknown + }; + KDTOOLS_EXPORT int compareVersion(const QString &v1, const QString &v2); +} + +#endif diff --git a/src/libs/kdtools/updatesinfo.cpp b/src/libs/kdtools/updatesinfo.cpp new file mode 100644 index 000000000..44539171b --- /dev/null +++ b/src/libs/kdtools/updatesinfo.cpp @@ -0,0 +1,250 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "updatesinfo_p.h" + +#include +#include +#include +#include + +using namespace KDUpdater; + +UpdatesInfoData::UpdatesInfoData() + : error(UpdatesInfo::NotYetReadError) +{ +} + +UpdatesInfoData::~UpdatesInfoData() +{ +} + +void UpdatesInfoData::setInvalidContentError(const QString &detail) +{ + error = UpdatesInfo::InvalidContentError; + errorMessage = tr("Updates.xml contains invalid content: %1").arg(detail); +} + +void UpdatesInfoData::parseFile(const QString &updateXmlFile) +{ + QFile file(updateXmlFile); + if (!file.open(QFile::ReadOnly)) { + error = UpdatesInfo::CouldNotReadUpdateInfoFileError; + errorMessage = tr("Cannot read \"%1\"").arg(updateXmlFile); + return; + } + + QDomDocument doc; + QString parseErrorMessage; + int parseErrorLine, 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++) { + const QDomElement childE = childNodes.at(i).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("PackageUpdate")) { + if (!parsePackageUpdateElement(childE)) + return; //error handled in subroutine + } + } + + if (applicationName.isEmpty()) { + setInvalidContentError(tr("ApplicationName element is missing.")); + return; + } + + if (applicationVersion.isEmpty()) { + setInvalidContentError(tr("ApplicationVersion element is missing.")); + return; + } + + errorMessage.clear(); + error = UpdatesInfo::NoError; +} + +bool UpdatesInfoData::parsePackageUpdateElement(const QDomElement &updateE) +{ + if (updateE.isNull()) + return false; + + UpdateInfo info; + for (int i = 0; i < updateE.childNodes().count(); i++) { + QDomElement childE = updateE.childNodes().at(i).toElement(); + if (childE.isNull()) + continue; + + if (childE.tagName() == QLatin1String("ReleaseNotes")) { + info.data[childE.tagName()] = QUrl(childE.text()); + } else if (childE.tagName() == QLatin1String("Licenses")) { + QHash 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 if (childE.tagName() == QLatin1String("Version")) { + info.data.insert(QLatin1String("inheritVersionFrom"), + childE.attribute(QLatin1String("inheritVersionFrom"))); + info.data[childE.tagName()] = childE.text(); + } else if (childE.tagName() == QLatin1String("DisplayName")) { + processLocalizedTag(childE, info.data); + } else if (childE.tagName() == QLatin1String("Description")) { + processLocalizedTag(childE, info.data); + } else if (childE.tagName() == QLatin1String("UpdateFile")) { + info.data[QLatin1String("CompressedSize")] = childE.attribute(QLatin1String("CompressedSize")); + info.data[QLatin1String("UncompressedSize")] = childE.attribute(QLatin1String("UncompressedSize")); + } else { + info.data[childE.tagName()] = childE.text(); + } + } + + if (!info.data.contains(QLatin1String("Name"))) { + setInvalidContentError(tr("PackageUpdate element without Name")); + return false; + } + if (!info.data.contains(QLatin1String("Version"))) { + setInvalidContentError(tr("PackageUpdate element without Version")); + return false; + } + if (!info.data.contains(QLatin1String("ReleaseDate"))) { + setInvalidContentError(tr("PackageUpdate element without ReleaseDate")); + return false; + } + + updateInfoList.append(info); + return true; +} + +void UpdatesInfoData::processLocalizedTag(const QDomElement &childE, QHash &info) const +{ + QString languageAttribute = childE.attribute(QLatin1String("xml:lang")).toLower(); + if (!info.contains(childE.tagName()) && (languageAttribute.isEmpty())) + info[childE.tagName()] = childE.text(); + + // overwrite default if we have a language specific description + if (QLocale().name().startsWith(languageAttribute, Qt::CaseInsensitive)) + info[childE.tagName()] = childE.text(); +} + + +// +// UpdatesInfo +// +UpdatesInfo::UpdatesInfo() + : d(new UpdatesInfoData) +{ +} + +UpdatesInfo::~UpdatesInfo() +{ +} + +bool UpdatesInfo::isValid() const +{ + return d->error == NoError; +} + +QString UpdatesInfo::errorString() const +{ + return d->errorMessage; +} + +void 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 UpdatesInfo::fileName() const +{ + return d->updateXmlFile; +} + +QString UpdatesInfo::applicationName() const +{ + return d->applicationName; +} + +QString UpdatesInfo::applicationVersion() const +{ + return d->applicationVersion; +} + +int UpdatesInfo::updateInfoCount() const +{ + return d->updateInfoList.count(); +} + +UpdateInfo UpdatesInfo::updateInfo(int index) const +{ + if (index < 0 || index >= d->updateInfoList.count()) + return UpdateInfo(); + return d->updateInfoList.at(index); +} + +QList UpdatesInfo::updatesInfo() const +{ + return d->updateInfoList; +} diff --git a/src/libs/kdtools/updatesinfo_p.h b/src/libs/kdtools/updatesinfo_p.h new file mode 100644 index 000000000..831440a62 --- /dev/null +++ b/src/libs/kdtools/updatesinfo_p.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef KD_UPDATER_UPDATE_INFO_H +#define KD_UPDATER_UPDATE_INFO_H + +#include "updater.h" +#include "updatesinfodata_p.h" + +#include +#include +#include + +// They are not a part of the public API +// Classes and structures in this header file are for internal use only but still exported for auto tests. + +namespace KDUpdater { + +struct KDTOOLS_EXPORT UpdateInfo +{ + QHash data; +}; + +class KDTOOLS_EXPORT UpdatesInfo +{ +public: + enum Error + { + NoError = 0, + NotYetReadError, + CouldNotReadUpdateInfoFileError, + InvalidXmlError, + InvalidContentError + }; + + UpdatesInfo(); + ~UpdatesInfo(); + + bool isValid() const; + + Error error() const; + QString errorString() const; + + QString fileName() const; + void setFileName(const QString &updateXmlFile); + + QString applicationName() const; + QString applicationVersion() const; + + int updateInfoCount() const; + UpdateInfo updateInfo(int index) const; + QList updatesInfo() const; + +private: + QSharedDataPointer d; +}; + +} // namespace KDUpdater + +#endif // KD_UPDATER_UPDATE_INFO_H diff --git a/src/libs/kdtools/updatesinfodata_p.h b/src/libs/kdtools/updatesinfodata_p.h new file mode 100644 index 000000000..402c25567 --- /dev/null +++ b/src/libs/kdtools/updatesinfodata_p.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef KD_UPDATER_UPDATE_INFO_DATA_H +#define KD_UPDATER_UPDATE_INFO_DATA_H + +#include +#include + +QT_FORWARD_DECLARE_CLASS(QDomElement) + +namespace KDUpdater { + +struct UpdateInfo; + +struct UpdatesInfoData : public QSharedData +{ + Q_DECLARE_TR_FUNCTIONS(KDUpdater::UpdatesInfoData) + +public: + UpdatesInfoData(); + ~UpdatesInfoData(); + + int error; + QString errorMessage; + QString updateXmlFile; + QString applicationName; + QString applicationVersion; + QList updateInfoList; + + void parseFile(const QString &updateXmlFile); + bool parsePackageUpdateElement(const QDomElement &updateE); + + void setInvalidContentError(const QString &detail); + +private: + void processLocalizedTag(const QDomElement &childE, QHash &info) const; +}; + +} // namespace KDUpdater + +#endif // KD_UPDATER_UPDATE_INFO_DATA_H diff --git a/src/sdk/installerbase.cpp b/src/sdk/installerbase.cpp index 03fb98f8b..0557f36a2 100644 --- a/src/sdk/installerbase.cpp +++ b/src/sdk/installerbase.cpp @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include #include #include @@ -53,8 +53,8 @@ #include #include -#include -#include +#include +#include #include #include diff --git a/src/sdk/main.cpp b/src/sdk/main.cpp index b80c10a6e..feea95a37 100644 --- a/src/sdk/main.cpp +++ b/src/sdk/main.cpp @@ -40,7 +40,7 @@ #include "updatechecker.h" #include -#include +#include #include #include diff --git a/src/sdk/updatechecker.cpp b/src/sdk/updatechecker.cpp index 35e2dda88..ea0427098 100644 --- a/src/sdk/updatechecker.cpp +++ b/src/sdk/updatechecker.cpp @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include -- cgit v1.2.3