2010-02-25 16:51:27 +01:00
|
|
|
/**************************************************************************
|
|
|
|
|
**
|
|
|
|
|
** This file is part of Qt Creator
|
|
|
|
|
**
|
|
|
|
|
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
|
|
|
|
**
|
|
|
|
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
|
|
|
**
|
|
|
|
|
** Commercial Usage
|
|
|
|
|
**
|
|
|
|
|
** Licensees holding valid Qt Commercial licenses may use this file in
|
|
|
|
|
** accordance with the Qt Commercial License Agreement provided with the
|
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
|
|
|
** a written agreement between you and Nokia.
|
|
|
|
|
**
|
|
|
|
|
** 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.
|
|
|
|
|
**
|
|
|
|
|
** If you are unsure which license is appropriate for your use, please
|
|
|
|
|
** contact the sales department at http://qt.nokia.com/contact.
|
|
|
|
|
**
|
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "s60createpackagestep.h"
|
|
|
|
|
|
|
|
|
|
#include "qt4projectmanagerconstants.h"
|
|
|
|
|
#include "qt4buildconfiguration.h"
|
2010-07-23 16:37:10 +02:00
|
|
|
#include "qt4nodes.h"
|
|
|
|
|
#include "qt4project.h"
|
2010-07-07 16:43:45 +02:00
|
|
|
#include "abldparser.h"
|
2010-08-11 14:55:49 +02:00
|
|
|
#include "sbsv2parser.h"
|
2010-07-27 10:46:25 +02:00
|
|
|
#include "signsisparser.h"
|
|
|
|
|
#include "passphraseforkeydialog.h"
|
2010-02-25 16:51:27 +01:00
|
|
|
|
|
|
|
|
#include <projectexplorer/buildconfiguration.h>
|
2010-07-16 14:00:41 +02:00
|
|
|
#include <projectexplorer/buildsteplist.h>
|
|
|
|
|
#include <projectexplorer/projectexplorerconstants.h>
|
2010-02-25 16:51:27 +01:00
|
|
|
#include <projectexplorer/target.h>
|
2010-07-23 16:37:10 +02:00
|
|
|
#include <projectexplorer/project.h>
|
2010-07-07 16:43:45 +02:00
|
|
|
#include <projectexplorer/gnumakeparser.h>
|
2010-07-23 16:37:10 +02:00
|
|
|
#include <projectexplorer/task.h>
|
2010-02-25 16:51:27 +01:00
|
|
|
|
2010-07-13 16:36:37 +02:00
|
|
|
#include <QtCore/QDir>
|
2010-07-23 16:37:10 +02:00
|
|
|
#include <QtCore/QTimer>
|
2010-07-27 10:46:25 +02:00
|
|
|
#include <QtCore/QCryptographicHash>
|
|
|
|
|
|
|
|
|
|
#include <QSettings>
|
|
|
|
|
#include <QMessageBox>
|
2010-07-13 16:36:37 +02:00
|
|
|
|
2010-02-25 16:51:27 +01:00
|
|
|
using namespace Qt4ProjectManager::Internal;
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
const char * const SIGN_BS_ID = "Qt4ProjectManager.S60SignBuildStep";
|
|
|
|
|
const char * const SIGNMODE_KEY("Qt4ProjectManager.S60CreatePackageStep.SignMode");
|
|
|
|
|
const char * const CERTIFICATE_KEY("Qt4ProjectManager.S60CreatePackageStep.Certificate");
|
|
|
|
|
const char * const KEYFILE_KEY("Qt4ProjectManager.S60CreatePackageStep.Keyfile");
|
2010-04-30 11:01:06 +02:00
|
|
|
const char * const SMART_INSTALLER_KEY("Qt4ProjectManager.S60CreatorPackageStep.SmartInstaller");
|
2010-07-27 10:46:25 +02:00
|
|
|
|
|
|
|
|
const char * const MAKE_PASSPHRASE_ARGUMENT("QT_SIS_PASSPHRASE=");
|
|
|
|
|
const char * const MAKE_KEY_ARGUMENT("QT_SIS_KEY=");
|
|
|
|
|
const char * const MAKE_CERTIFICATE_ARGUMENT("QT_SIS_CERTIFICATE=");
|
2010-02-25 16:51:27 +01:00
|
|
|
}
|
|
|
|
|
|
2010-07-16 14:00:41 +02:00
|
|
|
S60CreatePackageStep::S60CreatePackageStep(ProjectExplorer::BuildStepList *bsl) :
|
|
|
|
|
BuildStep(bsl, QLatin1String(SIGN_BS_ID)),
|
2010-04-30 11:01:06 +02:00
|
|
|
m_signingMode(SignSelf),
|
2010-07-23 16:37:10 +02:00
|
|
|
m_createSmartInstaller(false),
|
|
|
|
|
m_outputParserChain(0),
|
|
|
|
|
m_process(0),
|
|
|
|
|
m_timer(0),
|
|
|
|
|
m_eventLoop(0),
|
2010-07-27 10:46:25 +02:00
|
|
|
m_futureInterface(0),
|
|
|
|
|
m_errorType(ErrorNone),
|
|
|
|
|
m_settings(0)
|
2010-02-25 16:51:27 +01:00
|
|
|
{
|
|
|
|
|
ctor_package();
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-16 14:00:41 +02:00
|
|
|
S60CreatePackageStep::S60CreatePackageStep(ProjectExplorer::BuildStepList *bsl, S60CreatePackageStep *bs) :
|
|
|
|
|
BuildStep(bsl, bs),
|
2010-02-25 16:51:27 +01:00
|
|
|
m_signingMode(bs->m_signingMode),
|
|
|
|
|
m_customSignaturePath(bs->m_customSignaturePath),
|
2010-04-30 11:01:06 +02:00
|
|
|
m_customKeyPath(bs->m_customKeyPath),
|
2010-07-27 10:46:25 +02:00
|
|
|
m_passphrase(bs->m_passphrase),
|
2010-07-23 16:37:10 +02:00
|
|
|
m_createSmartInstaller(bs->m_createSmartInstaller),
|
|
|
|
|
m_outputParserChain(0),
|
|
|
|
|
m_timer(0),
|
|
|
|
|
m_eventLoop(0),
|
2010-07-27 10:46:25 +02:00
|
|
|
m_futureInterface(0),
|
|
|
|
|
m_errorType(ErrorNone),
|
|
|
|
|
m_settings(0)
|
2010-02-25 16:51:27 +01:00
|
|
|
{
|
|
|
|
|
ctor_package();
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-16 14:00:41 +02:00
|
|
|
S60CreatePackageStep::S60CreatePackageStep(ProjectExplorer::BuildStepList *bsl, const QString &id) :
|
|
|
|
|
BuildStep(bsl, id),
|
2010-04-30 11:01:06 +02:00
|
|
|
m_signingMode(SignSelf),
|
2010-07-23 16:37:10 +02:00
|
|
|
m_createSmartInstaller(false),
|
|
|
|
|
m_outputParserChain(0),
|
|
|
|
|
m_timer(0),
|
|
|
|
|
m_eventLoop(0),
|
2010-07-27 10:46:25 +02:00
|
|
|
m_futureInterface(0),
|
|
|
|
|
m_errorType(ErrorNone),
|
|
|
|
|
m_settings(0)
|
2010-02-25 16:51:27 +01:00
|
|
|
{
|
|
|
|
|
ctor_package();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void S60CreatePackageStep::ctor_package()
|
|
|
|
|
{
|
2010-08-19 12:26:21 +02:00
|
|
|
//: default create SIS package build step display name
|
|
|
|
|
setDefaultDisplayName(tr("Create SIS Package"));
|
2010-07-27 10:46:25 +02:00
|
|
|
connect(this, SIGNAL(badPassphrase()),
|
|
|
|
|
this, SLOT(definePassphrase()), Qt::QueuedConnection);
|
|
|
|
|
|
|
|
|
|
m_settings = new QSettings(QSettings::IniFormat, QSettings::UserScope,
|
|
|
|
|
QLatin1String("Nokia"), QLatin1String("QtCreatorKeys"), this);
|
2010-02-25 16:51:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
S60CreatePackageStep::~S60CreatePackageStep()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QVariantMap S60CreatePackageStep::toMap() const
|
|
|
|
|
{
|
2010-07-23 16:37:10 +02:00
|
|
|
QVariantMap map(BuildStep::toMap());
|
2010-02-25 16:51:27 +01:00
|
|
|
map.insert(QLatin1String(SIGNMODE_KEY), (int)m_signingMode);
|
|
|
|
|
map.insert(QLatin1String(CERTIFICATE_KEY), m_customSignaturePath);
|
|
|
|
|
map.insert(QLatin1String(KEYFILE_KEY), m_customKeyPath);
|
2010-04-30 11:01:06 +02:00
|
|
|
map.insert(QLatin1String(SMART_INSTALLER_KEY), m_createSmartInstaller);
|
2010-02-25 16:51:27 +01:00
|
|
|
return map;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool S60CreatePackageStep::fromMap(const QVariantMap &map)
|
|
|
|
|
{
|
2010-09-07 12:03:57 +02:00
|
|
|
m_signingMode = static_cast<SigningMode>(map.value(QLatin1String(SIGNMODE_KEY), static_cast<int>(SignSelf)).toInt());
|
2010-02-25 16:51:27 +01:00
|
|
|
m_customSignaturePath = map.value(QLatin1String(CERTIFICATE_KEY)).toString();
|
2010-07-27 10:46:25 +02:00
|
|
|
setCustomKeyPath(map.value(QLatin1String(KEYFILE_KEY)).toString());
|
2010-04-30 11:01:06 +02:00
|
|
|
m_createSmartInstaller = map.value(QLatin1String(SMART_INSTALLER_KEY), false).toBool();
|
2010-07-23 16:37:10 +02:00
|
|
|
return BuildStep::fromMap(map);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Qt4BuildConfiguration *S60CreatePackageStep::qt4BuildConfiguration() const
|
|
|
|
|
{
|
|
|
|
|
return static_cast<Qt4BuildConfiguration *>(buildConfiguration());
|
2010-02-25 16:51:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool S60CreatePackageStep::init()
|
|
|
|
|
{
|
2010-07-23 16:37:10 +02:00
|
|
|
Qt4Project *pro = qobject_cast<Qt4Project *>(buildConfiguration()->target()->project());
|
|
|
|
|
|
|
|
|
|
QList<Qt4ProFileNode *> nodes = pro->leafProFiles();
|
|
|
|
|
|
|
|
|
|
m_workingDirectories.clear();
|
|
|
|
|
foreach (Qt4ProFileNode *node, nodes)
|
|
|
|
|
m_workingDirectories << node->buildDir();
|
|
|
|
|
|
|
|
|
|
m_makeCmd = qt4BuildConfiguration()->makeCommand();
|
|
|
|
|
if (!QFileInfo(m_makeCmd).isAbsolute()) {
|
|
|
|
|
// Try to detect command in environment
|
|
|
|
|
const QString tmp = buildConfiguration()->environment().searchInPath(m_makeCmd);
|
|
|
|
|
if (tmp.isEmpty()) {
|
2010-09-10 10:51:43 +02:00
|
|
|
emit addOutput(tr("Could not find make command '%1' in the build environment").arg(m_makeCmd), BuildStep::ErrorOutput);
|
2010-07-23 16:37:10 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
m_makeCmd = tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_environment = qt4BuildConfiguration()->environment();
|
|
|
|
|
|
|
|
|
|
m_args.clear();
|
2010-04-30 11:01:06 +02:00
|
|
|
if (m_createSmartInstaller)
|
2010-07-23 16:37:10 +02:00
|
|
|
m_args << QLatin1String("installer_sis");
|
2010-04-30 11:01:06 +02:00
|
|
|
else
|
2010-07-23 16:37:10 +02:00
|
|
|
m_args << QLatin1String("sis");
|
2010-02-25 16:51:27 +01:00
|
|
|
if (signingMode() == SignCustom) {
|
2010-07-27 10:46:25 +02:00
|
|
|
m_args << QLatin1String(MAKE_CERTIFICATE_ARGUMENT) + QDir::toNativeSeparators(customSignaturePath())
|
|
|
|
|
<< QLatin1String(MAKE_KEY_ARGUMENT) + QDir::toNativeSeparators(customKeyPath());
|
|
|
|
|
|
|
|
|
|
setPassphrase(loadPassphraseForKey(m_keyId));
|
|
|
|
|
|
|
|
|
|
if (!passphrase().isEmpty()) {
|
|
|
|
|
m_args << QLatin1String(MAKE_PASSPHRASE_ARGUMENT) + passphrase();
|
|
|
|
|
}
|
2010-07-23 16:37:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delete m_outputParserChain;
|
2010-08-11 14:55:49 +02:00
|
|
|
if (qt4BuildConfiguration()->qtVersion()->isBuildWithSymbianSbsV2())
|
|
|
|
|
m_outputParserChain = new Qt4ProjectManager::SbsV2Parser;
|
|
|
|
|
else
|
|
|
|
|
m_outputParserChain = new Qt4ProjectManager::AbldParser;
|
|
|
|
|
m_outputParserChain->appendOutputParser(new ProjectExplorer::GnuMakeParser);
|
2010-07-27 10:46:25 +02:00
|
|
|
m_outputParserChain->appendOutputParser(new Qt4ProjectManager::SignsisParser);
|
|
|
|
|
|
2010-07-23 16:37:10 +02:00
|
|
|
connect(m_outputParserChain, SIGNAL(addOutput(QString, ProjectExplorer::BuildStep::OutputFormat)),
|
|
|
|
|
this, SLOT(outputAdded(QString, ProjectExplorer::BuildStep::OutputFormat)));
|
|
|
|
|
connect(m_outputParserChain, SIGNAL(addTask(ProjectExplorer::Task)),
|
2010-07-27 10:46:25 +02:00
|
|
|
this, SLOT(taskAdded(ProjectExplorer::Task)), Qt::DirectConnection);
|
2010-07-23 16:37:10 +02:00
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-27 10:46:25 +02:00
|
|
|
void S60CreatePackageStep::definePassphrase()
|
|
|
|
|
{
|
|
|
|
|
PassphraseForKeyDialog *passwordDialog
|
|
|
|
|
= new PassphraseForKeyDialog(QFileInfo(customKeyPath()).fileName());
|
|
|
|
|
if (passwordDialog->exec()) {
|
|
|
|
|
setPassphrase(passwordDialog->passphrase());
|
|
|
|
|
if (passwordDialog->savePassphrase())
|
|
|
|
|
savePassphraseForKey(m_keyId, passphrase());
|
|
|
|
|
} else
|
|
|
|
|
m_errorType = ErrorUndefined;
|
|
|
|
|
delete passwordDialog;
|
|
|
|
|
passwordDialog = 0;
|
|
|
|
|
|
|
|
|
|
m_waitCondition.wakeAll();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void S60CreatePackageStep::savePassphraseForKey(const QString &keyId, const QString &passphrase)
|
|
|
|
|
{
|
|
|
|
|
m_settings->beginGroup("keys");
|
|
|
|
|
if (passphrase.isEmpty())
|
|
|
|
|
m_settings->remove(keyId);
|
|
|
|
|
else
|
|
|
|
|
m_settings->setValue(keyId, obfuscatePassphrase(passphrase, keyId));
|
|
|
|
|
m_settings->endGroup();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString S60CreatePackageStep::loadPassphraseForKey(const QString &keyId)
|
|
|
|
|
{
|
|
|
|
|
m_settings->beginGroup("keys");
|
|
|
|
|
QString passphrase = elucidatePassphrase(m_settings->value(keyId, QByteArray()).toByteArray(), keyId);
|
|
|
|
|
m_settings->endGroup();
|
|
|
|
|
return passphrase;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QByteArray S60CreatePackageStep::obfuscatePassphrase(const QString &passphrase, const QString &key) const
|
|
|
|
|
{
|
|
|
|
|
QByteArray byteArray = passphrase.toUtf8();
|
|
|
|
|
char *data = byteArray.data();
|
|
|
|
|
const QChar *keyData = key.data();
|
|
|
|
|
int keyDataSize = key.size();
|
|
|
|
|
for (int i = 0; i <byteArray.size(); ++i)
|
|
|
|
|
data[i] = data[i]^keyData[i%keyDataSize].toAscii();
|
|
|
|
|
return byteArray.toBase64();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString S60CreatePackageStep::elucidatePassphrase(QByteArray obfuscatedPassphrase, const QString &key) const
|
|
|
|
|
{
|
|
|
|
|
QByteArray byteArray = QByteArray::fromBase64(obfuscatedPassphrase);
|
|
|
|
|
char *data = byteArray.data();
|
|
|
|
|
const QChar *keyData = key.data();
|
|
|
|
|
int keyDataSize = key.size();
|
|
|
|
|
for (int i = 0; i < byteArray.size(); ++i)
|
|
|
|
|
data[i] = data[i]^keyData[i%keyDataSize].toAscii();
|
|
|
|
|
return byteArray.data();
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-23 16:37:10 +02:00
|
|
|
void S60CreatePackageStep::run(QFutureInterface<bool> &fi)
|
|
|
|
|
{
|
|
|
|
|
m_futureInterface = &fi;
|
|
|
|
|
|
|
|
|
|
if (m_workingDirectories.isEmpty()) {
|
|
|
|
|
fi.reportResult(true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Setup everything...
|
|
|
|
|
m_process = new QProcess();
|
|
|
|
|
m_process->setEnvironment(m_environment.toStringList());
|
|
|
|
|
|
|
|
|
|
connect(m_process, SIGNAL(readyReadStandardOutput()),
|
|
|
|
|
this, SLOT(processReadyReadStdOutput()),
|
|
|
|
|
Qt::DirectConnection);
|
|
|
|
|
connect(m_process, SIGNAL(readyReadStandardError()),
|
|
|
|
|
this, SLOT(processReadyReadStdError()),
|
|
|
|
|
Qt::DirectConnection);
|
|
|
|
|
|
|
|
|
|
connect(m_process, SIGNAL(finished(int, QProcess::ExitStatus)),
|
|
|
|
|
this, SLOT(slotProcessFinished(int, QProcess::ExitStatus)),
|
|
|
|
|
Qt::DirectConnection);
|
|
|
|
|
|
|
|
|
|
m_timer = new QTimer();
|
|
|
|
|
connect(m_timer, SIGNAL(timeout()), this, SLOT(checkForCancel()), Qt::DirectConnection);
|
|
|
|
|
m_timer->start(500);
|
|
|
|
|
m_eventLoop = new QEventLoop;
|
|
|
|
|
|
|
|
|
|
bool returnValue = false;
|
|
|
|
|
if (startProcess())
|
|
|
|
|
returnValue = m_eventLoop->exec();
|
|
|
|
|
|
|
|
|
|
// Finished
|
|
|
|
|
m_timer->stop();
|
|
|
|
|
delete m_timer;
|
|
|
|
|
m_timer = 0;
|
|
|
|
|
|
|
|
|
|
delete m_process;
|
|
|
|
|
m_process = 0;
|
|
|
|
|
delete m_eventLoop;
|
|
|
|
|
m_eventLoop = 0;
|
|
|
|
|
fi.reportResult(returnValue);
|
|
|
|
|
m_futureInterface = 0;
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void S60CreatePackageStep::slotProcessFinished(int, QProcess::ExitStatus)
|
|
|
|
|
{
|
|
|
|
|
QString line = QString::fromLocal8Bit(m_process->readAllStandardError());
|
|
|
|
|
if (!line.isEmpty())
|
|
|
|
|
stdError(line);
|
|
|
|
|
|
|
|
|
|
line = QString::fromLocal8Bit(m_process->readAllStandardOutput());
|
|
|
|
|
if (!line.isEmpty())
|
|
|
|
|
stdOutput(line);
|
|
|
|
|
|
|
|
|
|
bool returnValue = false;
|
|
|
|
|
if (m_process->exitStatus() == QProcess::NormalExit && m_process->exitCode() == 0) {
|
|
|
|
|
emit addOutput(tr("The process \"%1\" exited normally.")
|
|
|
|
|
.arg(QDir::toNativeSeparators(m_makeCmd)),
|
|
|
|
|
BuildStep::MessageOutput);
|
|
|
|
|
returnValue = true;
|
|
|
|
|
} else if (m_process->exitStatus() == QProcess::NormalExit) {
|
|
|
|
|
emit addOutput(tr("The process \"%1\" exited with code %2.")
|
|
|
|
|
.arg(QDir::toNativeSeparators(m_makeCmd), QString::number(m_process->exitCode())),
|
|
|
|
|
BuildStep::ErrorMessageOutput);
|
|
|
|
|
} else {
|
|
|
|
|
emit addOutput(tr("The process \"%1\" crashed.").arg(QDir::toNativeSeparators(m_makeCmd)), BuildStep::ErrorMessageOutput);
|
2010-02-25 16:51:27 +01:00
|
|
|
}
|
2010-07-07 16:43:45 +02:00
|
|
|
|
2010-07-27 10:46:25 +02:00
|
|
|
switch (m_errorType) {
|
|
|
|
|
case ErrorUndefined:
|
|
|
|
|
m_eventLoop->exit(false);
|
|
|
|
|
return;
|
|
|
|
|
case ErrorBadPassphrase: {
|
|
|
|
|
emit badPassphrase();
|
|
|
|
|
QMutexLocker locker(&m_mutex);
|
|
|
|
|
//waiting for the user to input new passphrase or to abort
|
|
|
|
|
m_waitCondition.wait(&m_mutex);
|
|
|
|
|
if( m_errorType == ErrorUndefined ) {
|
2010-08-05 15:25:01 +02:00
|
|
|
m_eventLoop->exit(false);
|
2010-07-27 10:46:25 +02:00
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
QRegExp passphraseRegExp("^"+QLatin1String(MAKE_PASSPHRASE_ARGUMENT)+"(.+)$");
|
|
|
|
|
int index = m_args.indexOf(passphraseRegExp);
|
|
|
|
|
if (index>=0)
|
|
|
|
|
m_args.removeAt(index);
|
|
|
|
|
if (!passphrase().isEmpty())
|
|
|
|
|
m_args << QLatin1String(MAKE_PASSPHRASE_ARGUMENT) + passphrase();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
m_workingDirectories.removeFirst();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-23 16:37:10 +02:00
|
|
|
if (m_workingDirectories.isEmpty() || !returnValue) {
|
|
|
|
|
m_eventLoop->exit(returnValue);
|
|
|
|
|
} else {
|
|
|
|
|
// Success, do next
|
|
|
|
|
if (!startProcess())
|
|
|
|
|
m_eventLoop->exit(returnValue);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool S60CreatePackageStep::startProcess()
|
|
|
|
|
{
|
2010-07-27 10:46:25 +02:00
|
|
|
m_errorType = ErrorNone;
|
|
|
|
|
QString workingDirectory = m_workingDirectories.first();
|
2010-07-23 16:37:10 +02:00
|
|
|
QDir wd(workingDirectory);
|
|
|
|
|
if (!wd.exists())
|
|
|
|
|
wd.mkpath(wd.absolutePath());
|
|
|
|
|
|
|
|
|
|
m_process->setWorkingDirectory(workingDirectory);
|
2010-07-07 16:43:45 +02:00
|
|
|
|
2010-07-23 16:37:10 +02:00
|
|
|
// Go for it!
|
|
|
|
|
m_process->start(m_makeCmd, m_args);
|
|
|
|
|
if (!m_process->waitForStarted()) {
|
|
|
|
|
emit addOutput(tr("Could not start process \"%1\" in %2")
|
|
|
|
|
.arg(QDir::toNativeSeparators(m_makeCmd),
|
|
|
|
|
workingDirectory),
|
|
|
|
|
BuildStep::ErrorMessageOutput);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
emit addOutput(tr("Starting: \"%1\" %2 in %3\n")
|
|
|
|
|
.arg(QDir::toNativeSeparators(m_makeCmd),
|
|
|
|
|
m_args.join(" "),
|
|
|
|
|
workingDirectory),
|
|
|
|
|
BuildStep::MessageOutput);
|
2010-02-25 16:51:27 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-23 16:37:10 +02:00
|
|
|
void S60CreatePackageStep::processReadyReadStdOutput()
|
|
|
|
|
{
|
|
|
|
|
m_process->setReadChannel(QProcess::StandardOutput);
|
|
|
|
|
while (m_process->canReadLine()) {
|
|
|
|
|
QString line = QString::fromLocal8Bit(m_process->readLine());
|
|
|
|
|
stdOutput(line);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void S60CreatePackageStep::stdOutput(const QString &line)
|
|
|
|
|
{
|
|
|
|
|
if (m_outputParserChain)
|
|
|
|
|
m_outputParserChain->stdOutput(line);
|
|
|
|
|
emit addOutput(line, BuildStep::NormalOutput);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void S60CreatePackageStep::processReadyReadStdError()
|
|
|
|
|
{
|
|
|
|
|
m_process->setReadChannel(QProcess::StandardError);
|
|
|
|
|
while (m_process->canReadLine()) {
|
|
|
|
|
QString line = QString::fromLocal8Bit(m_process->readLine());
|
|
|
|
|
stdError(line);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void S60CreatePackageStep::stdError(const QString &line)
|
|
|
|
|
{
|
|
|
|
|
if (m_outputParserChain)
|
|
|
|
|
m_outputParserChain->stdError(line);
|
|
|
|
|
emit addOutput(line, BuildStep::ErrorOutput);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void S60CreatePackageStep::checkForCancel()
|
|
|
|
|
{
|
|
|
|
|
if (m_futureInterface->isCanceled() && m_timer->isActive()) {
|
|
|
|
|
m_timer->stop();
|
|
|
|
|
m_process->terminate();
|
|
|
|
|
m_process->waitForFinished(5000);
|
|
|
|
|
m_process->kill();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void S60CreatePackageStep::taskAdded(const ProjectExplorer::Task &task)
|
|
|
|
|
{
|
|
|
|
|
ProjectExplorer::Task editable(task);
|
|
|
|
|
QString filePath = QDir::cleanPath(task.file.trimmed());
|
|
|
|
|
if (!filePath.isEmpty() && !QDir::isAbsolutePath(filePath)) {
|
|
|
|
|
// TODO which kind of tasks do we get from package building?
|
|
|
|
|
// No absoulte path
|
|
|
|
|
}
|
2010-07-27 10:46:25 +02:00
|
|
|
if (task.type == ProjectExplorer::Task::Error) {
|
|
|
|
|
if (task.description.contains(QLatin1String("bad password"))
|
|
|
|
|
|| task.description.contains(QLatin1String("bad decrypt")))
|
|
|
|
|
m_errorType = ErrorBadPassphrase;
|
|
|
|
|
else if (m_errorType == ErrorNone)
|
|
|
|
|
m_errorType = ErrorUndefined;
|
|
|
|
|
}
|
2010-07-23 16:37:10 +02:00
|
|
|
emit addTask(editable);
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-27 10:46:25 +02:00
|
|
|
QString S60CreatePackageStep::generateKeyId(const QString &keyPath) const
|
|
|
|
|
{
|
|
|
|
|
if (keyPath.isEmpty())
|
|
|
|
|
return QString();
|
|
|
|
|
|
|
|
|
|
QFile file(keyPath);
|
|
|
|
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
|
|
|
|
return QString();
|
|
|
|
|
|
|
|
|
|
//key file is quite small in size
|
|
|
|
|
return QCryptographicHash::hash(file.readAll(),
|
|
|
|
|
QCryptographicHash::Md5).toHex();
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-23 16:37:10 +02:00
|
|
|
void S60CreatePackageStep::outputAdded(const QString &string, ProjectExplorer::BuildStep::OutputFormat format)
|
|
|
|
|
{
|
|
|
|
|
emit addOutput(string, format);
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-25 16:51:27 +01:00
|
|
|
bool S60CreatePackageStep::immutable() const
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ProjectExplorer::BuildStepConfigWidget *S60CreatePackageStep::createConfigWidget()
|
|
|
|
|
{
|
|
|
|
|
return new S60CreatePackageStepConfigWidget(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
S60CreatePackageStep::SigningMode S60CreatePackageStep::signingMode() const
|
|
|
|
|
{
|
|
|
|
|
return m_signingMode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void S60CreatePackageStep::setSigningMode(SigningMode mode)
|
|
|
|
|
{
|
|
|
|
|
m_signingMode = mode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString S60CreatePackageStep::customSignaturePath() const
|
|
|
|
|
{
|
|
|
|
|
return m_customSignaturePath;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void S60CreatePackageStep::setCustomSignaturePath(const QString &path)
|
|
|
|
|
{
|
|
|
|
|
m_customSignaturePath = path;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString S60CreatePackageStep::customKeyPath() const
|
|
|
|
|
{
|
|
|
|
|
return m_customKeyPath;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void S60CreatePackageStep::setCustomKeyPath(const QString &path)
|
|
|
|
|
{
|
|
|
|
|
m_customKeyPath = path;
|
2010-07-27 10:46:25 +02:00
|
|
|
m_keyId = generateKeyId(m_customKeyPath);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString S60CreatePackageStep::passphrase() const
|
|
|
|
|
{
|
|
|
|
|
return m_passphrase;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void S60CreatePackageStep::setPassphrase(const QString &passphrase)
|
|
|
|
|
{
|
|
|
|
|
m_passphrase = passphrase;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString S60CreatePackageStep::keyId() const
|
|
|
|
|
{
|
|
|
|
|
return m_keyId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void S60CreatePackageStep::setKeyId(const QString &keyId)
|
|
|
|
|
{
|
|
|
|
|
m_keyId = keyId;
|
2010-02-25 16:51:27 +01:00
|
|
|
}
|
|
|
|
|
|
2010-05-21 14:12:53 +02:00
|
|
|
bool S60CreatePackageStep::createsSmartInstaller() const
|
2010-04-30 11:01:06 +02:00
|
|
|
{
|
|
|
|
|
return m_createSmartInstaller;
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-21 14:12:53 +02:00
|
|
|
void S60CreatePackageStep::setCreatesSmartInstaller(bool value)
|
2010-04-30 11:01:06 +02:00
|
|
|
{
|
|
|
|
|
m_createSmartInstaller = value;
|
2010-05-21 14:12:53 +02:00
|
|
|
static_cast<Qt4BuildConfiguration *>(buildConfiguration())->emitS60CreatesSmartInstallerChanged();
|
2010-04-30 11:01:06 +02:00
|
|
|
}
|
|
|
|
|
|
2010-07-27 10:46:25 +02:00
|
|
|
void S60CreatePackageStep::resetPassphrases()
|
|
|
|
|
{
|
|
|
|
|
m_settings->beginGroup("keys");
|
|
|
|
|
QStringList keys = m_settings->allKeys();
|
|
|
|
|
foreach (QString key, keys) {
|
|
|
|
|
m_settings->setValue(key, "");
|
|
|
|
|
}
|
|
|
|
|
m_settings->remove("");
|
|
|
|
|
m_settings->endGroup();
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-25 16:51:27 +01:00
|
|
|
// #pragma mark -- S60SignBuildStepFactory
|
|
|
|
|
|
|
|
|
|
S60CreatePackageStepFactory::S60CreatePackageStepFactory(QObject *parent) :
|
|
|
|
|
ProjectExplorer::IBuildStepFactory(parent)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
S60CreatePackageStepFactory::~S60CreatePackageStepFactory()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-16 14:00:41 +02:00
|
|
|
bool S60CreatePackageStepFactory::canCreate(ProjectExplorer::BuildStepList *parent, const QString &id) const
|
2010-02-25 16:51:27 +01:00
|
|
|
{
|
2010-07-16 14:00:41 +02:00
|
|
|
if (parent->id() != QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY))
|
2010-02-25 16:51:27 +01:00
|
|
|
return false;
|
2010-07-16 14:00:41 +02:00
|
|
|
if (parent->target()->id() != QLatin1String(Constants::S60_DEVICE_TARGET_ID))
|
2010-02-25 16:51:27 +01:00
|
|
|
return false;
|
|
|
|
|
return (id == QLatin1String(SIGN_BS_ID));
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-16 14:00:41 +02:00
|
|
|
ProjectExplorer::BuildStep *S60CreatePackageStepFactory::create(ProjectExplorer::BuildStepList *parent, const QString &id)
|
2010-02-25 16:51:27 +01:00
|
|
|
{
|
2010-07-16 14:00:41 +02:00
|
|
|
if (!canCreate(parent, id))
|
2010-02-25 16:51:27 +01:00
|
|
|
return 0;
|
|
|
|
|
return new S60CreatePackageStep(parent);
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-16 14:00:41 +02:00
|
|
|
bool S60CreatePackageStepFactory::canClone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *source) const
|
2010-02-25 16:51:27 +01:00
|
|
|
{
|
2010-07-16 14:00:41 +02:00
|
|
|
return canCreate(parent, source->id());
|
2010-02-25 16:51:27 +01:00
|
|
|
}
|
|
|
|
|
|
2010-07-16 14:00:41 +02:00
|
|
|
ProjectExplorer::BuildStep *S60CreatePackageStepFactory::clone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *source)
|
2010-02-25 16:51:27 +01:00
|
|
|
{
|
2010-07-16 14:00:41 +02:00
|
|
|
if (!canClone(parent, source))
|
2010-02-25 16:51:27 +01:00
|
|
|
return 0;
|
|
|
|
|
return new S60CreatePackageStep(parent, static_cast<S60CreatePackageStep *>(source));
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-16 14:00:41 +02:00
|
|
|
bool S60CreatePackageStepFactory::canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const
|
2010-02-25 16:51:27 +01:00
|
|
|
{
|
|
|
|
|
QString id(ProjectExplorer::idFromMap(map));
|
2010-07-16 14:00:41 +02:00
|
|
|
return canCreate(parent, id);
|
2010-02-25 16:51:27 +01:00
|
|
|
}
|
|
|
|
|
|
2010-07-16 14:00:41 +02:00
|
|
|
ProjectExplorer::BuildStep *S60CreatePackageStepFactory::restore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map)
|
2010-02-25 16:51:27 +01:00
|
|
|
{
|
2010-07-16 14:00:41 +02:00
|
|
|
if (!canRestore(parent, map))
|
2010-02-25 16:51:27 +01:00
|
|
|
return 0;
|
|
|
|
|
S60CreatePackageStep *bs(new S60CreatePackageStep(parent));
|
|
|
|
|
if (bs->fromMap(map))
|
|
|
|
|
return bs;
|
|
|
|
|
delete bs;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-16 14:00:41 +02:00
|
|
|
QStringList S60CreatePackageStepFactory::availableCreationIds(ProjectExplorer::BuildStepList *parent) const
|
2010-02-25 16:51:27 +01:00
|
|
|
{
|
2010-07-16 14:00:41 +02:00
|
|
|
if (parent->id() != QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY))
|
2010-02-25 16:51:27 +01:00
|
|
|
return QStringList();
|
2010-07-16 14:00:41 +02:00
|
|
|
if (parent->target()->id() == QLatin1String(Constants::S60_DEVICE_TARGET_ID))
|
2010-02-25 16:51:27 +01:00
|
|
|
return QStringList() << QLatin1String(SIGN_BS_ID);
|
|
|
|
|
return QStringList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString S60CreatePackageStepFactory::displayNameForId(const QString &id) const
|
|
|
|
|
{
|
|
|
|
|
if (id == QLatin1String(SIGN_BS_ID))
|
2010-05-14 15:45:43 +02:00
|
|
|
return tr("Create SIS Package");
|
2010-02-25 16:51:27 +01:00
|
|
|
return QString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// #pragma mark -- S60SignBuildStepConfigWidget
|
|
|
|
|
|
|
|
|
|
S60CreatePackageStepConfigWidget::S60CreatePackageStepConfigWidget(S60CreatePackageStep *signStep)
|
|
|
|
|
: BuildStepConfigWidget(), m_signStep(signStep)
|
|
|
|
|
{
|
|
|
|
|
m_ui.setupUi(this);
|
2010-05-05 13:48:53 +02:00
|
|
|
m_ui.signaturePath->setExpectedKind(Utils::PathChooser::File);
|
|
|
|
|
m_ui.keyFilePath->setExpectedKind(Utils::PathChooser::File);
|
2010-02-25 16:51:27 +01:00
|
|
|
updateUi();
|
|
|
|
|
connect(m_ui.customCertificateButton, SIGNAL(clicked()),
|
|
|
|
|
this, SLOT(updateFromUi()));
|
|
|
|
|
connect(m_ui.selfSignedButton, SIGNAL(clicked()),
|
|
|
|
|
this, SLOT(updateFromUi()));
|
|
|
|
|
connect(m_ui.signaturePath, SIGNAL(changed(QString)),
|
|
|
|
|
this, SLOT(updateFromUi()));
|
|
|
|
|
connect(m_ui.keyFilePath, SIGNAL(changed(QString)),
|
|
|
|
|
this, SLOT(updateFromUi()));
|
2010-04-30 11:01:06 +02:00
|
|
|
connect(m_ui.smartInstaller, SIGNAL(clicked()),
|
|
|
|
|
this, SLOT(updateFromUi()));
|
2010-07-27 10:46:25 +02:00
|
|
|
connect(m_ui.resetPassphrasesButton, SIGNAL(clicked()),
|
|
|
|
|
this, SLOT(resetPassphrases()));
|
2010-02-25 16:51:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void S60CreatePackageStepConfigWidget::updateUi()
|
|
|
|
|
{
|
|
|
|
|
bool selfSigned = m_signStep->signingMode() == S60CreatePackageStep::SignSelf;
|
|
|
|
|
m_ui.selfSignedButton->setChecked(selfSigned);
|
|
|
|
|
m_ui.customCertificateButton->setChecked(!selfSigned);
|
|
|
|
|
m_ui.signaturePath->setEnabled(!selfSigned);
|
|
|
|
|
m_ui.keyFilePath->setEnabled(!selfSigned);
|
|
|
|
|
m_ui.signaturePath->setPath(m_signStep->customSignaturePath());
|
|
|
|
|
m_ui.keyFilePath->setPath(m_signStep->customKeyPath());
|
2010-05-21 14:12:53 +02:00
|
|
|
m_ui.smartInstaller->setChecked(m_signStep->createsSmartInstaller());
|
2010-02-25 16:51:27 +01:00
|
|
|
emit updateSummary();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void S60CreatePackageStepConfigWidget::updateFromUi()
|
|
|
|
|
{
|
|
|
|
|
bool selfSigned = m_ui.selfSignedButton->isChecked();
|
|
|
|
|
m_signStep->setSigningMode(selfSigned ? S60CreatePackageStep::SignSelf
|
|
|
|
|
: S60CreatePackageStep::SignCustom);
|
|
|
|
|
m_signStep->setCustomSignaturePath(m_ui.signaturePath->path());
|
|
|
|
|
m_signStep->setCustomKeyPath(m_ui.keyFilePath->path());
|
2010-05-21 14:12:53 +02:00
|
|
|
m_signStep->setCreatesSmartInstaller(m_ui.smartInstaller->isChecked());
|
2010-02-25 16:51:27 +01:00
|
|
|
updateUi();
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-27 10:46:25 +02:00
|
|
|
void S60CreatePackageStepConfigWidget::resetPassphrases()
|
|
|
|
|
{
|
|
|
|
|
QMessageBox msgBox(QMessageBox::Question, tr("Reset passwords"),
|
|
|
|
|
tr("Do you want to reset all saved passwords for used keys?"),
|
2010-09-14 14:57:36 +02:00
|
|
|
QMessageBox::Reset|QMessageBox::Cancel, this);
|
|
|
|
|
if (msgBox.exec() == QMessageBox::Reset)
|
2010-07-27 10:46:25 +02:00
|
|
|
m_signStep->resetPassphrases();
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-25 16:51:27 +01:00
|
|
|
QString S60CreatePackageStepConfigWidget::summaryText() const
|
|
|
|
|
{
|
|
|
|
|
QString text;
|
|
|
|
|
if (m_signStep->signingMode() == S60CreatePackageStep::SignSelf) {
|
|
|
|
|
text = tr("self-signed");
|
|
|
|
|
} else {
|
|
|
|
|
text = tr("signed with certificate %1 and key file %2")
|
2010-09-14 14:57:36 +02:00
|
|
|
.arg(m_signStep->customSignaturePath(), m_signStep->customKeyPath());
|
2010-02-25 16:51:27 +01:00
|
|
|
}
|
2010-05-21 14:12:53 +02:00
|
|
|
if (m_signStep->createsSmartInstaller())
|
2010-05-17 17:40:40 +02:00
|
|
|
return tr("<b>Create SIS Package:</b> %1, using Smart Installer").arg(text);
|
2010-05-14 15:45:43 +02:00
|
|
|
return tr("<b>Create SIS Package:</b> %1").arg(text);
|
2010-02-25 16:51:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString S60CreatePackageStepConfigWidget::displayName() const
|
|
|
|
|
{
|
|
|
|
|
return m_signStep->displayName();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void S60CreatePackageStepConfigWidget::init()
|
|
|
|
|
{
|
|
|
|
|
}
|