From f4b1c441aae6ba1d433c29229dac6eda2ff60b76 Mon Sep 17 00:00:00 2001 From: Pawel Polanski <pawel.3.polanski@nokia.com> Date: Tue, 27 Jul 2010 10:46:25 +0200 Subject: [PATCH] Added the SignSisParser for Symbian OS Added support for passphrases for keys for Symbian OS Reviewed-by: Tobias Hunger --- .../qt-s60/passphraseforkeydialog.cpp | 73 +++++++ .../qt-s60/passphraseforkeydialog.h | 32 +++ .../qt4projectmanager/qt-s60/qt-s60.pri | 8 +- .../qt-s60/s60createpackagestep.cpp | 199 +++++++++++++++++- .../qt-s60/s60createpackagestep.h | 38 ++++ .../qt-s60/s60createpackagestep.ui | 27 +++ .../qt-s60/signsisparser.cpp | 70 ++++++ .../qt4projectmanager/qt-s60/signsisparser.h | 27 +++ 8 files changed, 463 insertions(+), 11 deletions(-) create mode 100644 src/plugins/qt4projectmanager/qt-s60/passphraseforkeydialog.cpp create mode 100644 src/plugins/qt4projectmanager/qt-s60/passphraseforkeydialog.h create mode 100644 src/plugins/qt4projectmanager/qt-s60/signsisparser.cpp create mode 100644 src/plugins/qt4projectmanager/qt-s60/signsisparser.h diff --git a/src/plugins/qt4projectmanager/qt-s60/passphraseforkeydialog.cpp b/src/plugins/qt4projectmanager/qt-s60/passphraseforkeydialog.cpp new file mode 100644 index 00000000000..3e765a12f4a --- /dev/null +++ b/src/plugins/qt4projectmanager/qt-s60/passphraseforkeydialog.cpp @@ -0,0 +1,73 @@ +#include "passphraseforkeydialog.h" + +#include <QtGui/QDialogButtonBox> +#include <QtGui/QLabel> +#include <QtGui/QFormLayout> +#include <QtGui/QLineEdit> +#include <QtGui/QCheckBox> + +using namespace Qt4ProjectManager; + +PassphraseForKeyDialog::PassphraseForKeyDialog(const QString &keyName, QWidget *parent) + : QDialog(parent) +{ + QFormLayout *formLayout = new QFormLayout(this); + setLayout(formLayout); + + QLabel *passphraseLabel = new QLabel(this); + passphraseLabel->setText(tr("Passphrase:")); + passphraseLabel->setObjectName(QString::fromUtf8("passphraseLabel")); + + formLayout->setWidget(0, QFormLayout::LabelRole, passphraseLabel); + + QLineEdit *passphraseLineEdit = new QLineEdit(this); + passphraseLineEdit->setObjectName(QString::fromUtf8("passphraseLineEdit")); + passphraseLineEdit->setEchoMode(QLineEdit::Password); + + connect(passphraseLineEdit, SIGNAL(textChanged(QString)), this, SLOT(setPassphrase(QString))); + + formLayout->setWidget(0, QFormLayout::FieldRole, passphraseLineEdit); + + m_checkBox = new QCheckBox(this); + m_checkBox->setText(tr("Save passphrase")); + m_checkBox->setObjectName(QString::fromUtf8("checkBox")); + m_checkBox->setToolTip(tr("This is an insecure option. Password will be saved as a plain text!")); + + formLayout->setWidget(1, QFormLayout::LabelRole, m_checkBox); + + QDialogButtonBox *buttonBox = new QDialogButtonBox(this); + buttonBox->setObjectName(QString::fromUtf8("buttonBox")); + buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); + + connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); + connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + + formLayout->setWidget(2, QFormLayout::FieldRole, buttonBox); + setWindowTitle(tr("Passphrase for %1").arg(keyName)); + setFixedSize( sizeHint() ); +} + +void PassphraseForKeyDialog::accept() +{ + done(1); +} + +void PassphraseForKeyDialog::reject() +{ + done(0); +} + +void PassphraseForKeyDialog::setPassphrase(const QString &passphrase) +{ + m_passphrase = passphrase; +} + +QString PassphraseForKeyDialog::passphrase() const +{ + return m_passphrase; +} + +bool PassphraseForKeyDialog::savePassphrase() const +{ + return m_checkBox->isChecked(); +} diff --git a/src/plugins/qt4projectmanager/qt-s60/passphraseforkeydialog.h b/src/plugins/qt4projectmanager/qt-s60/passphraseforkeydialog.h new file mode 100644 index 00000000000..cd231c95dc4 --- /dev/null +++ b/src/plugins/qt4projectmanager/qt-s60/passphraseforkeydialog.h @@ -0,0 +1,32 @@ +#ifndef PASSPHRASEFORKEYDIALOG_H +#define PASSPHRASEFORKEYDIALOG_H + +#include <QtGui/QDialog> + +class QCheckBox; + +namespace Qt4ProjectManager { + +class PassphraseForKeyDialog : public QDialog +{ + Q_OBJECT +public: + explicit PassphraseForKeyDialog(const QString &keyName, QWidget *parent = 0); + + QString passphrase() const; + bool savePassphrase() const; + +protected slots: + void accept(); + void reject(); + void setPassphrase(const QString &passphrase); + +private: + QCheckBox *m_checkBox; + + QString m_passphrase; +}; + +} // namespace Qt4ProjectManager + +#endif // PASSPHRASEFORKEYDIALOG_H diff --git a/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri b/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri index 2fc08a98b3f..96935d99cdc 100644 --- a/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri +++ b/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri @@ -16,7 +16,9 @@ SOURCES += $$PWD/s60devices.cpp \ $$PWD/rvctparser.cpp \ $$PWD/winscwparser.cpp \ qt-s60/s60createpackagestep.cpp \ - qt-s60/s60deploystep.cpp + qt-s60/s60deploystep.cpp \ + qt-s60/signsisparser.cpp \ + qt-s60/passphraseforkeydialog.cpp HEADERS += $$PWD/s60devices.h \ $$PWD/s60devicespreferencepane.h \ $$PWD/s60manager.h \ @@ -32,6 +34,8 @@ HEADERS += $$PWD/s60devices.h \ $$PWD/rvctparser.h \ $$PWD/winscwparser.h \ qt-s60/s60createpackagestep.h \ - qt-s60/s60deploystep.h + qt-s60/s60deploystep.h \ + qt-s60/signsisparser.h \ + qt-s60/passphraseforkeydialog.h FORMS += $$PWD/s60devicespreferencepane.ui \ qt-s60/s60createpackagestep.ui diff --git a/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp b/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp index 694db1012ee..be6f6585ad0 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp @@ -34,6 +34,8 @@ #include "qt4nodes.h" #include "qt4project.h" #include "abldparser.h" +#include "signsisparser.h" +#include "passphraseforkeydialog.h" #include <projectexplorer/buildconfiguration.h> #include <projectexplorer/target.h> @@ -43,6 +45,10 @@ #include <QtCore/QDir> #include <QtCore/QTimer> +#include <QtCore/QCryptographicHash> + +#include <QSettings> +#include <QMessageBox> using namespace Qt4ProjectManager::Internal; @@ -52,6 +58,10 @@ namespace { const char * const CERTIFICATE_KEY("Qt4ProjectManager.S60CreatePackageStep.Certificate"); const char * const KEYFILE_KEY("Qt4ProjectManager.S60CreatePackageStep.Keyfile"); const char * const SMART_INSTALLER_KEY("Qt4ProjectManager.S60CreatorPackageStep.SmartInstaller"); + + 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="); } S60CreatePackageStep::S60CreatePackageStep(ProjectExplorer::BuildConfiguration *bc) : @@ -62,7 +72,9 @@ S60CreatePackageStep::S60CreatePackageStep(ProjectExplorer::BuildConfiguration * m_process(0), m_timer(0), m_eventLoop(0), - m_futureInterface(0) + m_futureInterface(0), + m_errorType(ErrorNone), + m_settings(0) { ctor_package(); } @@ -72,11 +84,14 @@ S60CreatePackageStep::S60CreatePackageStep(ProjectExplorer::BuildConfiguration * m_signingMode(bs->m_signingMode), m_customSignaturePath(bs->m_customSignaturePath), m_customKeyPath(bs->m_customKeyPath), + m_passphrase(bs->m_passphrase), m_createSmartInstaller(bs->m_createSmartInstaller), m_outputParserChain(0), m_timer(0), m_eventLoop(0), - m_futureInterface(0) + m_futureInterface(0), + m_errorType(ErrorNone), + m_settings(0) { ctor_package(); } @@ -88,7 +103,9 @@ S60CreatePackageStep::S60CreatePackageStep(ProjectExplorer::BuildConfiguration * m_outputParserChain(0), m_timer(0), m_eventLoop(0), - m_futureInterface(0) + m_futureInterface(0), + m_errorType(ErrorNone), + m_settings(0) { ctor_package(); } @@ -96,6 +113,11 @@ S60CreatePackageStep::S60CreatePackageStep(ProjectExplorer::BuildConfiguration * void S60CreatePackageStep::ctor_package() { setDisplayName(tr("Create SIS Package", "Create SIS package build step name")); + connect(this, SIGNAL(badPassphrase()), + this, SLOT(definePassphrase()), Qt::QueuedConnection); + + m_settings = new QSettings(QSettings::IniFormat, QSettings::UserScope, + QLatin1String("Nokia"), QLatin1String("QtCreatorKeys"), this); } S60CreatePackageStep::~S60CreatePackageStep() @@ -116,7 +138,7 @@ bool S60CreatePackageStep::fromMap(const QVariantMap &map) { m_signingMode = (SigningMode)map.value(QLatin1String(SIGNMODE_KEY)).toInt(); m_customSignaturePath = map.value(QLatin1String(CERTIFICATE_KEY)).toString(); - m_customKeyPath = map.value(QLatin1String(KEYFILE_KEY)).toString(); + setCustomKeyPath(map.value(QLatin1String(KEYFILE_KEY)).toString()); m_createSmartInstaller = map.value(QLatin1String(SMART_INSTALLER_KEY), false).toBool(); return BuildStep::fromMap(map); } @@ -155,21 +177,85 @@ bool S60CreatePackageStep::init() else m_args << QLatin1String("sis"); if (signingMode() == SignCustom) { - m_args << QLatin1String("QT_SIS_CERTIFICATE=") + QDir::toNativeSeparators(customSignaturePath()) - << QLatin1String("QT_SIS_KEY=") + QDir::toNativeSeparators(customKeyPath()); + 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(); + } } delete m_outputParserChain; m_outputParserChain = new ProjectExplorer::GnuMakeParser; m_outputParserChain->appendOutputParser(new Qt4ProjectManager::AbldParser); + m_outputParserChain->appendOutputParser(new Qt4ProjectManager::SignsisParser); + connect(m_outputParserChain, SIGNAL(addOutput(QString, ProjectExplorer::BuildStep::OutputFormat)), this, SLOT(outputAdded(QString, ProjectExplorer::BuildStep::OutputFormat))); connect(m_outputParserChain, SIGNAL(addTask(ProjectExplorer::Task)), - this, SLOT(taskAdded(ProjectExplorer::Task))); + this, SLOT(taskAdded(ProjectExplorer::Task)), Qt::DirectConnection); return true; } +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(); +} + void S60CreatePackageStep::run(QFutureInterface<bool> &fi) { m_futureInterface = &fi; @@ -242,6 +328,33 @@ void S60CreatePackageStep::slotProcessFinished(int, QProcess::ExitStatus) emit addOutput(tr("The process \"%1\" crashed.").arg(QDir::toNativeSeparators(m_makeCmd)), BuildStep::ErrorMessageOutput); } + 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 ) { + m_eventLoop->exit(true); + 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; + } + if (m_workingDirectories.isEmpty() || !returnValue) { m_eventLoop->exit(returnValue); } else { @@ -253,7 +366,8 @@ void S60CreatePackageStep::slotProcessFinished(int, QProcess::ExitStatus) bool S60CreatePackageStep::startProcess() { - QString workingDirectory = m_workingDirectories.takeFirst(); + m_errorType = ErrorNone; + QString workingDirectory = m_workingDirectories.first(); QDir wd(workingDirectory); if (!wd.exists()) wd.mkpath(wd.absolutePath()); @@ -327,15 +441,35 @@ void S60CreatePackageStep::taskAdded(const ProjectExplorer::Task &task) // TODO which kind of tasks do we get from package building? // No absoulte path } + 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; + } emit addTask(editable); } +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(); +} + void S60CreatePackageStep::outputAdded(const QString &string, ProjectExplorer::BuildStep::OutputFormat format) { emit addOutput(string, format); } - bool S60CreatePackageStep::immutable() const { return false; @@ -374,6 +508,27 @@ QString S60CreatePackageStep::customKeyPath() const void S60CreatePackageStep::setCustomKeyPath(const QString &path) { m_customKeyPath = path; + 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; } bool S60CreatePackageStep::createsSmartInstaller() const @@ -387,6 +542,17 @@ void S60CreatePackageStep::setCreatesSmartInstaller(bool value) static_cast<Qt4BuildConfiguration *>(buildConfiguration())->emitS60CreatesSmartInstallerChanged(); } +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(); +} + // #pragma mark -- S60SignBuildStepFactory S60CreatePackageStepFactory::S60CreatePackageStepFactory(QObject *parent) : @@ -478,6 +644,8 @@ S60CreatePackageStepConfigWidget::S60CreatePackageStepConfigWidget(S60CreatePack this, SLOT(updateFromUi())); connect(m_ui.smartInstaller, SIGNAL(clicked()), this, SLOT(updateFromUi())); + connect(m_ui.resetPassphrasesButton, SIGNAL(clicked()), + this, SLOT(resetPassphrases())); } void S60CreatePackageStepConfigWidget::updateUi() @@ -504,6 +672,19 @@ void S60CreatePackageStepConfigWidget::updateFromUi() updateUi(); } +void S60CreatePackageStepConfigWidget::resetPassphrases() +{ + QMessageBox msgBox(QMessageBox::Question, tr("Reset passwords"), + tr("Do you want to reset all saved passwords for used keys?"), + QMessageBox::Yes|QMessageBox::No, this); + msgBox.button(QMessageBox::Yes)->setText(tr("Reset")); + msgBox.button(QMessageBox::No)->setText(tr("Cancel")); + msgBox.setDefaultButton(QMessageBox::No); + msgBox.setEscapeButton(QMessageBox::No); + if (msgBox.exec() == QMessageBox::Yes) + m_signStep->resetPassphrases(); +} + QString S60CreatePackageStepConfigWidget::summaryText() const { QString text; diff --git a/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.h b/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.h index e4a03985adc..89495a7d117 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.h @@ -35,6 +35,11 @@ #include <projectexplorer/buildstep.h> #include <qt4projectmanager/makestep.h> +#include <QMutex> +#include <QWaitCondition> + +class QSettings; + namespace Qt4ProjectManager { namespace Internal { @@ -59,6 +64,7 @@ public: ProjectExplorer::BuildStep *clone(ProjectExplorer::BuildConfiguration *parent, ProjectExplorer::BuildStep::Type type, ProjectExplorer::BuildStep *product); }; + class S60CreatePackageStep : public ProjectExplorer::BuildStep { Q_OBJECT @@ -85,9 +91,18 @@ public: void setCustomSignaturePath(const QString &path); QString customKeyPath() const; void setCustomKeyPath(const QString &path); + QString passphrase() const ; + void setPassphrase(const QString &passphrase); + QString keyId() const; + void setKeyId(const QString &keyId); bool createsSmartInstaller() const; void setCreatesSmartInstaller(bool value); + void resetPassphrases(); + +signals: + void badPassphrase(); + protected: S60CreatePackageStep(ProjectExplorer::BuildConfiguration *bc, S60CreatePackageStep *bs); S60CreatePackageStep(ProjectExplorer::BuildConfiguration *bc, const QString &id); @@ -102,11 +117,25 @@ private slots: void taskAdded(const ProjectExplorer::Task &task); void outputAdded(const QString &string, ProjectExplorer::BuildStep::OutputFormat format); void checkForCancel(); + void definePassphrase(); private: + enum ErrorType { + ErrorNone = 0, + ErrorUndefined, + ErrorBadPassphrase + }; + void stdOutput(const QString &line); void stdError(const QString &line); bool startProcess(); + + QString generateKeyId(const QString &keyPath) const; + QString loadPassphraseForKey(const QString &keyId); + void savePassphraseForKey(const QString &keyId, const QString &passphrase); + QString elucidatePassphrase(QByteArray obfuscatedPassphrase, const QString &key) const; + QByteArray obfuscatePassphrase(const QString &passphrase, const QString &key) const; + QStringList m_workingDirectories; QString m_makeCmd; @@ -118,6 +147,8 @@ private: SigningMode m_signingMode; QString m_customSignaturePath; QString m_customKeyPath; + QString m_passphrase; + QString m_keyId; bool m_createSmartInstaller; ProjectExplorer::IOutputParser *m_outputParserChain; @@ -125,6 +156,12 @@ private: QTimer *m_timer; QEventLoop *m_eventLoop; QFutureInterface<bool> *m_futureInterface; + ErrorType m_errorType; + + QWaitCondition m_waitCondition; + QMutex m_mutex; + + QSettings *m_settings; }; class S60CreatePackageStepConfigWidget : public ProjectExplorer::BuildStepConfigWidget @@ -139,6 +176,7 @@ public: private slots: void updateUi(); void updateFromUi(); + void resetPassphrases(); private: S60CreatePackageStep *m_signStep; diff --git a/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.ui b/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.ui index ac7badf26c3..d8309d0f4bb 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.ui +++ b/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.ui @@ -90,6 +90,33 @@ </property> </widget> </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QPushButton" name="resetPassphrasesButton"> + <property name="toolTip"> + <string>Resets saved passphrases for all used keys</string> + </property> + <property name="text"> + <string>Reset passphrases</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> <item> <spacer name="verticalSpacer"> <property name="orientation"> diff --git a/src/plugins/qt4projectmanager/qt-s60/signsisparser.cpp b/src/plugins/qt4projectmanager/qt-s60/signsisparser.cpp new file mode 100644 index 00000000000..2145183bf38 --- /dev/null +++ b/src/plugins/qt4projectmanager/qt-s60/signsisparser.cpp @@ -0,0 +1,70 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 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 "signsisparser.h" + +#include <projectexplorer/projectexplorerconstants.h> +#include <projectexplorer/taskwindow.h> + +using namespace Qt4ProjectManager; +using namespace ProjectExplorer; +using namespace ProjectExplorer::Constants; + +SignsisParser::SignsisParser() +{ + m_signSis.setPattern("^(error):([A-Z\\d]+):(.+)$"); + m_signSis.setMinimal(true); +} + +void SignsisParser::stdOutput(const QString &line) +{ + QString lne = line.trimmed(); + + if (m_signSis.indexIn(lne) > -1) { + QString errorDescription(m_signSis.cap(3)); + int index = errorDescription.indexOf(QLatin1String("error:")); + if (index >= 0) { + stdOutput(errorDescription.mid(index)); + errorDescription = errorDescription.left(index); + } + Task task(Task::Error, + errorDescription /* description */, + QString(), -1, + TASK_CATEGORY_BUILDSYSTEM); + emit addTask(task); + } + IOutputParser::stdOutput(line); +} + +void SignsisParser::stdError(const QString &line) +{ + stdOutput(line); + IOutputParser::stdError(line); +} diff --git a/src/plugins/qt4projectmanager/qt-s60/signsisparser.h b/src/plugins/qt4projectmanager/qt-s60/signsisparser.h new file mode 100644 index 00000000000..85529a5d026 --- /dev/null +++ b/src/plugins/qt4projectmanager/qt-s60/signsisparser.h @@ -0,0 +1,27 @@ +#ifndef SIGNSISPARSER_H +#define SIGNSISPARSER_H + +#include <projectexplorer/ioutputparser.h> + +#include <QtCore/QRegExp> + +namespace Qt4ProjectManager { + +class SignsisParser : public ProjectExplorer::IOutputParser +{ + Q_OBJECT + +public: + SignsisParser(); + + virtual void stdOutput(const QString & line); + virtual void stdError(const QString & line); + +private: + QRegExp m_signSis; +}; + +} // namespace Qt4ProjectExplorer + + +#endif // SIGNSISPARSER_H -- GitLab