2011-02-21 16:30:31 +01:00
|
|
|
/**************************************************************************
|
|
|
|
**
|
2014-05-14 13:08:46 +02:00
|
|
|
** Copyright (C) 2012-2014 Digia Plc and/or its subsidiary(-ies).
|
2012-12-21 10:31:17 +01:00
|
|
|
** Contact: http://www.qt-project.org/legal
|
2011-02-21 16:30:31 +01:00
|
|
|
**
|
2012-12-21 10:31:17 +01:00
|
|
|
** This file is part of the Qt Installer Framework.
|
2011-02-21 16:30:31 +01:00
|
|
|
**
|
2012-12-21 10:31:17 +01:00
|
|
|
** $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.
|
2011-02-21 16:30:31 +01:00
|
|
|
**
|
|
|
|
** GNU Lesser General Public License Usage
|
2012-12-21 10:31:17 +01:00
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
2014-10-16 11:51:47 +02:00
|
|
|
** 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.
|
2012-12-21 10:31:17 +01:00
|
|
|
**
|
|
|
|
** In addition, as a special exception, Digia gives you certain additional
|
2014-10-16 11:51:47 +02:00
|
|
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
2011-11-28 17:03:44 +01:00
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
**
|
2011-02-21 16:30:31 +01:00
|
|
|
**
|
2012-12-21 10:31:17 +01:00
|
|
|
** $QT_END_LICENSE$
|
2011-02-21 16:30:31 +01:00
|
|
|
**
|
|
|
|
**************************************************************************/
|
2011-09-30 12:17:38 +02:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
#include "constants.h"
|
|
|
|
#include "commandlineparser.h"
|
|
|
|
#include "installerbase.h"
|
2011-03-03 16:03:57 +01:00
|
|
|
#include "installerbasecommons.h"
|
|
|
|
#include "tabcontroller.h"
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
#include <binaryformatenginehandler.h>
|
|
|
|
#include <copydirectoryoperation.h>
|
2012-03-13 16:38:56 +01:00
|
|
|
#include <errors.h>
|
2011-09-30 12:17:38 +02:00
|
|
|
#include <init.h>
|
2014-08-29 12:56:06 +02:00
|
|
|
#include <kdupdaterupdateoperations.h>
|
2014-07-09 13:23:33 +02:00
|
|
|
#include <messageboxhandler.h>
|
2014-08-29 12:56:06 +02:00
|
|
|
#include <packagemanagercore.h>
|
2014-10-31 13:07:43 +01:00
|
|
|
#include <packagemanagerproxyfactory.h>
|
2014-08-29 12:56:06 +02:00
|
|
|
#include <qprocesswrapper.h>
|
2014-07-09 13:23:33 +02:00
|
|
|
#include <productkeycheck.h>
|
2011-06-20 22:00:34 +02:00
|
|
|
#include <settings.h>
|
2012-03-13 16:38:56 +01:00
|
|
|
#include <utils.h>
|
2011-03-10 15:50:33 +01:00
|
|
|
|
2011-11-19 00:00:52 +01:00
|
|
|
#include <kdrunoncechecker.h>
|
2012-03-13 16:38:56 +01:00
|
|
|
#include <kdupdaterfiledownloaderfactory.h>
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2013-10-16 12:48:21 +02:00
|
|
|
#include <QDirIterator>
|
2014-08-29 12:56:06 +02:00
|
|
|
#include <QTemporaryFile>
|
2014-07-09 13:23:33 +02:00
|
|
|
#include <QTranslator>
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
InstallerBase::InstallerBase(int &argc, char *argv[])
|
|
|
|
: SDKApp<QApplication>(argc, argv)
|
|
|
|
, m_core(0)
|
2011-05-10 11:53:36 +02:00
|
|
|
{
|
2014-08-29 12:56:06 +02:00
|
|
|
QInstaller::init(); // register custom operations
|
2011-05-10 11:53:36 +02:00
|
|
|
}
|
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
InstallerBase::~InstallerBase()
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2014-08-29 12:56:06 +02:00
|
|
|
delete m_core;
|
|
|
|
}
|
2011-09-30 12:24:57 +02:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
int InstallerBase::run()
|
|
|
|
{
|
2014-11-07 12:27:00 +01:00
|
|
|
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;
|
|
|
|
}
|
2014-07-09 13:23:33 +02:00
|
|
|
}
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
QString fileName = datFile(binaryFile());
|
|
|
|
quint64 cookie = QInstaller::BinaryContent::MagicCookieDat;
|
|
|
|
if (fileName.isEmpty()) {
|
|
|
|
fileName = binaryFile();
|
|
|
|
cookie = QInstaller::BinaryContent::MagicCookie;
|
2014-07-09 13:23:33 +02:00
|
|
|
}
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2014-10-14 17:03:54 +02:00
|
|
|
QFile binary(fileName);
|
|
|
|
QInstaller::openForRead(&binary);
|
2014-08-29 12:56:06 +02:00
|
|
|
|
|
|
|
qint64 magicMarker;
|
|
|
|
QInstaller::ResourceCollectionManager manager;
|
|
|
|
QList<QInstaller::OperationBlob> oldOperations;
|
2014-10-14 17:03:54 +02:00
|
|
|
QInstaller::BinaryContent::readBinaryContent(&binary, &oldOperations, &manager, &magicMarker,
|
|
|
|
cookie);
|
2014-08-29 12:56:06 +02:00
|
|
|
|
|
|
|
if (QInstaller::isVerbose()) {
|
2014-09-03 15:01:44 +02:00
|
|
|
qDebug() << "Language:" << QLocale().uiLanguages().value(0,
|
|
|
|
QLatin1String("No UI language set")).toUtf8().constData();
|
|
|
|
qDebug() << "Arguments: " << arguments().join(QLatin1String(", ")).toUtf8().constData();
|
2014-08-29 12:56:06 +02:00
|
|
|
}
|
2011-10-04 12:46:04 +02:00
|
|
|
|
2014-10-14 17:03:54 +02:00
|
|
|
SDKApp::registerMetaResources(manager.collectionByName("QResources"));
|
2014-10-29 17:29:40 +01:00
|
|
|
m_core = new QInstaller::PackageManagerCore(magicMarker, oldOperations);
|
|
|
|
{
|
|
|
|
using namespace QInstaller;
|
|
|
|
ProductKeyCheck::instance()->init(m_core);
|
|
|
|
ProductKeyCheck::instance()->addPackagesFromXml(QLatin1String(":/metadata/Updates.xml"));
|
|
|
|
BinaryFormatEngineHandler::instance()->registerResources(manager.collections());
|
|
|
|
}
|
2014-08-29 12:56:06 +02:00
|
|
|
if (QInstaller::isVerbose())
|
|
|
|
dumpResourceTree();
|
2012-11-13 12:24:49 +01:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
CommandLineParser parser;
|
|
|
|
parser.parse(arguments());
|
2014-07-14 12:10:06 +02:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
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."));
|
|
|
|
}
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
if (parser.isSet(QLatin1String(CommandLineOptions::Proxy))) {
|
|
|
|
m_core->settings().setProxyType(QInstaller::Settings::SystemProxy);
|
|
|
|
KDUpdater::FileDownloaderFactory::instance().setProxyFactory(m_core->proxyFactory());
|
|
|
|
}
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
if (parser.isSet(QLatin1String(CommandLineOptions::ShowVirtualComponents))) {
|
|
|
|
QFont f;
|
|
|
|
f.setItalic(true);
|
|
|
|
QInstaller::PackageManagerCore::setVirtualComponentsFont(f);
|
|
|
|
QInstaller::PackageManagerCore::setVirtualComponentsVisible(true);
|
|
|
|
}
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
if (parser.isSet(QLatin1String(CommandLineOptions::Updater))) {
|
|
|
|
if (m_core->isInstaller())
|
|
|
|
throw QInstaller::Error(QLatin1String("Cannot start installer binary as updater."));
|
|
|
|
m_core->setUpdater();
|
|
|
|
}
|
2014-07-09 13:23:33 +02:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
if (parser.isSet(QLatin1String(CommandLineOptions::ManagePackages))) {
|
|
|
|
if (m_core->isInstaller())
|
|
|
|
throw QInstaller::Error(QLatin1String("Cannot start installer binary as package manager."));
|
|
|
|
m_core->setPackageManager();
|
|
|
|
}
|
2014-07-09 13:23:33 +02:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
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);
|
|
|
|
}
|
2014-07-09 13:23:33 +02:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
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);
|
|
|
|
}
|
2014-07-09 13:23:33 +02:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
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);
|
|
|
|
}
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
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);
|
2014-07-09 13:23:33 +02:00
|
|
|
}
|
2014-08-29 12:56:06 +02:00
|
|
|
}
|
2014-07-09 13:23:33 +02:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
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;
|
2014-07-09 13:23:33 +02:00
|
|
|
}
|
2014-08-29 12:56:06 +02:00
|
|
|
}
|
2014-07-09 13:23:33 +02:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
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());
|
2014-07-09 13:23:33 +02:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
if (translations.isEmpty()) {
|
|
|
|
translator.reset(new QTranslator(QCoreApplication::instance()));
|
|
|
|
foreach (const QLocale locale, QLocale().uiLanguages()) {
|
|
|
|
if (translator->load(locale, QLatin1String(""), QLatin1String(""), directory)) {
|
|
|
|
QCoreApplication::instance()->installTranslator(translator.take());
|
|
|
|
break;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
}
|
2014-08-29 12:56:06 +02:00
|
|
|
} else {
|
|
|
|
foreach (const QString &translation, translations) {
|
|
|
|
translator.reset(new QTranslator(QCoreApplication::instance()));
|
|
|
|
if (translator->load(translation, QLatin1String(":/translations")))
|
|
|
|
QCoreApplication::instance()->installTranslator(translator.take());
|
2013-10-14 19:26:18 +02:00
|
|
|
}
|
2014-08-29 12:56:06 +02:00
|
|
|
}
|
2013-10-14 19:26:18 +02:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
//create the wizard GUI
|
|
|
|
TabController controller(0);
|
|
|
|
controller.setManager(m_core);
|
|
|
|
controller.setManagerParams(params);
|
|
|
|
controller.setControlScript(controlScript);
|
2013-10-14 19:26:18 +02:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
if (m_core->isInstaller())
|
|
|
|
controller.setGui(new InstallerGui(m_core));
|
|
|
|
else
|
|
|
|
controller.setGui(new MaintenanceGui(m_core));
|
2013-10-14 19:26:18 +02:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
QInstaller::PackageManagerCore::Status status =
|
|
|
|
QInstaller::PackageManagerCore::Status(controller.init());
|
|
|
|
if (status != QInstaller::PackageManagerCore::Success)
|
|
|
|
return status;
|
2013-10-14 19:26:18 +02:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
const int result = QCoreApplication::instance()->exec();
|
|
|
|
if (result != 0)
|
|
|
|
return result;
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
if (m_core->finishedWithSuccess())
|
|
|
|
return QInstaller::PackageManagerCore::Success;
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
status = m_core->status();
|
|
|
|
switch (status) {
|
|
|
|
case QInstaller::PackageManagerCore::Success:
|
2011-03-14 17:42:15 +01:00
|
|
|
return status;
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
case QInstaller::PackageManagerCore::Canceled:
|
|
|
|
return status;
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return QInstaller::PackageManagerCore::Failure;
|
|
|
|
}
|
2011-02-21 16:30:31 +01:00
|
|
|
|
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
// -- private
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
void InstallerBase::dumpResourceTree() const
|
|
|
|
{
|
2014-09-03 15:01:44 +02:00
|
|
|
qDebug() << "Resource tree:";
|
2014-08-29 12:56:06 +02:00
|
|
|
QDirIterator it(QLatin1String(":/"), QDir::NoDotAndDotDot | QDir::AllEntries | QDir::Hidden,
|
|
|
|
QDirIterator::Subdirectories);
|
|
|
|
while (it.hasNext()) {
|
|
|
|
if (it.next().startsWith(QLatin1String(":/qt-project.org")))
|
|
|
|
continue;
|
2014-09-03 15:01:44 +02:00
|
|
|
qDebug() << " " << it.filePath().toUtf8().constData();
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
2014-08-29 12:56:06 +02:00
|
|
|
}
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2014-08-29 12:56:06 +02:00
|
|
|
QStringList InstallerBase::repositories(const QString &list) const
|
|
|
|
{
|
|
|
|
const QStringList items = list.split(QLatin1Char(','), QString::SkipEmptyParts);
|
|
|
|
foreach (const QString &item, items)
|
2014-09-03 15:01:44 +02:00
|
|
|
qDebug() << "Adding custom repository:" << item.toUtf8().constData();
|
2014-08-29 12:56:06 +02:00
|
|
|
return items;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|