diff options
Diffstat (limited to 'src/sdk')
-rw-r--r-- | src/sdk/commandlineparser.cpp | 109 | ||||
-rw-r--r-- | src/sdk/commandlineparser.h | 56 | ||||
-rw-r--r-- | src/sdk/console.h | 98 | ||||
-rw-r--r-- | src/sdk/console_win.cpp | 142 | ||||
-rw-r--r-- | src/sdk/constants.h | 62 | ||||
-rw-r--r-- | src/sdk/installerbase.cpp | 633 | ||||
-rw-r--r-- | src/sdk/installerbase.h | 63 | ||||
-rw-r--r-- | src/sdk/installerbase_p.cpp | 327 | ||||
-rw-r--r-- | src/sdk/installerbase_p.h | 92 | ||||
-rw-r--r-- | src/sdk/installerbasecommons.cpp | 508 | ||||
-rw-r--r-- | src/sdk/installerbasecommons.h | 102 | ||||
-rw-r--r-- | src/sdk/main.cpp | 203 | ||||
-rw-r--r-- | src/sdk/sdk.pro | 46 | ||||
-rw-r--r-- | src/sdk/sdkapp.h | 115 | ||||
-rw-r--r-- | src/sdk/settingsdialog.cpp | 36 | ||||
-rw-r--r-- | src/sdk/settingsdialog.h | 21 | ||||
-rw-r--r-- | src/sdk/settingsdialog.ui | 545 | ||||
-rw-r--r-- | src/sdk/tabcontroller.cpp | 35 | ||||
-rw-r--r-- | src/sdk/tabcontroller.h | 21 | ||||
-rw-r--r-- | src/sdk/translations/ja_jp.ts | 22 | ||||
-rw-r--r-- | src/sdk/updatechecker.cpp | 118 | ||||
-rw-r--r-- | src/sdk/updatechecker.h | 50 |
22 files changed, 1353 insertions, 2051 deletions
diff --git a/src/sdk/commandlineparser.cpp b/src/sdk/commandlineparser.cpp new file mode 100644 index 000000000..9c4200b3e --- /dev/null +++ b/src/sdk/commandlineparser.cpp @@ -0,0 +1,109 @@ +/************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#include "commandlineparser.h" + +#include "constants.h" + +namespace CommandLineOptions { +const char KeyValue[] = "Key=Value"; +} // namespace CommandLineOptions + +CommandLineParser::CommandLineParser() +{ + m_parser.addHelpOption(); + + m_parser.addOption(QCommandLineOption(QLatin1String(CommandLineOptions::Version), + QLatin1String("Displays version information."))); + + m_parser.addOption(QCommandLineOption(QLatin1String(CommandLineOptions::FrameworkVersion), + QLatin1String("Displays the version of the Qt Installer Framework."))); + + m_parser.addOption(QCommandLineOption(QStringList() + << QLatin1String(CommandLineOptions::VerboseShort) + << QLatin1String(CommandLineOptions::VerboseLong), + QLatin1String("Verbose mode. Prints out more information."))); + + m_parser.addOption(QCommandLineOption(QLatin1String(CommandLineOptions::Proxy), + QLatin1String("Use system proxy on Windows and OS X. This option has no effect on Linux."))); + + m_parser.addOption(QCommandLineOption(QLatin1String(CommandLineOptions::Script), + QLatin1String("Execute the script given as argument."), QLatin1String("file"))); + + m_parser.addOption(QCommandLineOption(QLatin1String(CommandLineOptions::CheckUpdates), + QLatin1String("Check for updates and return an XML description."))); + + m_parser.addOption(QCommandLineOption(QLatin1String(CommandLineOptions::Updater), + QLatin1String("Start application in updater mode."))); + + m_parser.addOption(QCommandLineOption(QLatin1String(CommandLineOptions::ManagePackages), + QLatin1String("Start application in package manager mode."))); + + m_parser.addOption(QCommandLineOption(QLatin1String(CommandLineOptions::NoForceInstallation), + QLatin1String("Allow deselecting components that are marked as forced."))); + + m_parser.addOption(QCommandLineOption(QLatin1String(CommandLineOptions::ShowVirtualComponents), + QLatin1String("Show virtual components in installer and package manager."))); + + m_parser.addOption(QCommandLineOption(QLatin1String(CommandLineOptions::CreateOfflineRepository), + QLatin1String("Create a local repository inside the installation directory. This option " + "has no effect on online installers."))); + + m_parser.addOption(QCommandLineOption(QLatin1String(CommandLineOptions::AddRepository), + QLatin1String("Add a local or remote repository to the list of user defined repositories."), + QLatin1String("URI,..."))); + + m_parser.addOption(QCommandLineOption(QLatin1String(CommandLineOptions::AddTmpRepository), + QLatin1String("Add a local or remote repository to the list of temporary available " + "repositories."), QLatin1String("URI,..."))); + + m_parser.addOption(QCommandLineOption(QLatin1String(CommandLineOptions::SetTmpRepository), + QLatin1String("Set a local or remote repository as temporary repository, it is the only " + "one used during fetch.\nNote: URI must be prefixed with the protocol, i.e. file:///, " + "https://, http:// or ftp://."), QLatin1String("URI,..."))); + + m_parser.addOption(QCommandLineOption(QLatin1String(CommandLineOptions::StartServer), + QLatin1String("Starts the application as headless process waiting for commands to execute." + " Mode can be DEBUG or PRODUCTION. In DEBUG mode, the option values can be omitted." + "Note: The server will not shutdown on his own, you need to quit the process by hand."), + QLatin1String("mode,port,key"))); + m_parser.addOption(QCommandLineOption(QLatin1String(CommandLineOptions::StartClient), + QString::fromLatin1("Starts the application to debug the client-server communication. If " + "a value is omitted, the client will use a default instead. Note: The server process is " + "not started by the client application in that case, you need to start it on your own."), + QLatin1String("port,key"))); + + m_parser.addPositionalArgument(QLatin1String(CommandLineOptions::KeyValue), + QLatin1String("Key Value pair to be set.")); +} diff --git a/src/sdk/commandlineparser.h b/src/sdk/commandlineparser.h new file mode 100644 index 000000000..2bdd34f0d --- /dev/null +++ b/src/sdk/commandlineparser.h @@ -0,0 +1,56 @@ +/************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#ifndef COMMANDLINEPARSER_H +#define COMMANDLINEPARSER_H + +#include <QCommandLineParser> + +class CommandLineParser +{ +public: + CommandLineParser(); + + QString helpText() const { return m_parser.helpText(); } + bool isSet(const QString &option) { return m_parser.isSet(option); } + QStringList unknownOptionNames() const { return m_parser.unknownOptionNames(); } + QStringList positionalArguments() const { return m_parser.positionalArguments(); } + bool parse(const QStringList &argumens) { return m_parser.parse(argumens); } + QString value(const QString &option) const { return m_parser.value(option); } + +private: + QCommandLineParser m_parser; +}; + +#endif // COMMANDLINEPARSER_H diff --git a/src/sdk/console.h b/src/sdk/console.h index 7eb4aa3f4..a29c7b088 100644 --- a/src/sdk/console.h +++ b/src/sdk/console.h @@ -16,24 +16,17 @@ ** ** 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 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** ** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** ** ** $QT_END_LICENSE$ ** @@ -42,90 +35,37 @@ #ifndef CONSOLE_H #define CONSOLE_H -#include <QtCore/QtGlobal> +#include <QtGlobal> #ifdef Q_OS_WIN -# include <qt_windows.h> -# include <wincon.h> - -# include <fstream> -# include <iostream> - -# ifndef ENABLE_INSERT_MODE -# define ENABLE_INSERT_MODE 0x0020 -# endif - -# ifndef ENABLE_QUICK_EDIT_MODE -# define ENABLE_QUICK_EDIT_MODE 0x0040 -# endif -# ifndef ENABLE_EXTENDED_FLAGS -# define ENABLE_EXTENDED_FLAGS 0x0080 -# endif +#include <fstream> +#include <iostream> class Console { public: - Console() - { - AllocConsole(); - HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); - if (handle != INVALID_HANDLE_VALUE) { - COORD largestConsoleWindowSize = GetLargestConsoleWindowSize(handle); - largestConsoleWindowSize.X -= 3; - largestConsoleWindowSize.Y = 5000; - SetConsoleScreenBufferSize(handle, largestConsoleWindowSize); - } - - handle = GetStdHandle(STD_INPUT_HANDLE); - if (handle != INVALID_HANDLE_VALUE) - SetConsoleMode(handle, ENABLE_INSERT_MODE | ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS); - - m_oldCin = std::cin.rdbuf(); - m_newCin.open("CONIN$"); - std::cin.rdbuf(m_newCin.rdbuf()); - - m_oldCout = std::cout.rdbuf(); - m_newCout.open("CONOUT$"); - std::cout.rdbuf(m_newCout.rdbuf()); - - m_oldCerr = std::cerr.rdbuf(); - m_newCerr.open("CONOUT$"); - std::cerr.rdbuf(m_newCerr.rdbuf()); -# ifndef Q_CC_MINGW - HMENU systemMenu = GetSystemMenu(GetConsoleWindow(), FALSE); - if (systemMenu != NULL) - RemoveMenu(systemMenu, SC_CLOSE, MF_BYCOMMAND); - DrawMenuBar(GetConsoleWindow()); -# endif - } - - ~Console() - { - system("PAUSE"); - - std::cin.rdbuf(m_oldCin); - std::cerr.rdbuf(m_oldCerr); - std::cout.rdbuf(m_oldCout); - - FreeConsole(); - } + Console(); + ~Console(); private: - std::ifstream m_newCin; + bool parentConsole; + std::ofstream m_newCout; std::ofstream m_newCerr; - std::streambuf* m_oldCin; std::streambuf* m_oldCout; std::streambuf* m_oldCerr; }; -#else + +#else // Q_OS_WIN + class Console { public: Console() {} }; -#endif + +#endif // Q_OS_WIN #endif // CONSOLE_H diff --git a/src/sdk/console_win.cpp b/src/sdk/console_win.cpp new file mode 100644 index 000000000..da5dca49f --- /dev/null +++ b/src/sdk/console_win.cpp @@ -0,0 +1,142 @@ +/************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#include "console.h" + +# include <qt_windows.h> +# include <wincon.h> + + +# ifndef ENABLE_INSERT_MODE +# define ENABLE_INSERT_MODE 0x0020 +# endif + +# ifndef ENABLE_QUICK_EDIT_MODE +# define ENABLE_QUICK_EDIT_MODE 0x0040 +# endif + +# ifndef ENABLE_EXTENDED_FLAGS +# define ENABLE_EXTENDED_FLAGS 0x0080 +# endif + +static bool isRedirected(HANDLE stdHandle) +{ + if (stdHandle == NULL) // launched from GUI + return false; + DWORD fileType = GetFileType(stdHandle); + if (fileType == FILE_TYPE_UNKNOWN) { + // launched from console, but no redirection + return false; + } + // redirected into file, pipe ... + return true; +} + +/** + * Redirects stdout, stderr output to console + * + * Console is a RAII class that ensures stdout, stderr output is visible + * for GUI applications on Windows. + * + * If the application is launched from the explorer, startup menu etc + * a new console window is created. + * + * If the application is launched from the console (cmd.exe), output is + * printed there. + * + * If the application is launched from the console, but stdout is redirected + * (e.g. into a file), Console does not interfere. + */ +Console::Console() : + m_oldCout(0), + m_oldCerr(0) +{ + bool isCoutRedirected = isRedirected(GetStdHandle(STD_OUTPUT_HANDLE)); + bool isCerrRedirected = isRedirected(GetStdHandle(STD_ERROR_HANDLE)); + + if (!isCoutRedirected) { // verbose output only ends up in cout + // try to use parent console. else launch & set up new console + parentConsole = AttachConsole(ATTACH_PARENT_PROCESS); + if (!parentConsole) { + AllocConsole(); + HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); + if (handle != INVALID_HANDLE_VALUE) { + COORD largestConsoleWindowSize = GetLargestConsoleWindowSize(handle); + largestConsoleWindowSize.X -= 3; + largestConsoleWindowSize.Y = 5000; + SetConsoleScreenBufferSize(handle, largestConsoleWindowSize); + } + handle = GetStdHandle(STD_INPUT_HANDLE); + if (handle != INVALID_HANDLE_VALUE) + SetConsoleMode(handle, ENABLE_INSERT_MODE | ENABLE_QUICK_EDIT_MODE + | ENABLE_EXTENDED_FLAGS); +# ifndef Q_CC_MINGW + HMENU systemMenu = GetSystemMenu(GetConsoleWindow(), FALSE); + if (systemMenu != NULL) + RemoveMenu(systemMenu, SC_CLOSE, MF_BYCOMMAND); + DrawMenuBar(GetConsoleWindow()); +# endif + } + } + + if (!isCoutRedirected) { + m_oldCout = std::cout.rdbuf(); + m_newCout.open("CONOUT$"); + std::cout.rdbuf(m_newCout.rdbuf()); + } + + if (!isCerrRedirected) { + m_oldCerr = std::cerr.rdbuf(); + m_newCerr.open("CONOUT$"); + std::cerr.rdbuf(m_newCerr.rdbuf()); + } +} + +Console::~Console() +{ + if (!parentConsole) { + system("PAUSE"); + } else { + // simulate enter key to switch to boot prompt + PostMessage(GetConsoleWindow(), WM_KEYDOWN, 0x0D, 0); + } + + if (m_oldCerr) + std::cerr.rdbuf(m_oldCerr); + if (m_oldCout) + std::cout.rdbuf(m_oldCout); + + if (m_oldCout) + FreeConsole(); +} diff --git a/src/sdk/constants.h b/src/sdk/constants.h new file mode 100644 index 000000000..44fe1f598 --- /dev/null +++ b/src/sdk/constants.h @@ -0,0 +1,62 @@ +/************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#ifndef CONSTANTS_H +#define CONSTANTS_H + +namespace CommandLineOptions { + +const char HelpShort[] = "h"; +const char HelpLong[] = "help"; +const char Version[] = "version"; +const char FrameworkVersion[] = "framework-version"; +const char VerboseShort[] = "v"; +const char VerboseLong[] = "verbose"; +const char Proxy[] = "proxy"; +const char Script[] = "script"; +const char CheckUpdates[] = "checkupdates"; +const char Updater[] = "updater"; +const char ManagePackages[] = "manage-packages"; +const char NoForceInstallation[] = "no-force-installations"; +const char ShowVirtualComponents[] = "show-virtual-components"; +const char CreateOfflineRepository[] = "create-offline-repository"; +const char AddRepository[] = "addRepository"; +const char AddTmpRepository[] = "addTempRepository"; +const char SetTmpRepository[] = "setTempRepository"; +const char StartServer[] = "startserver"; +const char StartClient[] = "startclient"; + +} // namespace CommandLineOptions + +#endif // CONSTANTS_H diff --git a/src/sdk/installerbase.cpp b/src/sdk/installerbase.cpp index 8c9fdad51..6253f3e25 100644 --- a/src/sdk/installerbase.cpp +++ b/src/sdk/installerbase.cpp @@ -16,485 +16,290 @@ ** ** 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 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** ** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** ** ** $QT_END_LICENSE$ ** **************************************************************************/ -#include "installerbase_p.h" +#include "constants.h" +#include "commandlineparser.h" +#include "installerbase.h" #include "installerbasecommons.h" -#include "sdkapp.h" #include "tabcontroller.h" -#include <binaryformat.h> +#include <binaryformatenginehandler.h> +#include <copydirectoryoperation.h> #include <errors.h> -#include <fileutils.h> -#include <fsengineserver.h> #include <init.h> -#include <lib7z_facade.h> -#include <operationrunner.h> +#include <kdupdaterupdateoperations.h> +#include <messageboxhandler.h> #include <packagemanagercore.h> -#include <packagemanagergui.h> -#include <qinstallerglobal.h> +#include <packagemanagerproxyfactory.h> +#include <qprocesswrapper.h> +#include <protocol.h> +#include <productkeycheck.h> #include <settings.h> #include <utils.h> -#include <updater.h> -#include <messageboxhandler.h> -#include <kdselfrestarter.h> #include <kdrunoncechecker.h> #include <kdupdaterfiledownloaderfactory.h> -#include <productkeycheck.h> - #include <QDirIterator> -#include <QtCore/QTranslator> - -#include <QtNetwork/QNetworkProxyFactory> - -#include <iostream> -#include <fstream> - -#include <string> - -#define QUOTE_(x) #x -#define QUOTE(x) QUOTE_(x) -#define VERSION "IFW Version: \"" QUOTE(IFW_VERSION) "\", Installer base SHA1: \"" QUOTE(_GIT_SHA1_) \ - "\", Build date: " QUOTE(__DATE__) "." - -using namespace QInstaller; -using namespace QInstallerCreator; +#include <QTemporaryFile> +#include <QTranslator> +#include <QUuid> -static const char installer_create_datetime_placeholder [32] = "MY_InstallerCreateDateTime_MY"; - -static QStringList repositories(const QStringList &arguments, const int index) +InstallerBase::InstallerBase(int &argc, char *argv[]) + : SDKApp<QApplication>(argc, argv) + , m_core(0) { - if (index < arguments.size()) { - QStringList items = arguments.at(index).split(QLatin1Char(',')); - foreach (const QString &item, items) { - qDebug() << "Adding custom repository:" << item; - } - return items; - } else { - std::cerr << "No repository specified" << std::endl; - } - return QStringList(); + QInstaller::init(); // register custom operations } -// -- main - -int main(int argc, char *argv[]) +InstallerBase::~InstallerBase() { -// increase maximum numbers of file descriptors -#if defined (Q_OS_MAC) - struct rlimit rl; - getrlimit(RLIMIT_NOFILE, &rl); - rl.rlim_cur = qMin((rlim_t)OPEN_MAX, rl.rlim_max); - setrlimit(RLIMIT_NOFILE, &rl); -#endif - - QStringList args = QInstaller::parseCommandLineArgs(argc, argv); - -// hack to use cleanlooks if it is under Ubuntu -#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) - std::string standardString; - std::string cleanLooks ="-style=cleanlooks"; - std::ifstream input("/etc/os-release"); - bool isUbuntu = false; - while (std::getline(input, standardString)) { - if (standardString == "ID=ubuntu") - isUbuntu = true; - } + delete m_core; +} - if (isUbuntu) { - argc++; - char **newArgv = new char* [argc]; - newArgv[0] = argv[0]; - newArgv[1] = const_cast<char*>(cleanLooks.data()); - for (int i = 1; i < argc-1; ++i) { - newArgv[i+1] = argv[i]; +int InstallerBase::run() +{ + KDRunOnceChecker runCheck(qApp->applicationDirPath() + QLatin1String("/lockmyApp1234865.lock")); + if (runCheck.isRunning(KDRunOnceChecker::ConditionFlag::Lockfile)) { + // It is possible to install an application and thus the maintenance tool into a + // directory that requires elevated permission to create a lock file. Since this + // cannot be done without requesting credentials from the user, we silently ignore + // the fact that we could not create the lock file and check the running processes. + if (runCheck.isRunning(KDRunOnceChecker::ConditionFlag::ProcessList)) { + QInstaller::MessageBoxHandler::information(0, QLatin1String("AlreadyRunning"), + QString::fromLatin1("Waiting for %1").arg(qAppName()), + QString::fromLatin1("Another %1 instance is already running. Wait " + "until it finishes, close it, or restart your system.").arg(qAppName())); + return EXIT_FAILURE; } - argv = newArgv; } -#endif - qsrand(QDateTime::currentDateTime().toTime_t()); - const KDSelfRestarter restarter(argc, argv); - KDRunOnceChecker runCheck(QLatin1String("lockmyApp1234865.lock")); - - try { - if (args.contains(QLatin1String("--help")) || args.contains(QLatin1String("-h"))) { - InstallerBase::showUsage(); - return 0; - } - - if (args.contains(QLatin1String("--version"))) { - QString versionOutPut; - QDateTime dateTimeCheck = QDateTime::fromString(QLatin1String( - installer_create_datetime_placeholder), QLatin1String("yyyy-MM-dd - HH:mm:ss")); - if (dateTimeCheck.isValid()) { - versionOutPut.append(QLatin1String("Installer creation time: ")); - versionOutPut.append(QLatin1String(installer_create_datetime_placeholder)); - versionOutPut.append(QLatin1String("\n")); - } - versionOutPut.append(QLatin1String(VERSION)); - InstallerBase::showVersion(versionOutPut); - return 0; - } - - // this is the FSEngineServer as an admin rights process upon request: - if (args.count() >= 3 && args[1] == QLatin1String("--startserver")) { - SDKApp<QCoreApplication> app(argc, argv); - FSEngineServer* const server = new FSEngineServer(args[2].toInt()); - if (args.count() >= 4) - server->setAuthorizationKey(args[3]); - QObject::connect(server, SIGNAL(destroyed()), &app, SLOT(quit())); - return app.exec(); - } - - // Make sure we honor the system's proxy settings -#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) - QUrl proxyUrl(QString::fromLatin1(qgetenv("http_proxy"))); - if (proxyUrl.isValid()) { - QNetworkProxy proxy(QNetworkProxy::HttpProxy, proxyUrl.host(), proxyUrl.port(), - proxyUrl.userName(), proxyUrl.password()); - QNetworkProxy::setApplicationProxy(proxy); - } -#else - if (args.contains(QLatin1String("--proxy"))) - QNetworkProxyFactory::setUseSystemConfiguration(true); -#endif - - if (args.contains(QLatin1String("--checkupdates"))) { - SDKApp<QCoreApplication> app(argc, argv); - if (runCheck.isRunning(KDRunOnceChecker::ProcessList)) - return 0; - - Updater u; - if (args.contains(QLatin1String("--verbose")) || args.contains(QLatin1String("-v"))) { - app.setVerbose(); - u.setVerbose(true); - } - return u.checkForUpdates() ? 0 : 1; - } - - if (args.contains(QLatin1String("--runoperation")) - || args.contains(QLatin1String("--undooperation"))) { - SDKApp<QCoreApplication> app(argc, argv); - OperationRunner o; - o.setVerbose(args.contains(QLatin1String("--verbose")) - || args.contains(QLatin1String("-v"))); - return o.runOperation(args); - } - - if (args.contains(QLatin1String("--update-installerbase"))) { - SDKApp<QCoreApplication> app(argc, argv); - if (runCheck.isRunning(KDRunOnceChecker::ProcessList)) - return 0; - - return InstallerBase().replaceMaintenanceToolBinary(args); - } - - if (args.contains(QLatin1String("--dump-binary-data"))) { - bool verbose = args.contains(QLatin1String("--verbose")) || args.contains(QLatin1String("-v")); - - args = args.mid(args.indexOf(QLatin1String("--dump-binary-data")) + 1, 4); - // we expect at least -o and the output path - if (args.count() < 2 || !args.contains(QLatin1String("-o"))) { - InstallerBase::showUsage(); - return EXIT_FAILURE; - } - - // output path - const QString output = args.at(args.indexOf(QLatin1String("-o")) + 1); - if (output.isEmpty()) { - InstallerBase::showUsage(); - return EXIT_FAILURE; - } + QString fileName = datFile(binaryFile()); + quint64 cookie = QInstaller::BinaryContent::MagicCookieDat; + if (fileName.isEmpty()) { + fileName = binaryFile(); + cookie = QInstaller::BinaryContent::MagicCookie; + } - SDKApp<QCoreApplication> app(argc, argv); + QFile binary(fileName); + QInstaller::openForRead(&binary); - // input, if not given use current app - QString input; - if (args.indexOf(QLatin1String("-i")) >= 0) - input = args.value(args.indexOf(QLatin1String("-i")) + 1); + qint64 magicMarker; + QInstaller::ResourceCollectionManager manager; + QList<QInstaller::OperationBlob> oldOperations; + QInstaller::BinaryContent::readBinaryContent(&binary, &oldOperations, &manager, &magicMarker, + cookie); - if (input.isEmpty() || input == QLatin1String("-o") || input == output) - input = QCoreApplication::applicationFilePath(); + if (QInstaller::isVerbose()) { + qDebug() << "Language:" << QLocale().uiLanguages().value(0, + QLatin1String("No UI language set")).toUtf8().constData(); + qDebug() << "Arguments: " << arguments().join(QLatin1String(", ")).toUtf8().constData(); + } - OperationRunner o(input); - o.setVerbose(verbose); - return o.runOperation(QStringList(QLatin1String("--runoperation")) - << QLatin1String("CreateLocalRepository") << input << output); - } + CommandLineParser parser; + parser.parse(arguments()); + + SDKApp::registerMetaResources(manager.collectionByName("QResources")); + if (parser.isSet(QLatin1String(CommandLineOptions::StartClient))) { + const QStringList arguments = parser.value(QLatin1String(CommandLineOptions::StartServer)) + .split(QLatin1Char(','), QString::SkipEmptyParts); + m_core = new QInstaller::PackageManagerCore(magicMarker, oldOperations, QString(arguments + .value(0, QString::number(QInstaller::Protocol::DefaultPort))).toInt(), + arguments.value(1, QLatin1String(QInstaller::Protocol::DefaultAuthorizationKey)), + QInstaller::Protocol::Mode::Debug); + } else { + m_core = new QInstaller::PackageManagerCore(magicMarker, oldOperations, + 30000 + qrand() % 100, QUuid::createUuid().toString()); + } - // from here, the "normal" installer binary is running - SDKApp<QApplication> app(argc, argv); - args = app.arguments(); + { + using namespace QInstaller; + ProductKeyCheck::instance()->init(m_core); + ProductKeyCheck::instance()->addPackagesFromXml(QLatin1String(":/metadata/Updates.xml")); + BinaryFormatEngineHandler::instance()->registerResources(manager.collections()); + } + if (QInstaller::isVerbose()) + dumpResourceTree(); + + QString controlScript; + if (parser.isSet(QLatin1String(CommandLineOptions::Script))) { + controlScript = parser.value(QLatin1String(CommandLineOptions::Script)); + if (!QFileInfo(controlScript).exists()) + throw QInstaller::Error(QLatin1String("Script file does not exist.")); + } - if (runCheck.isRunning(KDRunOnceChecker::ProcessList)) { - if (runCheck.isRunning(KDRunOnceChecker::Lockfile)) - return 0; + if (parser.isSet(QLatin1String(CommandLineOptions::Proxy))) { + m_core->settings().setProxyType(QInstaller::Settings::SystemProxy); + KDUpdater::FileDownloaderFactory::instance().setProxyFactory(m_core->proxyFactory()); + } - while (runCheck.isRunning(KDRunOnceChecker::ProcessList)) - Sleep::sleep(1); - } + if (parser.isSet(QLatin1String(CommandLineOptions::ShowVirtualComponents))) { + QFont f; + f.setItalic(true); + QInstaller::PackageManagerCore::setVirtualComponentsFont(f); + QInstaller::PackageManagerCore::setVirtualComponentsVisible(true); + } - if (args.contains(QLatin1String("--verbose")) || args.contains(QLatin1String("-v"))) { - app.setVerbose(); - QInstaller::setVerbose(true); - } + if (parser.isSet(QLatin1String(CommandLineOptions::Updater))) { + if (m_core->isInstaller()) + throw QInstaller::Error(QLatin1String("Cannot start installer binary as updater.")); + m_core->setUpdater(); + } - if (QInstaller::isVerbose()) { - qDebug() << VERSION; - qDebug() << "Arguments:" << args; - qDebug() << "Resource tree before loading the in-binary resource:"; - qDebug() << "Language: " << QLocale().uiLanguages().value(0, QLatin1String("No UI language set")); + if (parser.isSet(QLatin1String(CommandLineOptions::ManagePackages))) { + if (m_core->isInstaller()) + throw QInstaller::Error(QLatin1String("Cannot start installer binary as package manager.")); + m_core->setPackageManager(); + } - QDirIterator it(QLatin1String(":/"), QDir::NoDotAndDotDot | QDir::AllEntries | QDir::Hidden, - QDirIterator::Subdirectories); - while (it.hasNext()) - qDebug() << QString::fromLatin1(" %1").arg(it.next()); - } + if (parser.isSet(QLatin1String(CommandLineOptions::AddRepository))) { + const QStringList repoList = repositories(parser + .value(QLatin1String(CommandLineOptions::AddRepository))); + if (repoList.isEmpty()) + throw QInstaller::Error(QLatin1String("Empty repository list for option 'addRepository'.")); + m_core->addUserRepositories(repoList); + } - // register custom operations before reading the binary content cause they may used in - // the uninstaller for the recorded list of during the installation performed operations - QInstaller::init(); - - QString binaryFile = QCoreApplication::applicationFilePath(); - const int index = args.indexOf(QLatin1String("--binarydatafile")); - if (index >= 0) { - binaryFile = args.value(index + 1); - if (binaryFile.isEmpty()) { - std::cerr << QFileInfo(app.applicationFilePath()).fileName() << " --binarydatafile [missing " - "argument]" << std::endl; - return PackageManagerCore::Failure; - } + if (parser.isSet(QLatin1String(CommandLineOptions::AddTmpRepository))) { + const QStringList repoList = repositories(parser + .value(QLatin1String(CommandLineOptions::AddTmpRepository))); + if (repoList.isEmpty()) + throw QInstaller::Error(QLatin1String("Empty repository list for option 'addTempRepository'.")); + m_core->setTemporaryRepositories(repoList, false); + } - // Consume the arguments to avoid "Unknown option" output. Also there's no need to check for a - // valid binary, will throw in readAndRegisterFromBinary(...) if the magic cookie can't be found. - args.removeAt(index + 1); - args.removeAll(QLatin1String("--binarydatafile")); - } + if (parser.isSet(QLatin1String(CommandLineOptions::SetTmpRepository))) { + const QStringList repoList = repositories(parser + .value(QLatin1String(CommandLineOptions::SetTmpRepository))); + if (repoList.isEmpty()) + throw QInstaller::Error(QLatin1String("Empty repository list for option 'setTempRepository'.")); + m_core->setTemporaryRepositories(repoList, true); + } -#ifdef Q_OS_MAC - // Load the external binary resource if we got one passed, otherwise assume we are a bundle. In that - // case we need to figure out the path into the bundles resources folder to get the binary data. - if (index < 0) { - QDir resourcePath(QFileInfo(binaryFile).dir()); - resourcePath.cdUp(); - resourcePath.cd(QLatin1String("Resources")); - binaryFile = resourcePath.filePath(QLatin1String("installer.dat")); - } -#endif - BinaryContent content = BinaryContent::readAndRegisterFromBinary(binaryFile); - - // instantiate the installer we are actually going to use - QInstaller::PackageManagerCore core(content.magicMarker(), content.performedOperations()); - ProductKeyCheck::instance()->init(&core); - - QString controlScript; - QHash<QString, QString> params; - for (int i = 1; i < args.size(); ++i) { - const QString &argument = args.at(i); - if (argument.isEmpty()) - continue; - - if (argument.contains(QLatin1Char('='))) { - const QString name = argument.section(QLatin1Char('='), 0, 0); - const QString value = argument.section(QLatin1Char('='), 1, 1); - params.insert(name, value); - core.setValue(name, value); - } else if (argument == QLatin1String("--script") || argument == QLatin1String("Script")) { - ++i; - if (i < args.size()) { - controlScript = args.at(i); - if (!QFileInfo(controlScript).exists()) - return PackageManagerCore::Failure; - } else { - return PackageManagerCore::Failure; - } - } else if (argument == QLatin1String("--verbose") || argument == QLatin1String("-v")) { - core.setVerbose(true); - } else if (argument == QLatin1String("--proxy")) { - core.settings().setProxyType(QInstaller::Settings::SystemProxy); - KDUpdater::FileDownloaderFactory::instance().setProxyFactory(core.proxyFactory()); - } else if (argument == QLatin1String("--show-virtual-components") - || argument == QLatin1String("ShowVirtualComponents")) { - QFont f; - f.setItalic(true); - PackageManagerCore::setVirtualComponentsFont(f); - PackageManagerCore::setVirtualComponentsVisible(true); - } else if ((argument == QLatin1String("--updater") - || argument == QLatin1String("Updater")) && core.isUninstaller()) { - core.setUpdater(); - } else if ((argument == QLatin1String("--manage-packages") - || argument == QLatin1String("ManagePackages")) && core.isUninstaller()) { - core.setPackageManager(); - } else if (argument == QLatin1String("--addTempRepository") - || argument == QLatin1String("--setTempRepository")) { - ++i; - QStringList repoList = repositories(args, i); - if (repoList.isEmpty()) - return PackageManagerCore::Failure; - - // We cannot use setRemoteRepositories as that is a synchronous call which " - // tries to get the data from server and this isn't what we want at this point - const bool replace = (argument == QLatin1String("--setTempRepository")); - core.setTemporaryRepositories(repoList, replace); - } else if (argument == QLatin1String("--addRepository")) { - ++i; - QStringList repoList = repositories(args, i); - if (repoList.isEmpty()) - return PackageManagerCore::Failure; - core.addUserRepositories(repoList); - } else if (argument == QLatin1String("--no-force-installations")) { - PackageManagerCore::setNoForceInstallation(true); - } else if (argument == QLatin1String("--create-offline-repository")) { - PackageManagerCore::setCreateLocalRepositoryFromBinary(true); - } else { - std::cerr << "Unknown option: " << argument << std::endl; - } + QInstaller::PackageManagerCore::setNoForceInstallation(parser + .isSet(QLatin1String(CommandLineOptions::NoForceInstallation))); + QInstaller::PackageManagerCore::setCreateLocalRepositoryFromBinary(parser + .isSet(QLatin1String(CommandLineOptions::CreateOfflineRepository))); + + QHash<QString, QString> params; + const QStringList positionalArguments = parser.positionalArguments(); + foreach (const QString &argument, positionalArguments) { + if (argument.contains(QLatin1Char('='))) { + const QString name = argument.section(QLatin1Char('='), 0, 0); + const QString value = argument.section(QLatin1Char('='), 1, 1); + params.insert(name, value); + m_core->setValue(name, value); } + } - // this needs to happen after we parse the arguments, but before we use the actual resources - const QString newDefaultResource = core.value(QString::fromLatin1("DefaultResourceReplacement")); - if (!newDefaultResource.isEmpty()) - content.registerAsDefaultQResource(newDefaultResource); - - if (QInstaller::isVerbose()) { - qDebug() << "Resource tree after loading the in-binary resource:"; - QDirIterator it(QLatin1String(":/"), QDir::NoDotAndDotDot | QDir::AllEntries | QDir::Hidden, - QDirIterator::Subdirectories); - while (it.hasNext()) - qDebug() << QString::fromLatin1(" %1").arg(it.next()); + const QString directory = QLatin1String(":/translations"); + const QStringList translations = m_core->settings().translations(); + + // install the default Qt translator + QScopedPointer<QTranslator> translator(new QTranslator(QCoreApplication::instance())); + foreach (const QLocale locale, QLocale().uiLanguages()) { + // As there is no qt_en.qm, we simply end the search when the next + // preferred language is English. + if (locale.language() == QLocale::English) + break; + if (translator->load(locale, QLatin1String("qt"), QString::fromLatin1("_"), directory)) { + QCoreApplication::instance()->installTranslator(translator.take()); + break; } + } - const QString directory = QLatin1String(":/translations"); - const QStringList translations = core.settings().translations(); + translator.reset(new QTranslator(QCoreApplication::instance())); + // install English translation as fallback so that correct license button text is used + if (translator->load(QLatin1String("en_us"), directory)) + QCoreApplication::instance()->installTranslator(translator.take()); - // install the default Qt translator - QScopedPointer<QTranslator> translator(new QTranslator(&app)); + if (translations.isEmpty()) { + translator.reset(new QTranslator(QCoreApplication::instance())); foreach (const QLocale locale, QLocale().uiLanguages()) { - // As there is no qt_en.qm, we simply end the search when the next - // preferred language is English. - if (locale.language() == QLocale::English) - break; - if (translator->load(locale, QLatin1String("qt"), QString::fromLatin1("_"), directory)) { - app.installTranslator(translator.take()); + if (translator->load(locale, QLatin1String(""), QLatin1String(""), directory)) { + QCoreApplication::instance()->installTranslator(translator.take()); break; } } - - translator.reset(new QTranslator(&app)); - // install English translation as fallback so that correct license button text is used - if (translator->load(QLatin1String("en_us"), directory)) - app.installTranslator(translator.take()); - - if (translations.isEmpty()) { - translator.reset(new QTranslator(&app)); - foreach (const QLocale locale, QLocale().uiLanguages()) { - if (translator->load(locale, QLatin1String(""), QLatin1String(""), directory)) { - app.installTranslator(translator.take()); - break; - } - } - } else { - foreach (const QString &translation, translations) { - translator.reset(new QTranslator(&app)); - if (translator->load(translation, QLatin1String(":/translations"))) - app.installTranslator(translator.take()); - } + } else { + foreach (const QString &translation, translations) { + translator.reset(new QTranslator(QCoreApplication::instance())); + if (translator->load(translation, QLatin1String(":/translations"))) + QCoreApplication::instance()->installTranslator(translator.take()); } + } - // Create the wizard gui - TabController controller(0); - controller.setManager(&core); - controller.setManagerParams(params); - controller.setControlScript(controlScript); + //create the wizard GUI + TabController controller(0); + controller.setManager(m_core); + controller.setManagerParams(params); + controller.setControlScript(controlScript); - if (core.isInstaller()) { - controller.setGui(new InstallerGui(&core)); - } else { - controller.setGui(new MaintenanceGui(&core)); - } + if (m_core->isInstaller()) + controller.setGui(new InstallerGui(m_core)); + else + controller.setGui(new MaintenanceGui(m_core)); - // - // Sanity check to detect a broken installations with missing operations. - // Every installed package should have at least one MinimalProgress operation. - // - QSet<QString> installedPackages = core.localInstalledPackages().keys().toSet(); - QSet<QString> operationPackages; - foreach (QInstaller::Operation *operation, content.performedOperations()) { - if (operation->hasValue(QLatin1String("component"))) - operationPackages.insert(operation->value(QLatin1String("component")).toString()); - } + QInstaller::PackageManagerCore::Status status = + QInstaller::PackageManagerCore::Status(controller.init()); + if (status != QInstaller::PackageManagerCore::Success) + return status; - QSet<QString> packagesWithoutOperation = installedPackages - operationPackages; - QSet<QString> orphanedOperations = operationPackages - installedPackages; - if (!packagesWithoutOperation.isEmpty() || !orphanedOperations.isEmpty()) { - qCritical() << "Operations missing for installed packages" << packagesWithoutOperation.toList(); - qCritical() << "Orphaned operations" << orphanedOperations.toList(); - MessageBoxHandler::critical( - MessageBoxHandler::currentBestSuitParent(), - QLatin1String("Corrupt_Installation_Error"), - QCoreApplication::translate("QInstaller", "Corrupt installation"), - QCoreApplication::translate("QInstaller", - "Your installation seems to be corrupted. " - "Please consider re-installing from scratch." - )); - } else { - qDebug() << "Operations sanity check succeeded."; - } + const int result = QCoreApplication::instance()->exec(); + if (result != 0) + return result; + + if (m_core->finishedWithSuccess()) + return QInstaller::PackageManagerCore::Success; - PackageManagerCore::Status status = PackageManagerCore::Status(controller.init()); - if (status != PackageManagerCore::Success) + status = m_core->status(); + switch (status) { + case QInstaller::PackageManagerCore::Success: return status; - const int result = app.exec(); - if (result != 0) - return result; + case QInstaller::PackageManagerCore::Canceled: + return status; - if (core.finishedWithSuccess()) - return PackageManagerCore::Success; + default: + break; + } + return QInstaller::PackageManagerCore::Failure; +} - status = core.status(); - switch (status) { - case PackageManagerCore::Success: - return status; - case PackageManagerCore::Canceled: - return status; +// -- private - default: - break; - } - return PackageManagerCore::Failure; - } catch(const Error &e) { - std::cerr << qPrintable(e.message()) << std::endl; - } catch (const std::exception &e) { - std::cerr << e.what() << std::endl; - } catch(...) { - std::cerr << "Unknown error, aborting." << std::endl; +void InstallerBase::dumpResourceTree() const +{ + qDebug() << "Resource tree:"; + QDirIterator it(QLatin1String(":/"), QDir::NoDotAndDotDot | QDir::AllEntries | QDir::Hidden, + QDirIterator::Subdirectories); + while (it.hasNext()) { + if (it.next().startsWith(QLatin1String(":/qt-project.org"))) + continue; + qDebug() << " " << it.filePath().toUtf8().constData(); } +} - return PackageManagerCore::Failure; +QStringList InstallerBase::repositories(const QString &list) const +{ + const QStringList items = list.split(QLatin1Char(','), QString::SkipEmptyParts); + foreach (const QString &item, items) + qDebug() << "Adding custom repository:" << item.toUtf8().constData(); + return items; } diff --git a/src/sdk/installerbase.h b/src/sdk/installerbase.h new file mode 100644 index 000000000..8230a89e0 --- /dev/null +++ b/src/sdk/installerbase.h @@ -0,0 +1,63 @@ +/************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#ifndef INSTALLERBASE_H +#define INSTALLERBASE_H + +#include "sdkapp.h" + +namespace QInstaller { + class PackageManagerCore; +} + +class InstallerBase : public SDKApp<QApplication> +{ + Q_OBJECT + Q_DISABLE_COPY(InstallerBase) + +public: + InstallerBase(int &argc, char *argv[]); + ~InstallerBase(); + + int run(); + +private: + void dumpResourceTree() const; + QStringList repositories(const QString &list) const; + +private: + QInstaller::PackageManagerCore *m_core; +}; + +#endif // INSTALLERBASE_H diff --git a/src/sdk/installerbase_p.cpp b/src/sdk/installerbase_p.cpp deleted file mode 100644 index 57de0dc5d..000000000 --- a/src/sdk/installerbase_p.cpp +++ /dev/null @@ -1,327 +0,0 @@ -/************************************************************************** -** -** Copyright (C) 2012-2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/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 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -**************************************************************************/ -#include "installerbase_p.h" -#include "console.h" - -#include <binaryformat.h> -#include <errors.h> -#include <fileutils.h> -#include <lib7z_facade.h> -#include <qprocesswrapper.h> -#include <utils.h> - -#include <kdsavefile.h> -#include <kdupdaterfiledownloader.h> -#include <kdupdaterfiledownloaderfactory.h> - -#include <QtCore/QDir> -#include <QtCore/QDebug> -#include <QtCore/QTemporaryFile> -#include <QtCore/QUrl> - -#include <QMessageBox> - -#include <iomanip> -#include <iostream> - -using namespace KDUpdater; -using namespace QInstaller; -using namespace QInstallerCreator; - - -// -- InstallerBase - -InstallerBase::InstallerBase(QObject *parent) - : QObject(parent) - , m_downloadFinished(false) -{ -} - -InstallerBase::~InstallerBase() -{ -} - -int InstallerBase::replaceMaintenanceToolBinary(QStringList arguments) -{ - QInstaller::setVerbose(arguments.contains(QLatin1String("--verbose")) - || arguments.contains(QLatin1String("-v"))); - - arguments.removeAll(QLatin1String("--verbose")); - arguments.removeAll(QLatin1String("-v")); - arguments.removeAll(QLatin1String("--update-installerbase")); - - QUrl url = arguments.value(1); - if (!FileDownloaderFactory::isSupportedScheme(url.scheme()) && QFileInfo(url.toString()).exists()) - url = QLatin1String("file:///") + url.toString(); - m_downloader.reset(FileDownloaderFactory::instance().create(url.scheme(), 0)); - if (m_downloader.isNull()) { - qDebug() << QString::fromLatin1("Scheme not supported: %1 (%2)").arg(url.scheme(), url.toString()); - return EXIT_FAILURE; - } - m_downloader->setUrl(url); - m_downloader->setAutoRemoveDownloadedFile(true); - - QString target = QDir::tempPath() + QLatin1String("/") + QFileInfo(arguments.at(1)).fileName(); - if (FileDownloaderFactory::isSupportedScheme(url.scheme())) - m_downloader->setDownloadedFileName(target); - - connect(m_downloader.data(), SIGNAL(downloadStarted()), this, SLOT(downloadStarted())); - connect(m_downloader.data(), SIGNAL(downloadCanceled()), this, SLOT(downloadFinished())); - connect(m_downloader.data(), SIGNAL(downloadCompleted()), this, SLOT(downloadFinished())); - connect(m_downloader.data(), SIGNAL(downloadAborted(QString)), this, SLOT(downloadAborted(QString))); - - m_downloader->download(); - - while (true) { - QCoreApplication::processEvents(); - if (m_downloadFinished) - break; - } - - if (!m_downloader->isDownloaded()) { - qDebug() << QString::fromLatin1("Could not download file %1: . Error: %2.").arg( - m_downloader->url().toString(), m_downloader->errorString()); - return EXIT_FAILURE; - } - - if (Lib7z::isSupportedArchive(target)) { - QFile archive(target); - if (archive.open(QIODevice::ReadOnly)) { - try { - Lib7z::extractArchive(&archive, QDir::tempPath()); - if (!archive.remove()) { - qDebug() << QString::fromLatin1("Could not delete file %1: %2").arg( - target, archive.errorString()); - } - } catch (const Lib7z::SevenZipException& e) { - qDebug() << QString::fromLatin1("Error while extracting '%1': %2").arg(target, e.message()); - return EXIT_FAILURE; - } catch (...) { - qDebug() << QString::fromLatin1("Unknown exception caught while extracting %1.").arg(target); - return EXIT_FAILURE; - } - } else { - qDebug() << QString::fromLatin1("Could not open %1 for reading: %2.").arg( - target, archive.errorString()); - return EXIT_FAILURE; - } -#ifndef Q_OS_WIN - target = QDir::tempPath() + QLatin1String("/.tempSDKMaintenanceTool"); -#else - target = QDir::tempPath() + QLatin1String("/temp/SDKMaintenanceToolBase.exe"); -#endif - } - - try { - QFile installerBase(target); - QInstaller::openForRead(&installerBase, installerBase.fileName()); - writeMaintenanceBinary(arguments.value(0), &installerBase, installerBase.size()); - deferredRename(arguments.value(0) + QLatin1String(".new"), arguments.value(0)); - } catch (const QInstaller::Error &error) { - qDebug() << error.message(); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} - -/* static*/ -void InstallerBase::showUsage() -{ -#define WIDTH1 46 -#define WIDTH2 40 - Console c; - std::cout << "Usage: SDKMaintenanceTool [OPTIONS]" << std::endl << std::endl; - - std::cout << "User:"<<std::endl; - std::cout << std::setw(WIDTH1) << std::setiosflags(std::ios::left) << " --help" << std::setw(WIDTH2) - << "Show commandline usage" << std::endl; - std::cout << std::setw(WIDTH1) << std::setiosflags(std::ios::left) << " --version" << std::setw(WIDTH2) - << "Show current version" << std::endl; - std::cout << std::setw(WIDTH1) << std::setiosflags(std::ios::left) << " --checkupdates" << std::setw(WIDTH2) - << "Check for updates and return an XML file describing" << std::endl - << std::setw(WIDTH1) << " " << std::setw(WIDTH2) << "the available updates" << std::endl; - std::cout << std::setw(WIDTH1) << std::setiosflags(std::ios::left) << " --updater" << std::setw(WIDTH2) - << "Start in updater mode." << std::endl; - std::cout << std::setw(WIDTH1) << std::setiosflags(std::ios::left) << " --manage-packages" << std::setw(WIDTH2) - << "Start in packagemanager mode." << std::endl; - std::cout << std::setw(WIDTH1) << std::setiosflags(std::ios::left) << " --proxy" << std::setw(WIDTH2) - << "Set system proxy on Win and Mac." << std::endl - << std::setw(WIDTH1) << " " << std::setw(WIDTH2) << "This option has no effect on Linux." << std::endl; - std::cout << std::setw(WIDTH1) << std::setiosflags(std::ios::left) << " --verbose" << std::setw(WIDTH2) - << "Show debug output on the console" << std::endl; - std::cout << std::setw(WIDTH1) << std::setiosflags(std::ios::left) << " --create-offline-repository" - << std::setw(WIDTH2) << "Offline installer only: Create a local repository inside the" << std::endl - << std::setw(WIDTH1) << " " << std::setw(WIDTH2) << "installation directory based on the offline" << std::endl - << std::setw(WIDTH1) << " " << std::setw(WIDTH2) << "installer's content." << std::endl; - - std::cout << "\nDeveloper:"<< std::endl; - std::cout << std::setw(WIDTH1) << std::setiosflags(std::ios::left) - << " --runoperation [OPERATION] [arguments...]" << std::setw(WIDTH2) - << "Perform an operation with a list of arguments" << std::endl; - std::cout << std::setw(WIDTH1) << std::setiosflags(std::ios::left) - << " --undooperation [OPERATION] [arguments...]" << std::setw(WIDTH2) - << "Undo an operation with a list of arguments" <<std::endl; - std::cout << std::setw(WIDTH1) << std::setiosflags(std::ios::left) - << " --script [scriptName]" << std::setw(WIDTH2) << "Execute a script" << std::endl; - std::cout << std::setw(WIDTH1) << std::setiosflags(std::ios::left) << " --no-force-installations" - << std::setw(WIDTH2) << "Enable deselection of forced components" << std::endl; - std::cout << std::setw(WIDTH1) << std::setiosflags(std::ios::left) << " --addRepository [URI]" - << std::setw(WIDTH2) << "Add a local or remote repo to the list of user defined repos." << std::endl; - std::cout << std::setw(WIDTH1) << std::setiosflags(std::ios::left) << " --addTempRepository [URI]" - << std::setw(WIDTH2) << "Add a local or remote repo to the list of temporary available" << std::endl - << std::setw(WIDTH1) << " " << std::setw(WIDTH2) << "repos." << std::endl; - std::cout << std::setw(WIDTH1) << std::setiosflags(std::ios::left) << " --setTempRepository [URI]" - << std::setw(WIDTH2) << "Set a local or remote repo as tmp repo, it is the only one" << std::endl - << std::setw(WIDTH1) << " " << std::setw(WIDTH2) << "used during fetch." << std::endl; - std::cout << std::setw(WIDTH1) << std::setiosflags(std::ios::left) << " " << std::setw(WIDTH2) << "Note: URI " - "must be prefixed with the protocol, i.e. file:///" << std::endl - << std::setw(WIDTH1) << " " << std::setw(WIDTH2) << "http:// or ftp://. It can consist of multiple" << std::endl - << std::setw(WIDTH1) << " " << std::setw(WIDTH2) << "addresses separated by comma only." << std::endl; - std::cout << std::setw(WIDTH1) << std::setiosflags(std::ios::left) << " --show-virtual-components" - << std::setw(WIDTH2) << "Show virtual components in package manager and updater" << std::endl; - std::cout << std::setw(WIDTH1) << std::setiosflags(std::ios::left) - << " --binarydatafile [binary_data_file]" << std::setw(WIDTH2) << "Use the binary data of " - "another installer or maintenance tool." << std::endl; - std::cout << std::setw(WIDTH1) << std::setiosflags(std::ios::left) - << " --update-installerbase [new_installerbase]" << std::setw(WIDTH2) - << "Patch a full installer with a new installer base" << std::endl; - std::cout << std::setw(WIDTH1) << std::setiosflags(std::ios::left) << " --dump-binary-data -i [PATH] -o [PATH]" - << std::setw(WIDTH2) << "Dumps the binary content into specified output path (offline" << std::endl - << std::setw(WIDTH1) << " " << std::setw(WIDTH2) << "installer only)." << std::endl - << std::setw(WIDTH1) << " " << std::setw(WIDTH2) << "Input path pointing to binary data file, if omitted" << std::endl - << std::setw(WIDTH1) << " " << std::setw(WIDTH2) << "the current application is used as input." << std::endl; -} - -/* static*/ -void InstallerBase::showVersion(const QString &version) -{ - Console c; - std::cout << qPrintable(version) << std::endl; -} - - -// -- private slots - -void InstallerBase::downloadStarted() -{ - m_downloadFinished = false; - qDebug() << QString::fromLatin1("Download started! Source: %1, Target: %2").arg( - m_downloader->url().toString(), m_downloader->downloadedFileName()); -} - -void InstallerBase::downloadFinished() -{ - m_downloadFinished = true; - qDebug() << QString::fromLatin1("Download finished! Source: %1, Target: %2").arg( - m_downloader->url().toString(), m_downloader->downloadedFileName()); -} - -void InstallerBase::downloadProgress(double progress) -{ - qDebug() << "Progress: " << progress; -} - -void InstallerBase::downloadAborted(const QString &error) -{ - m_downloadFinished = true; - qDebug() << QString::fromLatin1("Download aborted! Source: %1, Target: %2, Error: %3").arg( - m_downloader->url().toString(), m_downloader->downloadedFileName(), error); -} - - -// -- private - -void InstallerBase::deferredRename(const QString &oldName, const QString &newName) -{ -#ifdef Q_OS_WIN - QTemporaryFile vbScript(QDir::temp().absoluteFilePath(QLatin1String("deferredrenameXXXXXX.vbs"))); - { - openForWrite(&vbScript, vbScript.fileName()); - vbScript.setAutoRemove(false); - - QTextStream batch(&vbScript); - batch << "Set fso = WScript.CreateObject(\"Scripting.FileSystemObject\")\n"; - batch << "Set tmp = WScript.CreateObject(\"WScript.Shell\")\n"; - batch << QString::fromLatin1("file = \"%1\"\n").arg(QDir::toNativeSeparators(newName)); - batch << QString::fromLatin1("backup = \"%1.bak\"\n").arg(QDir::toNativeSeparators(newName)); - batch << "on error resume next\n"; - - batch << "while fso.FileExists(file)\n"; - batch << " fso.MoveFile file, backup\n"; - batch << " WScript.Sleep(1000)\n"; - batch << "wend\n"; - batch << QString::fromLatin1("fso.MoveFile \"%1\", file\n").arg(QDir::toNativeSeparators(oldName)); - batch << "fso.DeleteFile(WScript.ScriptFullName)\n"; - } - - QProcessWrapper::startDetached(QLatin1String("cscript"), QStringList() << QLatin1String("//Nologo") - << QDir::toNativeSeparators(vbScript.fileName())); -#else - QFile::rename(newName, newName + QLatin1String(".bak")); - QFile::rename(oldName, newName); -#endif -} - -void InstallerBase::writeMaintenanceBinary(const QString &target, QFile *const source, qint64 size) -{ - KDSaveFile out(target + QLatin1String(".new")); - QInstaller::openForWrite(&out, out.fileName()); // throws an exception in case of error - - if (!source->seek(0)) { - throw QInstaller::Error(QObject::tr("Failed to seek in file %1. Reason: %2.").arg(source->fileName(), - source->errorString())); - } - - QInstaller::appendData(&out, source, size); - QInstaller::appendInt64(&out, 0); // resource count - QInstaller::appendInt64(&out, 4 * sizeof(qint64)); // data block size - QInstaller::appendInt64(&out, QInstaller::MagicUninstallerMarker); - QInstaller::appendInt64(&out, QInstaller::MagicCookie); - - out.setPermissions(out.permissions() | QFile::WriteUser | QFile::ReadGroup | QFile::ReadOther - | QFile::ExeOther | QFile::ExeGroup | QFile::ExeUser); - - if (!out.commit(KDSaveFile::OverwriteExistingFile)) { - throw QInstaller::Error(QString::fromLatin1("Could not write new maintenance-tool to %1. Reason: %2.") - .arg(out.fileName(), out.errorString())); - } -} diff --git a/src/sdk/installerbase_p.h b/src/sdk/installerbase_p.h deleted file mode 100644 index 5d3e66e31..000000000 --- a/src/sdk/installerbase_p.h +++ /dev/null @@ -1,92 +0,0 @@ -/************************************************************************** -** -** Copyright (C) 2012-2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/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 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -**************************************************************************/ - -#ifndef INSTALLERBASE_P_H -#define INSTALLERBASE_P_H - -#include <QThread> - -namespace KDUpdater { - class FileDownloader; -} - -QT_BEGIN_NAMESPACE -class QFile; -QT_END_NAMESPACE - -class Sleep : public QThread -{ -public: - static void sleep(unsigned long ms) - { - QThread::usleep(ms); - } -}; - -class InstallerBase : public QObject -{ - Q_OBJECT - -public: - explicit InstallerBase(QObject *parent = 0); - ~InstallerBase(); - - int replaceMaintenanceToolBinary(QStringList arguments); - - static void showUsage(); - static void showVersion(const QString &version); - -private slots: - void downloadStarted(); - void downloadFinished(); - void downloadProgress(double progress); - void downloadAborted(const QString &error); - -private: - void deferredRename(const QString &source, const QString &target); - void writeMaintenanceBinary(const QString &target, QFile *source, qint64 size); - -private: - volatile bool m_downloadFinished; - QScopedPointer<KDUpdater::FileDownloader> m_downloader; -}; - -#endif // INSTALLERBASE_P_H diff --git a/src/sdk/installerbasecommons.cpp b/src/sdk/installerbasecommons.cpp index 263eb5767..efdd58b75 100644 --- a/src/sdk/installerbasecommons.cpp +++ b/src/sdk/installerbasecommons.cpp @@ -16,508 +16,31 @@ ** ** 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 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** ** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** ** ** $QT_END_LICENSE$ ** **************************************************************************/ #include "installerbasecommons.h" -#include <component.h> -#include <messageboxhandler.h> #include <packagemanagercore.h> +#include <scriptengine.h> #include <packagemanagerpagefactory.h> -#include <settings.h> - #include <productkeycheck.h> -#include <QtCore/QDir> -#include <QtCore/QFileInfo> -#include <QtCore/QTimer> - -#include <QLabel> -#include <QProgressBar> -#include <QRadioButton> -#include <QStackedWidget> -#include <QVBoxLayout> - -#ifdef Q_OS_WIN -#include <qt_windows.h> -#endif - using namespace QInstaller; -// -- IntroductionPageImpl - -IntroductionPageImpl::IntroductionPageImpl(QInstaller::PackageManagerCore *core) - : QInstaller::IntroductionPage(core) - , m_updatesFetched(false) - , m_allPackagesFetched(false) -{ - QWidget *widget = new QWidget(this); - QVBoxLayout *layout = new QVBoxLayout(widget); - - m_packageManager = new QRadioButton(tr("Package manager"), this); - m_packageManager->setObjectName(QLatin1String("PackageManagerRadioButton")); - layout->addWidget(m_packageManager); - m_packageManager->setChecked(core->isPackageManager()); - connect(m_packageManager, SIGNAL(toggled(bool)), this, SLOT(setPackageManager(bool))); - - m_updateComponents = new QRadioButton(tr("Update components"), this); - m_updateComponents->setObjectName(QLatin1String("UpdaterRadioButton")); - layout->addWidget(m_updateComponents); - m_updateComponents->setChecked(core->isUpdater()); - connect(m_updateComponents, SIGNAL(toggled(bool)), this, SLOT(setUpdater(bool))); - - m_removeAllComponents = new QRadioButton(tr("Remove all components"), this); - m_removeAllComponents->setObjectName(QLatin1String("UninstallerRadioButton")); - layout->addWidget(m_removeAllComponents); - m_removeAllComponents->setChecked(core->isUninstaller()); - connect(m_removeAllComponents, SIGNAL(toggled(bool)), this, SLOT(setUninstaller(bool))); - connect(m_removeAllComponents, SIGNAL(toggled(bool)), core, SLOT(setCompleteUninstallation(bool))); - - layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding)); - - m_label = new QLabel(this); - m_label->setWordWrap(true); - m_label->setText(tr("Retrieving information from remote installation sources...")); - layout->addWidget(m_label); - - m_progressBar = new QProgressBar(this); - m_progressBar->setRange(0, 0); - layout->addWidget(m_progressBar); - - layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding)); - - m_errorLabel = new QLabel(this); - m_errorLabel->setWordWrap(true); - layout->addWidget(m_errorLabel); - - widget->setLayout(layout); - setWidget(widget); - - core->setCompleteUninstallation(core->isUninstaller()); - - connect(core, SIGNAL(metaJobProgress(int)), this, SLOT(onProgressChanged(int))); - connect(core, SIGNAL(metaJobInfoMessage(QString)), this, SLOT(setMessage(QString))); - connect(core, SIGNAL(coreNetworkSettingsChanged()), this, SLOT(onCoreNetworkSettingsChanged())); - - m_updateComponents->setEnabled(ProductKeyCheck::instance()->hasValidKey()); -} - -int IntroductionPageImpl::nextId() const -{ - if (packageManagerCore()->isUninstaller()) - return PackageManagerCore::ReadyForInstallation; - - if (packageManagerCore()->isUpdater() || packageManagerCore()->isPackageManager()) - return PackageManagerCore::ComponentSelection; - - return QInstaller::IntroductionPage::nextId(); -} - -bool IntroductionPageImpl::validatePage() -{ - PackageManagerCore *core = packageManagerCore(); - if (core->isUninstaller()) - return true; - - setComplete(false); - if (!validRepositoriesAvailable()) { - setErrorMessage(QLatin1String("<font color=\"red\">") + tr("At least one valid and enabled " - "repository required for this action to succeed.") + QLatin1String("</font>")); - return isComplete(); - } - - gui()->setSettingsButtonEnabled(false); - const bool maintanence = core->isUpdater() || core->isPackageManager(); - if (maintanence) { - showAll(); - setMaintenanceToolsEnabled(false); - } else { - showMetaInfoUdate(); - } - - // fetch updater packages - if (core->isUpdater()) { - if (!m_updatesFetched) { - m_updatesFetched = core->fetchRemotePackagesTree(); - if (!m_updatesFetched) - setErrorMessage(core->error()); - } - - callControlScript(QLatin1String("UpdaterSelectedCallback")); - - if (m_updatesFetched) { - if (core->updaterComponents().count() <= 0) - setErrorMessage(QLatin1String("<b>") + tr("No updates available.") + QLatin1String("</b>")); - else - setComplete(true); - } - } - - // fetch common packages - if (core->isInstaller() || core->isPackageManager()) { - bool localPackagesTreeFetched = false; - if (!m_allPackagesFetched) { - // first try to fetch the server side packages tree - m_allPackagesFetched = core->fetchRemotePackagesTree(); - if (!m_allPackagesFetched) { - QString error = core->error(); - if (core->isPackageManager() && core->status() != PackageManagerCore::ForceUpdate) { - // if that fails and we're in maintenance mode, try to fetch local installed tree - localPackagesTreeFetched = core->fetchLocalPackagesTree(); - if (localPackagesTreeFetched) { - // if that succeeded, adjust error message - error = QLatin1String("<font color=\"red\">") + error + tr(" Only local package " - "management available.") + QLatin1String("</font>"); - } - } - setErrorMessage(error); - } - } - - callControlScript(QLatin1String("PackageManagerSelectedCallback")); - - if (m_allPackagesFetched | localPackagesTreeFetched) - setComplete(true); - } - - if (maintanence) { - showMaintenanceTools(); - setMaintenanceToolsEnabled(true); - } else { - hideAll(); - } - gui()->setSettingsButtonEnabled(true); - - return isComplete(); -} - -void IntroductionPageImpl::showAll() -{ - showWidgets(true); -} - -void IntroductionPageImpl::hideAll() -{ - showWidgets(false); -} - -void IntroductionPageImpl::showMetaInfoUdate() -{ - showWidgets(false); - m_label->setVisible(true); - m_progressBar->setVisible(true); -} - -void IntroductionPageImpl::showMaintenanceTools() -{ - showWidgets(true); - m_label->setVisible(false); - m_progressBar->setVisible(false); -} - -void IntroductionPageImpl::setMaintenanceToolsEnabled(bool enable) -{ - m_packageManager->setEnabled(enable); - m_updateComponents->setEnabled(enable && ProductKeyCheck::instance()->hasValidKey()); - m_removeAllComponents->setEnabled(enable); -} - -// -- public slots - -void IntroductionPageImpl::setMessage(const QString &msg) -{ - m_label->setText(msg); -} - -void IntroductionPageImpl::onProgressChanged(int progress) -{ - m_progressBar->setRange(0, 100); - m_progressBar->setValue(progress); -} - -void IntroductionPageImpl::setErrorMessage(const QString &error) -{ - QPalette palette; - const PackageManagerCore::Status s = packageManagerCore()->status(); - if (s == PackageManagerCore::Failure || s == PackageManagerCore::Failure) { - palette.setColor(QPalette::WindowText, Qt::red); - } else { - palette.setColor(QPalette::WindowText, palette.color(QPalette::WindowText)); - } - - m_errorLabel->setText(error); - m_errorLabel->setPalette(palette); -} - -void IntroductionPageImpl::callControlScript(const QString &callback) -{ - // Initialize the gui. Needs to be done after check repositories as only then the ui can handle - // hide of pages depending on the components. - gui()->init(); - gui()->callControlScriptMethod(callback); -} - -bool IntroductionPageImpl::validRepositoriesAvailable() const -{ - const PackageManagerCore *const core = packageManagerCore(); - bool valid = (core->isInstaller() && core->isOfflineOnly()) || core->isUninstaller(); - - if (!valid) { - foreach (const Repository &repo, core->settings().repositories()) { - if (repo.isEnabled() && repo.isValid()) { - valid = true; - break; - } - } - } - return valid; -} - -// -- private slots - -void IntroductionPageImpl::setUpdater(bool value) -{ - if (value) { - entering(); - gui()->showSettingsButton(true); - packageManagerCore()->setUpdater(); - emit packageManagerCoreTypeChanged(); - } -} - -void IntroductionPageImpl::setUninstaller(bool value) -{ - if (value) { - entering(); - gui()->showSettingsButton(false); - packageManagerCore()->setUninstaller(); - emit packageManagerCoreTypeChanged(); - } -} - -void IntroductionPageImpl::setPackageManager(bool value) -{ - if (value) { - entering(); - gui()->showSettingsButton(true); - packageManagerCore()->setPackageManager(); - emit packageManagerCoreTypeChanged(); - } -} - -void IntroductionPageImpl::onCoreNetworkSettingsChanged() -{ - m_updatesFetched = false; - m_allPackagesFetched = false; -} - -// -- private - -void IntroductionPageImpl::entering() -{ - setComplete(true); - showWidgets(false); - setMessage(QString()); - setErrorMessage(QString()); - setButtonText(QWizard::CancelButton, tr("Quit")); - - m_progressBar->setValue(0); - m_progressBar->setRange(0, 0); - PackageManagerCore *core = packageManagerCore(); - if (core->isUninstaller() ||core->isUpdater() || core->isPackageManager()) { - showMaintenanceTools(); - setMaintenanceToolsEnabled(true); - } - setSettingsButtonRequested((!core->isOfflineOnly()) && (!core->isUninstaller())); -} - -void IntroductionPageImpl::leaving() -{ - m_progressBar->setValue(0); - m_progressBar->setRange(0, 0); - setButtonText(QWizard::CancelButton, gui()->defaultButtonText(QWizard::CancelButton)); -} - -void IntroductionPageImpl::showWidgets(bool show) -{ - m_label->setVisible(show); - m_progressBar->setVisible(show); - m_packageManager->setVisible(show); - m_updateComponents->setVisible(show); - m_removeAllComponents->setVisible(show); -} - - -// -- TargetDirectoryPageImpl - -/*! - A custom target directory selection based due to the no-space restriction... -*/ -TargetDirectoryPageImpl::TargetDirectoryPageImpl(PackageManagerCore *core) - : TargetDirectoryPage(core) -{ - QPalette palette; - palette.setColor(QPalette::WindowText, Qt::red); - - m_warningLabel = new QLabel(this); - m_warningLabel->setPalette(palette); - m_warningLabel->setWordWrap(true); - - insertWidget(m_warningLabel, QLatin1String("MessageLabel"), 2); -} - -QString TargetDirectoryPageImpl::targetDirWarning() const -{ - if (targetDir().isEmpty()) { - return TargetDirectoryPageImpl::tr("The installation path cannot be empty, please specify a valid " - "folder."); - } - - if (QDir(targetDir()).isRelative()) { - return TargetDirectoryPageImpl::tr("The installation path cannot be relative, please specify an " - "absolute path."); - } - - QDir target(targetDir()); - target = target.canonicalPath(); - - if (target.isRoot()) { - return TargetDirectoryPageImpl::tr("As the install directory is completely deleted, installing " - "in %1 is forbidden.").arg(QDir::toNativeSeparators(QDir::rootPath())); - } - - if (target == QDir::home()) { - return TargetDirectoryPageImpl::tr("As the install directory is completely deleted, installing " - "in %1 is forbidden.").arg(QDir::toNativeSeparators(QDir::homePath())); - } - - QString dir = QDir::toNativeSeparators(targetDir()); -#ifdef Q_OS_WIN - // folder length (set by user) + maintenance tool name length (no extension) + extra padding - if ((dir.length() + packageManagerCore()->settings().uninstallerName().length() + 20) >= MAX_PATH) { - return TargetDirectoryPageImpl::tr("The path you have entered is too long, please make sure to " - "specify a valid path."); - } - - if (dir.count() >= 3 && dir.indexOf(QRegExp(QLatin1String("[a-zA-Z]:"))) == 0 - && dir.at(2) != QLatin1Char('\\')) { - return TargetDirectoryPageImpl::tr("The path you have entered is not valid, please make sure to " - "specify a valid drive."); - } - - // remove e.g. "c:" - dir = dir.mid(2); -#endif - - QString ambiguousChars = QLatin1String("[~<>|?*!@#$%^&:,; ]"); - if (packageManagerCore()->settings().allowSpaceInPath()) - ambiguousChars.remove(QLatin1Char(' ')); - - // check if there are not allowed characters in the target path - if (dir.contains(QRegExp(ambiguousChars))) { - return TargetDirectoryPageImpl::tr("The installation path must not contain %1, " - "please specify a valid folder.").arg(ambiguousChars); - } - - dir = targetDir(); - if (!packageManagerCore()->settings().allowNonAsciiCharacters()) { - for (int i = 0; i < dir.length(); ++i) { - if (dir.at(i).unicode() & 0xff80) { - return TargetDirectoryPageImpl::tr("The path or installation directory contains non ASCII " - "characters. This is currently not supported! Please choose a different path or " - "installation directory."); - } - } - } - - return QString(); -} - -bool TargetDirectoryPageImpl::isComplete() const -{ - m_warningLabel->setText(targetDirWarning()); - return m_warningLabel->text().isEmpty(); -} - -bool TargetDirectoryPageImpl::askQuestion(const QString &identifier, const QString &message) -{ - QMessageBox::StandardButton bt = - MessageBoxHandler::warning(MessageBoxHandler::currentBestSuitParent(), identifier, - TargetDirectoryPageImpl::tr("Warning"), message, QMessageBox::Yes | QMessageBox::No); - return bt == QMessageBox::Yes; -} - -bool TargetDirectoryPageImpl::failWithError(const QString &identifier, const QString &message) -{ - MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(), identifier, - TargetDirectoryPageImpl::tr("Error"), message); - return false; -} - -bool TargetDirectoryPageImpl::validatePage() -{ - if (!isVisible()) - return true; - - const QString remove = packageManagerCore()->value(QLatin1String("RemoveTargetDir")); - if (!QVariant(remove).toBool()) - return true; - - const QString targetDir = this->targetDir(); - const QDir dir(targetDir); - // the directory exists and is empty... - if (dir.exists() && dir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot).isEmpty()) - return true; - - const QFileInfo fi(targetDir); - if (fi.isDir()) { - QString fileName = packageManagerCore()->settings().uninstallerName(); -#if defined(Q_OS_MAC) - if (QFileInfo(QCoreApplication::applicationDirPath() + QLatin1String("/../..")).isBundle()) - fileName += QLatin1String(".app/Contents/MacOS/") + fileName; -#elif defined(Q_OS_WIN) - fileName += QLatin1String(".exe"); -#endif - - QFileInfo fi2(targetDir + QDir::separator() + fileName); - if (fi2.exists()) { - return failWithError(QLatin1String("TargetDirectoryInUse"), tr("The folder you selected already " - "exists and contains an installation. Choose a different target for installation.")); - } - - return askQuestion(QLatin1String("OverwriteTargetDirectory"), - tr("You have selected an existing, non-empty folder for installation.\nNote that it will be " - "completely wiped on uninstallation of this application.\nIt is not advisable to install into " - "this folder as installation might fail.\nDo you want to continue?")); - } else if (fi.isFile() || fi.isSymLink()) { - return failWithError(QLatin1String("WrongTargetDirectory"), tr("You have selected an existing file " - "or symlink, please choose a different target for installation.")); - } - return true; -} - - // -- InstallerGui InstallerGui::InstallerGui(PackageManagerCore *core) @@ -530,8 +53,9 @@ InstallerGui::InstallerGui(PackageManagerCore *core) "constructed.").arg(id))); setPage(id, page); } - setPage(PackageManagerCore::Introduction, new IntroductionPageImpl(core)); - setPage(PackageManagerCore::TargetDirectory, new TargetDirectoryPageImpl(core)); + + setPage(PackageManagerCore::Introduction, new IntroductionPage(core)); + setPage(PackageManagerCore::TargetDirectory, new TargetDirectoryPage(core)); setPage(PackageManagerCore::ComponentSelection, new ComponentSelectionPage(core)); setPage(PackageManagerCore::LicenseCheck, new LicenseAgreementPage(core)); #ifdef Q_OS_WIN @@ -544,6 +68,10 @@ InstallerGui::InstallerGui(PackageManagerCore *core) void InstallerGui::init() { + foreach (const int id, pageIds()) { + packageManagerCore()->controlScriptEngine()->addQObjectChildren(page(id)); + packageManagerCore()->componentScriptEngine()->addQObjectChildren(page(id)); + } } @@ -560,7 +88,7 @@ MaintenanceGui::MaintenanceGui(PackageManagerCore *core) setPage(id, page); } - IntroductionPageImpl *intro = new IntroductionPageImpl(core); + IntroductionPage *intro = new IntroductionPage(core); connect(intro, SIGNAL(packageManagerCoreTypeChanged()), this, SLOT(updateRestartPage())); setPage(PackageManagerCore::Introduction, intro); @@ -580,6 +108,10 @@ MaintenanceGui::MaintenanceGui(PackageManagerCore *core) void MaintenanceGui::init() { + foreach (const int id, pageIds()) { + packageManagerCore()->controlScriptEngine()->addQObjectChildren(page(id)); + packageManagerCore()->componentScriptEngine()->addQObjectChildren(page(id)); + } } void MaintenanceGui::updateRestartPage() diff --git a/src/sdk/installerbasecommons.h b/src/sdk/installerbasecommons.h index 79330eaf7..b3ba68c35 100644 --- a/src/sdk/installerbasecommons.h +++ b/src/sdk/installerbasecommons.h @@ -16,24 +16,17 @@ ** ** 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 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** ** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** ** ** $QT_END_LICENSE$ ** @@ -44,87 +37,6 @@ #include <packagemanagergui.h> -QT_BEGIN_NAMESPACE -class QLabel; -class QString; -class QProgressBar; -QT_END_NAMESPACE - - -// -- IntroductionPageImpl - -class IntroductionPageImpl : public QInstaller::IntroductionPage -{ - Q_OBJECT - -public: - explicit IntroductionPageImpl(QInstaller::PackageManagerCore *core); - - int nextId() const; - bool validatePage(); - - void showAll(); - void hideAll(); - void showMetaInfoUdate(); - void showMaintenanceTools(); - void setMaintenanceToolsEnabled(bool enable); - -public Q_SLOTS: - void onCoreNetworkSettingsChanged(); - void setMessage(const QString &msg); - void onProgressChanged(int progress); - void setErrorMessage(const QString &error); - -Q_SIGNALS: - void packageManagerCoreTypeChanged(); - -private Q_SLOTS: - void setUpdater(bool value); - void setUninstaller(bool value); - void setPackageManager(bool value); - -private: - void entering(); - void leaving(); - - void showWidgets(bool show); - void callControlScript(const QString &callback); - - bool validRepositoriesAvailable() const; - -private: - bool m_updatesFetched; - bool m_updatesCompleted; - bool m_allPackagesFetched; - - QLabel *m_label; - QLabel *m_errorLabel; - QProgressBar *m_progressBar; - QRadioButton *m_packageManager; - QRadioButton *m_updateComponents; - QRadioButton *m_removeAllComponents; -}; - - -// --TargetDirectoryPageImpl - -class TargetDirectoryPageImpl : public QInstaller::TargetDirectoryPage -{ - Q_OBJECT - -public: - explicit TargetDirectoryPageImpl(QInstaller::PackageManagerCore *core); - - QString targetDirWarning() const; - bool isComplete() const; - bool askQuestion(const QString &identifier, const QString &message); - bool failWithError(const QString &identifier, const QString &message); - bool validatePage(); - -private: - QLabel *m_warningLabel; -}; - // -- InstallerGui diff --git a/src/sdk/main.cpp b/src/sdk/main.cpp new file mode 100644 index 000000000..2e698f35d --- /dev/null +++ b/src/sdk/main.cpp @@ -0,0 +1,203 @@ +/************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#include "console.h" +#include "constants.h" +#include "commandlineparser.h" +#include "installerbase.h" +#include "sdkapp.h" +#include "updatechecker.h" + +#include <errors.h> +#include <kdselfrestarter.h> +#include <remoteserver.h> +#include <utils.h> + +#include <QCommandLineParser> +#include <QDateTime> +#include <QNetworkProxyFactory> + +#include <iostream> + +#define QUOTE_(x) #x +#define QUOTE(x) QUOTE_(x) +#define VERSION "IFW Version: \"" QUOTE(IFW_VERSION_STR) "\"" +#define BUILDDATE "Build date: " QUOTE(__DATE__) +#define SHA "Installer Framework SHA1: \"" QUOTE(_GIT_SHA1_) "\"" +static const char PLACEHOLDER[32] = "MY_InstallerCreateDateTime_MY"; + +int main(int argc, char *argv[]) +{ + // increase maximum numbers of file descriptors +#if defined (Q_OS_OSX) + QCoreApplication::setSetuidAllowed(true); + struct rlimit rl; + getrlimit(RLIMIT_NOFILE, &rl); + rl.rlim_cur = qMin((rlim_t) OPEN_MAX, rl.rlim_max); + setrlimit(RLIMIT_NOFILE, &rl); +#endif + + qsrand(QDateTime::currentDateTime().toTime_t()); + + // We need to start either a command line application or a GUI application. Since we + // fail doing so at least on Linux while parsing the argument using a core application + // object and later starting the GUI application, we now parse the arguments first. + CommandLineParser parser; + parser.parse(QInstaller::parseCommandLineArgs(argc, argv)); + + QStringList mutually; + if (parser.isSet(QLatin1String(CommandLineOptions::CheckUpdates))) + mutually << QLatin1String(CommandLineOptions::CheckUpdates); + if (parser.isSet(QLatin1String(CommandLineOptions::Updater))) + mutually << QLatin1String(CommandLineOptions::Updater); + if (parser.isSet(QLatin1String(CommandLineOptions::ManagePackages))) + mutually << QLatin1String(CommandLineOptions::ManagePackages); + + const bool help = parser.isSet(QLatin1String(CommandLineOptions::HelpShort)) + || parser.isSet(QLatin1String(CommandLineOptions::HelpLong)); + if (help + || parser.isSet(QLatin1String(CommandLineOptions::Version)) + || parser.isSet(QLatin1String(CommandLineOptions::FrameworkVersion)) + || mutually.count() > 1) { + Console c; + QCoreApplication app(argc, argv); + + if (parser.isSet(QLatin1String(CommandLineOptions::Version))) { + std::cout << VERSION << std::endl << BUILDDATE << std::endl << SHA << std::endl; + const QDateTime dateTime = QDateTime::fromString(QLatin1String(PLACEHOLDER), + QLatin1String("yyyy-MM-dd - HH:mm:ss")); + if (dateTime.isValid()) + std::cout << "Installer creation time: " << PLACEHOLDER << std::endl; + return EXIT_SUCCESS; + } + + if (parser.isSet(QLatin1String(CommandLineOptions::FrameworkVersion))) { + std::cout << QUOTE(IFW_VERSION_STR) << std::endl; + return EXIT_SUCCESS; + } + + std::cout << qPrintable(parser.helpText()) << std::endl; + if (mutually.count() > 1) { + std::cerr << qPrintable(QString::fromLatin1("The following options are mutually " + "exclusive: %1.").arg(mutually.join(QLatin1String(", ")))) << std::endl; + } + return help ? EXIT_SUCCESS : EXIT_FAILURE; + } + + if (parser.isSet(QLatin1String(CommandLineOptions::StartServer))) { + const QStringList arguments = parser.value(QLatin1String(CommandLineOptions::StartServer)) + .split(QLatin1Char(','), QString::SkipEmptyParts); + + QString port, key; + const QString mode = arguments.value(0); + bool argumentsValid = (mode.compare(QLatin1String(QInstaller::Protocol::ModeDebug), + Qt::CaseInsensitive) == 0); + if (argumentsValid) { + port = arguments.value(1, QString::number(QInstaller::Protocol::DefaultPort)); + key = arguments.value(2, QLatin1String(QInstaller::Protocol::DefaultAuthorizationKey)); + } else { + port = arguments.value(1); + key = arguments.value(2); + } + + const bool production = (mode.compare(QLatin1String(QInstaller::Protocol::ModeProduction), + Qt::CaseInsensitive) == 0); + if (production) + argumentsValid = (!key.isEmpty()) && (!port.isEmpty()); + + SDKApp<QCoreApplication> app(argc, argv); + if (!argumentsValid) { + Console c; + std::cout << qPrintable(parser.helpText()) << std::endl; + std::cerr << "Wrong argument(s) for option --startserver." << std::endl; + return EXIT_FAILURE; + } + + QInstaller::RemoteServer *server = new QInstaller::RemoteServer; + QObject::connect(server, SIGNAL(destroyed()), &app, SLOT(quit())); + server->init(port.toInt(), key, (production ? QInstaller::Protocol::Mode::Production + : QInstaller::Protocol::Mode::Debug)); + + server->start(); + return app.exec(); + } + + try { + QScopedPointer<Console> console; + if (parser.isSet(QLatin1String(CommandLineOptions::VerboseShort)) + || parser.isSet(QLatin1String(CommandLineOptions::VerboseLong))) { + console.reset(new Console); + QInstaller::setVerbose(true); + } + + // On Windows we need the console window from above, we are a GUI application. + const QStringList unknownOptionNames = parser.unknownOptionNames(); + if (!unknownOptionNames.isEmpty()) { + const QString options = unknownOptionNames.join(QLatin1String(", ")); + std::cerr << "Unknown option: " << qPrintable(options) << std::endl; + } + + if (parser.isSet(QLatin1String(CommandLineOptions::Proxy))) { + // Make sure we honor the system's proxy settings +#if defined(Q_OS_UNIX) && !defined(Q_OS_OSX) + QUrl proxyUrl(QString::fromLatin1(qgetenv("http_proxy"))); + if (proxyUrl.isValid()) { + QNetworkProxy proxy(QNetworkProxy::HttpProxy, proxyUrl.host(), proxyUrl.port(), + proxyUrl.userName(), proxyUrl.password()); + QNetworkProxy::setApplicationProxy(proxy); + } +#else + QNetworkProxyFactory::setUseSystemConfiguration(true); +#endif + } + + if (parser.isSet(QLatin1String(CommandLineOptions::CheckUpdates))) + return UpdateChecker(argc, argv).check(); + + if (QInstaller::isVerbose()) + std::cout << VERSION << std::endl << BUILDDATE << std::endl << SHA << std::endl; + + const KDSelfRestarter restarter(argc, argv); + return InstallerBase(argc, argv).run(); + + } catch (const QInstaller::Error &e) { + std::cerr << qPrintable(e.message()) << std::endl; + } catch (const std::exception &e) { + std::cerr << e.what() << std::endl; + } catch (...) { + std::cerr << "Unknown exception caught." << std::endl; + } + + return EXIT_FAILURE; +} diff --git a/src/sdk/sdk.pro b/src/sdk/sdk.pro index 51098e3b3..1227ed1c8 100644 --- a/src/sdk/sdk.pro +++ b/src/sdk/sdk.pro @@ -4,16 +4,12 @@ TARGET = installerbase include(../../installerfw.pri) -QT += network script xml - -isEqual(QT_MAJOR_VERSION, 5) { - QT += widgets - # add the minimal plugin in static case to be able to start the installer - # headless with: installer-binary -platform minimal - # using QT += qpa_minimal_plugin would result in a minimal only compiled version - !win32:CONFIG(static, static|shared) { +QT += network qml xml widgets +# add the minimal plugin in static build to be able to start the installer headless with: +# installer-binary -platform minimal +# using QT += qpa_minimal_plugin would result in a minimal only compiled version +!win32:CONFIG(static, static|shared) { QTPLUGIN += qminimal - } } DESTDIR = $$IFW_APP_PATH @@ -110,30 +106,32 @@ exists($$LRELEASE) { } FORMS += settingsdialog.ui -HEADERS += installerbase_p.h \ +HEADERS += \ tabcontroller.h \ installerbasecommons.h \ settingsdialog.h \ console.h \ - sdkapp.h - -SOURCES = installerbase.cpp \ - installerbase_p.cpp \ + sdkapp.h \ + updatechecker.h \ + installerbase.h \ + constants.h \ + commandlineparser.h + +SOURCES = \ + main.cpp \ + installerbase.cpp \ tabcontroller.cpp \ installerbasecommons.cpp \ - settingsdialog.cpp + settingsdialog.cpp \ + updatechecker.cpp \ + commandlineparser.cpp win32 { # Force to overwrite the default manifest file with our own extended version. - isEqual(QT_MAJOR_VERSION, 4) { - !win32-g++* { - win32:RC_FILE = installerbase.rc - QMAKE_POST_LINK += $$quote(mt.exe -updateresource:$$IFW_APP_PATH/$${TARGET}.exe -manifest \"$${IFW_SOURCE_TREE}\\src\\sdk\\installerbase.manifest\") - } - } else { - RC_FILE = installerbase_qt5.rc - QMAKE_MANIFEST = installerbase.manifest - } + RC_FILE = installerbase_qt5.rc + QMAKE_MANIFEST = installerbase.manifest + + SOURCES += console_win.cpp } macx:include(../../no_app_bundle.pri) diff --git a/src/sdk/sdkapp.h b/src/sdk/sdkapp.h index 78d586560..1a5520c85 100644 --- a/src/sdk/sdkapp.h +++ b/src/sdk/sdkapp.h @@ -16,24 +16,17 @@ ** ** 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 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** ** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** ** ** $QT_END_LICENSE$ ** @@ -42,9 +35,15 @@ #ifndef SDKAPP_H #define SDKAPP_H -#include "console.h" +#include <binarycontent.h> +#include <binaryformat.h> +#include <fileio.h> +#include <fileutils.h> #include <QApplication> +#include <QDir> +#include <QFileInfo> +#include <QResource> template<class T> class SDKApp : public T @@ -52,33 +51,99 @@ class SDKApp : public T public: SDKApp(int& argc, char** argv) : T(argc, argv) - , m_console(0) { } virtual ~SDKApp() { - delete m_console; - } - - void setVerbose() - { - if (!m_console) - m_console = new Console; + foreach (const QByteArray &ba, m_resourceMappings) + QResource::unregisterResource((const uchar*) ba.data(), QLatin1String(":/metadata")); } - virtual bool notify(QObject *receiver, QEvent *event) + bool notify(QObject *receiver, QEvent *event) { try { return T::notify(receiver, event); } catch (std::exception &e) { qFatal("Exception thrown: %s", e.what()); + } catch (...) { + qFatal("Unknown exception caught."); } return false; } + /*! + Returns the installer / maintenance tool binary. In case of an installer this will be the + installer binary itself, which contains the binary layout and the binary content. In case + of an maintenance tool, it will return a binary that has just a binary layout append. + + Note on OS X: For compatibility reason this function will return the a .dat file located + inside the resource folder in the application bundle, as on OS X the binary layout cannot + be appended to the actual installer / maintenance tool binary itself because of signing. + */ + QString binaryFile() const + { + QString binaryFile = QCoreApplication::applicationFilePath(); +#ifdef Q_OS_OSX + // The installer binary on OSX does not contain the binary content, it's put into + // the resources folder as separate file. Adjust the actual binary path. No error + // checking here since we will fail later while reading the binary content. + QDir resourcePath(QFileInfo(binaryFile).dir()); + resourcePath.cdUp(); + resourcePath.cd(QLatin1String("Resources")); + return resourcePath.filePath(QLatin1String("installer.dat")); +#endif + return binaryFile; + } + + /*! + Returns the corresponding .dat file for a given installer / maintenance tool binary or an + empty string if it fails to find one. + */ + QString datFile(const QString &binaryFile) const + { + QFile file(binaryFile); + QInstaller::openForRead(&file); + const quint64 cookiePos = QInstaller::BinaryContent::findMagicCookie(&file, + QInstaller::BinaryContent::MagicCookie); + if (!file.seek(cookiePos - sizeof(qint64))) // seek to read the marker + return QString(); // ignore error, we will fail later + + const qint64 magicMarker = QInstaller::retrieveInt64(&file); + if (magicMarker == QInstaller::BinaryContent::MagicUninstallerMarker) { + QFileInfo fi(binaryFile); + QString bundlePath; + if (QInstaller::isInBundle(fi.absoluteFilePath(), &bundlePath)) + fi.setFile(bundlePath); + return fi.absoluteDir().filePath(fi.baseName() + QLatin1String(".dat")); + } + return QString(); + } + + void registerMetaResources(const QInstaller::ResourceCollection &collection) + { + foreach (const QSharedPointer<QInstaller::Resource> &resource, collection.resources()) { + const bool isOpen = resource->isOpen(); + if ((!isOpen) && (!resource->open())) + continue; + + if (!resource->seek(0)) + continue; + + const QByteArray ba = resource->readAll(); + if (ba.isEmpty()) + continue; + + if (QResource::registerResource((const uchar*) ba.data(), QLatin1String(":/metadata"))) + m_resourceMappings.append(ba); + + if (!isOpen) // If we reach that point, either the resource was opened already... + resource->close(); // or we did open it and have to close it again. + } + } + private: - Console *m_console; + QList<QByteArray> m_resourceMappings; }; #endif // SDKAPP_H diff --git a/src/sdk/settingsdialog.cpp b/src/sdk/settingsdialog.cpp index 305fc051a..3281cc45d 100644 --- a/src/sdk/settingsdialog.cpp +++ b/src/sdk/settingsdialog.cpp @@ -16,24 +16,17 @@ ** ** 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 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** ** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** ** ** $QT_END_LICENSE$ ** @@ -229,16 +222,10 @@ SettingsDialog::SettingsDialog(PackageManagerCore *core, QWidget *parent) const QNetworkProxy &ftpProxy = settings.ftpProxy(); m_ui->m_ftpProxy->setText(ftpProxy.hostName()); m_ui->m_ftpProxyPort->setValue(ftpProxy.port()); - m_ui->m_ftpProxyUser->setText(ftpProxy.user()); - m_ui->m_ftpProxyPass->setText(ftpProxy.password()); - m_ui->m_ftpProxyNeedsAuth->setChecked(!ftpProxy.user().isEmpty() | !ftpProxy.password().isEmpty()); const QNetworkProxy &httpProxy = settings.httpProxy(); m_ui->m_httpProxy->setText(httpProxy.hostName()); m_ui->m_httpProxyPort->setValue(httpProxy.port()); - m_ui->m_httpProxyUser->setText(httpProxy.user()); - m_ui->m_httpProxyPass->setText(httpProxy.password()); - m_ui->m_httpProxyNeedsAuth->setChecked(!httpProxy.user().isEmpty() | !httpProxy.password().isEmpty()); connect(m_ui->m_addRepository, SIGNAL(clicked()), this, SLOT(addRepository())); connect(m_ui->m_showPasswords, SIGNAL(clicked()), this, SLOT(updatePasswords())); @@ -291,12 +278,12 @@ void SettingsDialog::accept() if (newSettings.proxyType() == Settings::UserDefinedProxy) { // update ftp proxy settings newSettings.setFtpProxy(QNetworkProxy(QNetworkProxy::HttpProxy, m_ui->m_ftpProxy->text(), - m_ui->m_ftpProxyPort->value(), m_ui->m_ftpProxyUser->text(), m_ui->m_ftpProxyPass->text())); + m_ui->m_ftpProxyPort->value())); settingsChanged |= (settings.ftpProxy() != newSettings.ftpProxy()); // update http proxy settings newSettings.setHttpProxy(QNetworkProxy(QNetworkProxy::HttpProxy, m_ui->m_httpProxy->text(), - m_ui->m_httpProxyPort->value(), m_ui->m_httpProxyUser->text(), m_ui->m_httpProxyPass->text())); + m_ui->m_httpProxyPort->value())); settingsChanged |= (settings.httpProxy() != newSettings.httpProxy()); } @@ -428,13 +415,8 @@ void SettingsDialog::setupRepositoriesTreeWidget() for (int i = 0; i < treeWidget->model()->columnCount(); ++i) treeWidget->resizeColumnToContents(i); -#if QT_VERSION < 0x050000 - treeWidget->header()->setResizeMode(0, QHeaderView::Fixed); - treeWidget->header()->setResizeMode(1, QHeaderView::Fixed); -#else treeWidget->header()->setSectionResizeMode(0, QHeaderView::Fixed); treeWidget->header()->setSectionResizeMode(1, QHeaderView::Fixed); -#endif treeWidget->header()->setMinimumSectionSize(treeWidget->columnWidth(1)); treeWidget->setItemDelegateForColumn(0, new PasswordDelegate(treeWidget)); diff --git a/src/sdk/settingsdialog.h b/src/sdk/settingsdialog.h index 942adfc2f..fb0253d26 100644 --- a/src/sdk/settingsdialog.h +++ b/src/sdk/settingsdialog.h @@ -16,24 +16,17 @@ ** ** 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 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** ** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** ** ** $QT_END_LICENSE$ ** diff --git a/src/sdk/settingsdialog.ui b/src/sdk/settingsdialog.ui index d3ca959a6..3683f3cd1 100644 --- a/src/sdk/settingsdialog.ui +++ b/src/sdk/settingsdialog.ui @@ -56,253 +56,118 @@ </item> <item> <widget class="QWidget" name="m_rootWidget" native="true"> - <layout class="QVBoxLayout" name="verticalLayout_6"> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <item> - <layout class="QVBoxLayout" name="m_httpRootLayout"> - <item> - <layout class="QHBoxLayout" name="m_httpProxyLayout"> - <item> - <widget class="QLabel" name="m_httpProxyLabel"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>HTTP proxy:</string> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="m_httpProxy"> - <property name="enabled"> - <bool>false</bool> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="m_httpProxyPortLabel"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Port:</string> - </property> - </widget> - </item> - <item> - <widget class="QSpinBox" name="m_httpProxyPort"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="maximum"> - <number>65535</number> - </property> - </widget> - </item> - </layout> - </item> - <item> - <widget class="QCheckBox" name="m_httpProxyNeedsAuth"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>HTTP proxy requires authentication</string> - </property> - </widget> - </item> - <item> - <widget class="QWidget" name="m_httpAuthWidget" native="true"> - <property name="enabled"> - <bool>false</bool> - </property> - <layout class="QGridLayout" name="gridLayout_2"> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <item row="0" column="0"> - <widget class="QLabel" name="m_httpProxyUserLabel"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Username:</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLineEdit" name="m_httpProxyUser"> - <property name="enabled"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="m_httpProxyPassLabel"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Password:</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLineEdit" name="m_httpProxyPass"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="echoMode"> - <enum>QLineEdit::Password</enum> - </property> - </widget> - </item> - </layout> - </widget> - </item> - </layout> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="0" column="0"> + <widget class="QLabel" name="m_httpProxyLabel"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>HTTP proxy:</string> + </property> + </widget> </item> - <item> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> + <item row="0" column="1"> + <widget class="QLineEdit" name="m_httpProxy"> + <property name="enabled"> + <bool>false</bool> </property> - <property name="sizeType"> - <enum>QSizePolicy::Fixed</enum> + </widget> + </item> + <item row="0" column="2"> + <widget class="QLabel" name="m_httpProxyPortLabel"> + <property name="enabled"> + <bool>false</bool> </property> - <property name="sizeHint" stdset="0"> - <size> - <width>10</width> - <height>10</height> - </size> + <property name="text"> + <string>Port:</string> </property> - </spacer> + </widget> + </item> + <item row="0" column="3"> + <widget class="QSpinBox" name="m_httpProxyPort"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="maximum"> + <number>65535</number> + </property> + </widget> </item> - <item> - <layout class="QVBoxLayout" name="m_ftpRootLayout"> - <item> - <layout class="QHBoxLayout" name="m_ftpProxyLayout"> - <item> - <widget class="QLabel" name="m_ftpProxyLabel"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>FTP proxy:</string> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="m_ftpProxy"> - <property name="enabled"> - <bool>false</bool> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="m_ftpProxyPortLabel"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Port:</string> - </property> - </widget> - </item> - <item> - <widget class="QSpinBox" name="m_ftpProxyPort"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="maximum"> - <number>65535</number> - </property> - </widget> - </item> - </layout> - </item> - <item> - <widget class="QCheckBox" name="m_ftpProxyNeedsAuth"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>FTP proxy requires authentication</string> - </property> - </widget> - </item> - <item> - <widget class="QWidget" name="m_ftpAuthWidget" native="true"> - <property name="enabled"> - <bool>false</bool> - </property> - <layout class="QGridLayout" name="gridLayout"> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <item row="0" column="0"> - <widget class="QLabel" name="m_ftpProxyUserLabel"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Username:</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLineEdit" name="m_ftpProxyUser"> - <property name="enabled"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="m_ftpProxyPassLabel"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Password:</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLineEdit" name="m_ftpProxyPass"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="echoMode"> - <enum>QLineEdit::Password</enum> - </property> - </widget> - </item> - </layout> - </widget> - </item> - </layout> + <item row="1" column="0"> + <widget class="QWidget" name="m_httpAuthWidget" native="true"> + <property name="enabled"> + <bool>false</bool> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + </layout> + </widget> </item> - <item> + <item row="2" column="0"> + <widget class="QLabel" name="m_ftpProxyLabel"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>FTP proxy:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="m_ftpProxy"> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="2" column="2"> + <widget class="QLabel" name="m_ftpProxyPortLabel"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Port:</string> + </property> + </widget> + </item> + <item row="2" column="3"> + <widget class="QSpinBox" name="m_ftpProxyPort"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="maximum"> + <number>65535</number> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QWidget" name="m_ftpAuthWidget" native="true"> + <property name="enabled"> + <bool>false</bool> + </property> + <layout class="QGridLayout" name="gridLayout"> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + </layout> + </widget> + </item> + <item row="3" column="2"> <spacer name="verticalSpacer_2"> <property name="orientation"> <enum>Qt::Vertical</enum> @@ -478,22 +343,6 @@ <connection> <sender>m_manualProxySettings</sender> <signal>toggled(bool)</signal> - <receiver>m_httpProxyPortLabel</receiver> - <slot>setEnabled(bool)</slot> - <hints> - <hint type="sourcelabel"> - <x>349</x> - <y>78</y> - </hint> - <hint type="destinationlabel"> - <x>347</x> - <y>96</y> - </hint> - </hints> - </connection> - <connection> - <sender>m_manualProxySettings</sender> - <signal>toggled(bool)</signal> <receiver>m_httpProxyPort</receiver> <slot>setEnabled(bool)</slot> <hints> @@ -510,32 +359,16 @@ <connection> <sender>m_manualProxySettings</sender> <signal>toggled(bool)</signal> - <receiver>m_ftpProxyLabel</receiver> - <slot>setEnabled(bool)</slot> - <hints> - <hint type="sourcelabel"> - <x>61</x> - <y>76</y> - </hint> - <hint type="destinationlabel"> - <x>109</x> - <y>243</y> - </hint> - </hints> - </connection> - <connection> - <sender>m_manualProxySettings</sender> - <signal>toggled(bool)</signal> - <receiver>m_ftpProxy</receiver> + <receiver>m_httpProxyPortLabel</receiver> <slot>setEnabled(bool)</slot> <hints> <hint type="sourcelabel"> - <x>204</x> + <x>349</x> <y>78</y> </hint> <hint type="destinationlabel"> - <x>203</x> - <y>248</y> + <x>347</x> + <y>96</y> </hint> </hints> </connection> @@ -558,48 +391,48 @@ <connection> <sender>m_manualProxySettings</sender> <signal>toggled(bool)</signal> - <receiver>m_ftpProxyPort</receiver> + <receiver>m_ftpProxyLabel</receiver> <slot>setEnabled(bool)</slot> <hints> <hint type="sourcelabel"> - <x>406</x> - <y>78</y> + <x>61</x> + <y>76</y> </hint> <hint type="destinationlabel"> - <x>380</x> - <y>252</y> + <x>109</x> + <y>243</y> </hint> </hints> </connection> <connection> <sender>m_manualProxySettings</sender> <signal>toggled(bool)</signal> - <receiver>m_httpProxyNeedsAuth</receiver> + <receiver>m_ftpProxy</receiver> <slot>setEnabled(bool)</slot> <hints> <hint type="sourcelabel"> - <x>53</x> - <y>75</y> + <x>204</x> + <y>78</y> </hint> <hint type="destinationlabel"> - <x>100</x> - <y>129</y> + <x>203</x> + <y>248</y> </hint> </hints> </connection> <connection> <sender>m_manualProxySettings</sender> <signal>toggled(bool)</signal> - <receiver>m_ftpProxyNeedsAuth</receiver> + <receiver>m_ftpProxyPort</receiver> <slot>setEnabled(bool)</slot> <hints> <hint type="sourcelabel"> - <x>88</x> - <y>74</y> + <x>406</x> + <y>78</y> </hint> <hint type="destinationlabel"> - <x>95</x> - <y>274</y> + <x>380</x> + <y>252</y> </hint> </hints> </connection> @@ -635,133 +468,5 @@ </hint> </hints> </connection> - <connection> - <sender>m_ftpProxyNeedsAuth</sender> - <signal>toggled(bool)</signal> - <receiver>m_ftpProxyUserLabel</receiver> - <slot>setEnabled(bool)</slot> - <hints> - <hint type="sourcelabel"> - <x>82</x> - <y>283</y> - </hint> - <hint type="destinationlabel"> - <x>77</x> - <y>303</y> - </hint> - </hints> - </connection> - <connection> - <sender>m_ftpProxyNeedsAuth</sender> - <signal>toggled(bool)</signal> - <receiver>m_ftpProxyUser</receiver> - <slot>setEnabled(bool)</slot> - <hints> - <hint type="sourcelabel"> - <x>180</x> - <y>284</y> - </hint> - <hint type="destinationlabel"> - <x>170</x> - <y>304</y> - </hint> - </hints> - </connection> - <connection> - <sender>m_ftpProxyNeedsAuth</sender> - <signal>toggled(bool)</signal> - <receiver>m_ftpProxyPass</receiver> - <slot>setEnabled(bool)</slot> - <hints> - <hint type="sourcelabel"> - <x>224</x> - <y>283</y> - </hint> - <hint type="destinationlabel"> - <x>223</x> - <y>330</y> - </hint> - </hints> - </connection> - <connection> - <sender>m_ftpProxyNeedsAuth</sender> - <signal>toggled(bool)</signal> - <receiver>m_ftpProxyPassLabel</receiver> - <slot>setEnabled(bool)</slot> - <hints> - <hint type="sourcelabel"> - <x>317</x> - <y>282</y> - </hint> - <hint type="destinationlabel"> - <x>122</x> - <y>335</y> - </hint> - </hints> - </connection> - <connection> - <sender>m_httpProxyNeedsAuth</sender> - <signal>toggled(bool)</signal> - <receiver>m_httpProxyUserLabel</receiver> - <slot>setEnabled(bool)</slot> - <hints> - <hint type="sourcelabel"> - <x>81</x> - <y>134</y> - </hint> - <hint type="destinationlabel"> - <x>70</x> - <y>154</y> - </hint> - </hints> - </connection> - <connection> - <sender>m_httpProxyNeedsAuth</sender> - <signal>toggled(bool)</signal> - <receiver>m_httpProxyPassLabel</receiver> - <slot>setEnabled(bool)</slot> - <hints> - <hint type="sourcelabel"> - <x>87</x> - <y>137</y> - </hint> - <hint type="destinationlabel"> - <x>84</x> - <y>186</y> - </hint> - </hints> - </connection> - <connection> - <sender>m_httpProxyNeedsAuth</sender> - <signal>toggled(bool)</signal> - <receiver>m_httpProxyUser</receiver> - <slot>setEnabled(bool)</slot> - <hints> - <hint type="sourcelabel"> - <x>183</x> - <y>135</y> - </hint> - <hint type="destinationlabel"> - <x>182</x> - <y>154</y> - </hint> - </hints> - </connection> - <connection> - <sender>m_httpProxyNeedsAuth</sender> - <signal>toggled(bool)</signal> - <receiver>m_httpProxyPass</receiver> - <slot>setEnabled(bool)</slot> - <hints> - <hint type="sourcelabel"> - <x>287</x> - <y>134</y> - </hint> - <hint type="destinationlabel"> - <x>285</x> - <y>182</y> - </hint> - </hints> - </connection> </connections> </ui> diff --git a/src/sdk/tabcontroller.cpp b/src/sdk/tabcontroller.cpp index 8c9f2cc0d..035622dfb 100644 --- a/src/sdk/tabcontroller.cpp +++ b/src/sdk/tabcontroller.cpp @@ -16,24 +16,17 @@ ** ** 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 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** ** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** ** ** $QT_END_LICENSE$ ** @@ -95,7 +88,7 @@ TabController::TabController(QObject *parent) TabController::~TabController() { - d->m_core->writeUninstaller(); + d->m_core->writeMaintenanceTool(); delete d; } @@ -137,8 +130,8 @@ int TabController::init() connect(d->m_gui, SIGNAL(settingsButtonClicked()), this, SLOT(onSettingsButtonClicked())); } - IntroductionPageImpl *page = - qobject_cast<IntroductionPageImpl*> (d->m_gui->page(PackageManagerCore::Introduction)); + IntroductionPage *page = + qobject_cast<IntroductionPage*> (d->m_gui->page(PackageManagerCore::Introduction)); if (page) { page->setMessage(QString()); page->setErrorMessage(QString()); @@ -174,7 +167,7 @@ void TabController::restartWizard() // Make sure we are writing the .dat file with the list of uninstall operations already now. // Otherwise we will write at the end of the next updater run, with a potentially // empty component list (if no updates are found). - d->m_core->writeUninstaller(); + d->m_core->writeMaintenanceTool(); // restart and switch back to intro page QTimer::singleShot(0, this, SLOT(init())); @@ -189,8 +182,8 @@ void TabController::onSettingsButtonClicked() if (d->m_networkSettingsChanged) { d->m_core->setCanceled(); - IntroductionPageImpl *page = - qobject_cast<IntroductionPageImpl*> (d->m_gui->page(PackageManagerCore::Introduction)); + IntroductionPage *page = + qobject_cast<IntroductionPage*> (d->m_gui->page(PackageManagerCore::Introduction)); if (page) { page->setMessage(QString()); page->setErrorMessage(QString()); @@ -202,7 +195,7 @@ void TabController::onSettingsButtonClicked() void TabController::onCurrentIdChanged(int newId) { if (d->m_gui) { - if (PackageManagerPage *page = d->m_gui->page(newId)) + if (PackageManagerPage *page = qobject_cast<PackageManagerPage *>(d->m_gui->page(newId))) d->m_gui->showSettingsButton(page->settingsButtonRequested()); } } diff --git a/src/sdk/tabcontroller.h b/src/sdk/tabcontroller.h index 546837997..831211453 100644 --- a/src/sdk/tabcontroller.h +++ b/src/sdk/tabcontroller.h @@ -16,24 +16,17 @@ ** ** 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 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** ** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** ** ** $QT_END_LICENSE$ ** diff --git a/src/sdk/translations/ja_jp.ts b/src/sdk/translations/ja_jp.ts index 3303cfd10..0222d7c14 100644 --- a/src/sdk/translations/ja_jp.ts +++ b/src/sdk/translations/ja_jp.ts @@ -255,7 +255,7 @@ </message> <message> <source>Could not create folder %1: Unknown error.</source> - <translation>フォルダー %1 を作成できませんでした: 未知のエラーです。</translation> + <translation>フォルダ %1 を作成できませんでした: 未知のエラーです。</translation> </message> <message> <source>Cannot remove directory %1: %2</source> @@ -362,11 +362,11 @@ </message> <message> <source>Could not remove folder %1: The folder does not exist.</source> - <translation>フォルダー %1 を削除できませんでした: フォルダーが存在しません。</translation> + <translation>フォルダ %1 を削除できませんでした: フォルダが存在しません。</translation> </message> <message> <source>Could not remove folder %1: %2</source> - <translation>フォルダー %1 を削除できませんでした: %2</translation> + <translation>フォルダ %1 を削除できませんでした: %2</translation> </message> <message> <source>Cannot recreate directory %1: %2</source> @@ -875,7 +875,7 @@ </message> <message> <source>Could not create folder %1: %2.</source> - <translation>フォルダー %1 を作成できませんでした: %2</translation> + <translation>フォルダ %1 を作成できませんでした: %2</translation> </message> <message> <source>Could not create link %1: %2</source> @@ -1905,7 +1905,7 @@ Qt のバイナリにパッチを適用しようとしましたが、Qt の他 </message> <message> <source>The install directory cannot be empty, please specify a valid folder.</source> - <translation>インストールディレクトリが殻にできません。有効なフォルダを指定してください。</translation> + <translation>インストールディレクトリが空にできません。有効なフォルダを指定してください。</translation> </message> <message> <source>As the install directory is completely deleted on uninstall, installing in %1 is forbidden.</source> @@ -2034,11 +2034,11 @@ Qt のバイナリにパッチを適用しようとしましたが、Qt の他 </message> <message> <source>Could not remove folder %1: %2</source> - <translation>フォルダー %1 を削除できませんでした: %2</translation> + <translation>フォルダ %1 を削除できませんでした: %2</translation> </message> <message> <source>Could not create folder %1</source> - <translation>フォルダー %1 を作成できませんでした</translation> + <translation>フォルダ %1 を作成できませんでした</translation> </message> <message> <source>Could not copy file from %1 to %2: %3</source> @@ -2050,7 +2050,7 @@ Qt のバイナリにパッチを適用しようとしましたが、Qt の他 </message> <message> <source>Could not create folder %1: %2</source> - <translation>フォルダー %1 を作成できませんでした: %2</translation> + <translation>フォルダ %1 を作成できませんでした: %2</translation> </message> <message> <source>Could not open temporary file: %1</source> @@ -2078,11 +2078,11 @@ Qt のバイナリにパッチを適用しようとしましたが、Qt の他 </message> <message> <source>Path exists but is not a folder: %1</source> - <translation>パスが存在していますが、フォルダーではありません: %1</translation> + <translation>パスが存在していますが、フォルダではありません: %1</translation> </message> <message> <source>Could not create folder: %1</source> - <translation>フォルダーを作成できませんでした: %1</translation> + <translation>フォルダを作成できませんでした: %1</translation> </message> <message> <source>Could not create temporary file</source> @@ -2242,7 +2242,7 @@ Qt のバイナリにパッチを適用しようとしましたが、Qt の他 </message> <message> <source>Could not create folder at %1: %2</source> - <translation>%1 にフォルダーを作成できませんでした: %2</translation> + <translation>%1 にフォルダを作成できませんでした: %2</translation> </message> <message> <source>Invalid arguments: %1 arguments given, %2 to %3 expected.</source> diff --git a/src/sdk/updatechecker.cpp b/src/sdk/updatechecker.cpp new file mode 100644 index 000000000..7f2e50275 --- /dev/null +++ b/src/sdk/updatechecker.cpp @@ -0,0 +1,118 @@ +/************************************************************************** +** +** Copyright (C) 2012-2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#include "updatechecker.h" + +#include <binaryformatenginehandler.h> +#include <component.h> +#include <errors.h> +#include <init.h> +#include <kdrunoncechecker.h> +#include <packagemanagercore.h> +#include <productkeycheck.h> + +#include <QDomDocument> + +#include <iostream> + +UpdateChecker::UpdateChecker(int &argc, char *argv[]) + : SDKApp<QCoreApplication>(argc, argv) +{ + QInstaller::init(); // register custom operations +} + +int UpdateChecker::check() +{ + KDRunOnceChecker runCheck(qApp->applicationDirPath() + QLatin1String("/lockmyApp15021976.lock")); + if (runCheck.isRunning(KDRunOnceChecker::ConditionFlag::Lockfile)) { + // It is possible to install an application and thus the maintenance tool into a + // directory that requires elevated permission to create a lock file. Since this + // cannot be done without requesting credentials from the user, we silently ignore + // the fact that we could not create the lock file and check the running processes. + if (runCheck.isRunning(KDRunOnceChecker::ConditionFlag::ProcessList)) + throw QInstaller::Error(QLatin1String("An instance is already checking for updates.")); + } + + QString fileName = datFile(binaryFile()); + quint64 cookie = QInstaller::BinaryContent::MagicCookieDat; + if (fileName.isEmpty()) { + fileName = binaryFile(); + cookie = QInstaller::BinaryContent::MagicCookie; + } + + QFile binary(fileName); + QInstaller::openForRead(&binary); + + qint64 magicMarker; + QList<QInstaller::OperationBlob> operations; + QInstaller::ResourceCollectionManager manager; + QInstaller::BinaryContent::readBinaryContent(&binary, &operations, &manager, &magicMarker, + cookie); + + if (magicMarker != QInstaller::BinaryContent::MagicInstallerMarker) + throw QInstaller::Error(QLatin1String("Installers cannot check for updates.")); + + SDKApp::registerMetaResources(manager.collectionByName("QResources")); + + QInstaller::PackageManagerCore core(QInstaller::BinaryContent::MagicUpdaterMarker, operations); + QInstaller::PackageManagerCore::setVirtualComponentsVisible(true); + { + using namespace QInstaller; + ProductKeyCheck::instance()->init(&core); + ProductKeyCheck::instance()->addPackagesFromXml(QLatin1String(":/metadata/Updates.xml")); + BinaryFormatEngineHandler::instance()->registerResources(manager.collections()); + } + if (!core.fetchRemotePackagesTree()) + throw QInstaller::Error(core.error()); + + const QList<QInstaller::Component *> components = + core.components(QInstaller::PackageManagerCore::ComponentType::Root); + if (components.isEmpty()) + throw QInstaller::Error(QLatin1String("There are currently no updates available.")); + + QDomDocument doc; + QDomElement root = doc.createElement(QLatin1String("updates")); + doc.appendChild(root); + + foreach (QInstaller::Component *component, components) { + QDomElement update = doc.createElement(QLatin1String("update")); + update.setAttribute(QLatin1String("name"), component->value(QInstaller::scDisplayName)); + update.setAttribute(QLatin1String("version"), component->value(QInstaller::scRemoteVersion)); + update.setAttribute(QLatin1String("size"), component->value(QInstaller::scUncompressedSize)); + root.appendChild(update); + } + + std::cout << qPrintable(doc.toString(4)) << std::endl; + return EXIT_SUCCESS; +} diff --git a/src/sdk/updatechecker.h b/src/sdk/updatechecker.h new file mode 100644 index 000000000..134ef704b --- /dev/null +++ b/src/sdk/updatechecker.h @@ -0,0 +1,50 @@ +/************************************************************************** +** +** Copyright (C) 2012-2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#ifndef UPDATECHECKER_H +#define UPDATECHECKER_H + +#include "sdkapp.h" + +class UpdateChecker : public SDKApp<QCoreApplication> +{ + Q_OBJECT + Q_DISABLE_COPY(UpdateChecker) + +public: + UpdateChecker(int &argc, char *argv[]); + int check(); +}; + +#endif // UPDATECHECKER_H |