forked from qt-creator/qt-creator
Move SSH functionality out of the Qt4ProjectManager.
It does not conceptually belong there, and several people have asked for an interface to use the functionality in their own plugins. Task-number: QTCREATORBUG-1204 Reviewed-by: kh1
This commit is contained in:
@@ -105,7 +105,7 @@ void MaemoConfigTestDialog::startConfigTest()
|
||||
"|sed 's/[[:space:]][[:space:]]*/ /g' "
|
||||
"|cut -d ' ' -f 2,3 |sed 's/~.*//g'");
|
||||
QString command(sysInfoCmd + " && " + qtInfoCmd);
|
||||
m_deviceTester = new MaemoSshRunner(m_config, command);
|
||||
m_deviceTester = new MaemoSshRunner(m_config.server, command);
|
||||
connect(m_deviceTester, SIGNAL(remoteOutput(QString)),
|
||||
this, SLOT(processSshOutput(QString)));
|
||||
connect(m_deviceTester, SIGNAL(finished()),
|
||||
@@ -126,12 +126,12 @@ void MaemoConfigTestDialog::handleTestThreadFinished()
|
||||
output.append(tr("\nDid you start Qemu?"));
|
||||
} else {
|
||||
output = parseTestOutput();
|
||||
if (!m_qtVersionOk) {
|
||||
m_ui->errorLabel->setText(tr("Qt version mismatch! "
|
||||
" Expected Qt on device: 4.6.2 or later."));
|
||||
}
|
||||
}
|
||||
m_ui->testResultEdit->setPlainText(output);
|
||||
if (!m_qtVersionOk) {
|
||||
m_ui->errorLabel->setText(tr("Qt version mismatch! Expected Qt on device: "
|
||||
"4.6.2 or later."));
|
||||
}
|
||||
stopConfigTest();
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
typedef Core::SshServerInfo::AuthType AuthType;
|
||||
|
||||
namespace Qt4ProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
@@ -78,7 +80,7 @@ namespace {
|
||||
const QString DefaultHostNameHW(QLatin1String("192.168.2.15"));
|
||||
const QString DefaultHostNameSim(QLatin1String("localhost"));
|
||||
const QString DefaultUserName(QLatin1String("developer"));
|
||||
const MaemoDeviceConfig::AuthType DefaultAuthType(MaemoDeviceConfig::Key);
|
||||
const AuthType DefaultAuthType(Core::SshServerInfo::AuthByKey);
|
||||
const int DefaultTimeout(30);
|
||||
const MaemoDeviceConfig::DeviceType DefaultDeviceType(MaemoDeviceConfig::Physical);
|
||||
};
|
||||
@@ -98,33 +100,35 @@ private:
|
||||
MaemoDeviceConfig::MaemoDeviceConfig(const QString &name, MaemoDeviceConfig::DeviceType devType)
|
||||
: name(name),
|
||||
type(devType),
|
||||
host(defaultHost(type)),
|
||||
sshPort(defaultSshPort(type)),
|
||||
gdbServerPort(defaultGdbServerPort(type)),
|
||||
uname(DefaultUserName),
|
||||
authentication(DefaultAuthType),
|
||||
keyFile(DefaultKeyFile),
|
||||
timeout(DefaultTimeout),
|
||||
internalId(MaemoDeviceConfigurations::instance().m_nextId++)
|
||||
{
|
||||
server.host = defaultHost(type);
|
||||
server.port = defaultSshPort(type);
|
||||
server.uname = DefaultUserName;
|
||||
server.authType = DefaultAuthType;
|
||||
server.privateKeyFile = DefaultKeyFile;
|
||||
server.timeout = DefaultTimeout;
|
||||
}
|
||||
|
||||
MaemoDeviceConfig::MaemoDeviceConfig(const QSettings &settings,
|
||||
quint64 &nextId)
|
||||
: name(settings.value(NameKey).toString()),
|
||||
type(static_cast<DeviceType>(settings.value(TypeKey, DefaultDeviceType).toInt())),
|
||||
host(settings.value(HostKey, defaultHost(type)).toString()),
|
||||
sshPort(settings.value(SshPortKey, defaultSshPort(type)).toInt()),
|
||||
gdbServerPort(settings.value(GdbServerPortKey, defaultGdbServerPort(type)).toInt()),
|
||||
uname(settings.value(UserNameKey, DefaultUserName).toString()),
|
||||
authentication(static_cast<AuthType>(settings.value(AuthKey, DefaultAuthType).toInt())),
|
||||
pwd(settings.value(PasswordKey).toString()),
|
||||
keyFile(settings.value(KeyFileKey, DefaultKeyFile).toString()),
|
||||
timeout(settings.value(TimeoutKey, DefaultTimeout).toInt()),
|
||||
internalId(settings.value(InternalIdKey, nextId).toInt())
|
||||
{
|
||||
if (internalId == nextId)
|
||||
++nextId;
|
||||
server.host = settings.value(HostKey, defaultHost(type)).toString();
|
||||
server.port = settings.value(SshPortKey, defaultSshPort(type)).toInt();
|
||||
server.uname = settings.value(UserNameKey, DefaultUserName).toString();
|
||||
server.authType
|
||||
= static_cast<AuthType>(settings.value(AuthKey, DefaultAuthType).toInt());
|
||||
server.pwd = settings.value(PasswordKey).toString();
|
||||
server.privateKeyFile
|
||||
= settings.value(KeyFileKey, DefaultKeyFile).toString();
|
||||
server.timeout = settings.value(TimeoutKey, DefaultTimeout).toInt();
|
||||
}
|
||||
|
||||
MaemoDeviceConfig::MaemoDeviceConfig()
|
||||
@@ -156,14 +160,14 @@ void MaemoDeviceConfig::save(QSettings &settings) const
|
||||
{
|
||||
settings.setValue(NameKey, name);
|
||||
settings.setValue(TypeKey, type);
|
||||
settings.setValue(HostKey, host);
|
||||
settings.setValue(SshPortKey, sshPort);
|
||||
settings.setValue(HostKey, server.host);
|
||||
settings.setValue(SshPortKey, server.port);
|
||||
settings.setValue(GdbServerPortKey, gdbServerPort);
|
||||
settings.setValue(UserNameKey, uname);
|
||||
settings.setValue(AuthKey, authentication);
|
||||
settings.setValue(PasswordKey, pwd);
|
||||
settings.setValue(KeyFileKey, keyFile);
|
||||
settings.setValue(TimeoutKey, timeout);
|
||||
settings.setValue(UserNameKey, server.uname);
|
||||
settings.setValue(AuthKey, server.authType);
|
||||
settings.setValue(PasswordKey, server.pwd);
|
||||
settings.setValue(KeyFileKey, server.privateKeyFile);
|
||||
settings.setValue(TimeoutKey, server.timeout);
|
||||
settings.setValue(InternalIdKey, internalId);
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
#ifndef MAEMODEVICECONFIGURATIONS_H
|
||||
#define MAEMODEVICECONFIGURATIONS_H
|
||||
|
||||
#include <coreplugin/ssh/sshconnection.h>
|
||||
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QString>
|
||||
@@ -52,22 +54,16 @@ class MaemoDeviceConfig
|
||||
{
|
||||
public:
|
||||
enum DeviceType { Physical, Simulator };
|
||||
enum AuthType { Password, Key };
|
||||
MaemoDeviceConfig();
|
||||
MaemoDeviceConfig(const QString &name, DeviceType type);
|
||||
MaemoDeviceConfig(const QSettings &settings, quint64 &nextId);
|
||||
void save(QSettings &settings) const;
|
||||
bool isValid() const;
|
||||
|
||||
Core::SshServerInfo server;
|
||||
QString name;
|
||||
DeviceType type;
|
||||
QString host;
|
||||
int sshPort;
|
||||
int gdbServerPort;
|
||||
QString uname;
|
||||
AuthType authentication;
|
||||
QString pwd;
|
||||
QString keyFile;
|
||||
int timeout;
|
||||
quint64 internalId;
|
||||
|
||||
private:
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
#include "maemosettingspage.h"
|
||||
#include "maemotoolchain.h"
|
||||
#include "maemorunconfiguration.h"
|
||||
#include "ne7sshobject.h"
|
||||
|
||||
#include <coreplugin/actionmanager/actionmanager.h>
|
||||
#include <coreplugin/coreconstants.h>
|
||||
@@ -83,8 +82,6 @@ MaemoManager::MaemoManager()
|
||||
pluginManager->addObject(m_runConfigurationFactory);
|
||||
pluginManager->addObject(m_packageCreationFactory);
|
||||
pluginManager->addObject(m_settingsPage);
|
||||
|
||||
Ne7SshObject::instance();
|
||||
}
|
||||
|
||||
MaemoManager::~MaemoManager()
|
||||
@@ -96,7 +93,6 @@ MaemoManager::~MaemoManager()
|
||||
pluginManager->removeObject(m_packageCreationFactory);
|
||||
pluginManager->removeObject(m_settingsPage);
|
||||
|
||||
Ne7SshObject::removeInstance();
|
||||
m_instance = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ void AbstractMaemoRunControl::startDeployment(bool forDebugging)
|
||||
emit finished();
|
||||
} else {
|
||||
m_deployables.clear();
|
||||
if (m_runConfig->currentlyNeedsDeployment(m_devConfig.host)) {
|
||||
if (m_runConfig->currentlyNeedsDeployment(m_devConfig.server.host)) {
|
||||
m_deployables.append(Deployable(packageFileName(),
|
||||
QFileInfo(executableOnHost()).canonicalPath(),
|
||||
&MaemoRunConfiguration::wasDeployed));
|
||||
@@ -132,7 +132,7 @@ void AbstractMaemoRunControl::startDeployment(bool forDebugging)
|
||||
m_needsInstall = false;
|
||||
}
|
||||
if (forDebugging
|
||||
&& m_runConfig->debuggingHelpersNeedDeployment(m_devConfig.host)) {
|
||||
&& m_runConfig->debuggingHelpersNeedDeployment(m_devConfig.server.host)) {
|
||||
const QFileInfo &info(m_runConfig->dumperLib());
|
||||
m_deployables.append(Deployable(info.fileName(), info.canonicalPath(),
|
||||
&MaemoRunConfiguration::debuggingHelpersDeployed));
|
||||
@@ -148,7 +148,7 @@ void AbstractMaemoRunControl::deploy()
|
||||
->addTask(m_progress.future(), tr("Deploying"),
|
||||
QLatin1String("Maemo.Deploy"));
|
||||
if (!m_deployables.isEmpty()) {
|
||||
QList<SshDeploySpec> deploySpecs;
|
||||
QList<Core::SftpTransferInfo> deploySpecs;
|
||||
QStringList files;
|
||||
foreach (const Deployable &deployable, m_deployables) {
|
||||
const QString srcFilePath
|
||||
@@ -156,10 +156,11 @@ void AbstractMaemoRunControl::deploy()
|
||||
const QString tgtFilePath
|
||||
= remoteDir() % QDir::separator() % deployable.fileName;
|
||||
files << srcFilePath;
|
||||
deploySpecs << SshDeploySpec(srcFilePath, tgtFilePath);
|
||||
deploySpecs << Core::SftpTransferInfo(srcFilePath,
|
||||
tgtFilePath.toUtf8(), Core::SftpTransferInfo::Upload);
|
||||
}
|
||||
emit appendMessage(this, tr("Files to deploy: %1.").arg(files.join(" ")), false);
|
||||
m_sshDeployer.reset(new MaemoSshDeployer(m_devConfig, deploySpecs));
|
||||
m_sshDeployer.reset(new MaemoSshDeployer(m_devConfig.server, deploySpecs));
|
||||
connect(m_sshDeployer.data(), SIGNAL(finished()),
|
||||
this, SLOT(handleDeployThreadFinished()));
|
||||
connect(m_sshDeployer.data(), SIGNAL(fileCopied(QString)),
|
||||
@@ -177,7 +178,7 @@ void AbstractMaemoRunControl::deploy()
|
||||
void AbstractMaemoRunControl::handleFileCopied()
|
||||
{
|
||||
Deployable deployable = m_deployables.takeFirst();
|
||||
(m_runConfig->*deployable.updateTimestamp)(m_devConfig.host);
|
||||
(m_runConfig->*deployable.updateTimestamp)(m_devConfig.server.host);
|
||||
m_progress.setProgressValue(m_progress.progressValue() + 1);
|
||||
}
|
||||
|
||||
@@ -208,7 +209,7 @@ bool AbstractMaemoRunControl::isCleaning() const
|
||||
|
||||
void AbstractMaemoRunControl::startExecution()
|
||||
{
|
||||
m_sshRunner.reset(new MaemoSshRunner(m_devConfig, remoteCall()));
|
||||
m_sshRunner.reset(new MaemoSshRunner(m_devConfig.server, remoteCall()));
|
||||
connect(m_sshRunner.data(), SIGNAL(finished()),
|
||||
this, SLOT(handleRunThreadFinished()));
|
||||
connect(m_sshRunner.data(), SIGNAL(remoteOutput(QString)),
|
||||
@@ -246,7 +247,7 @@ void AbstractMaemoRunControl::killRemoteProcesses(const QStringList &apps,
|
||||
remoteCall.remove(remoteCall.count() - 1, 1); // Get rid of trailing semicolon.
|
||||
QScopedPointer<MaemoSshRunner> &runner
|
||||
= initialCleanup ? m_initialCleaner : m_sshStopper;
|
||||
runner.reset(new MaemoSshRunner(m_devConfig, remoteCall));
|
||||
runner.reset(new MaemoSshRunner(m_devConfig.server, remoteCall));
|
||||
if (initialCleanup)
|
||||
connect(runner.data(), SIGNAL(finished()),
|
||||
this, SLOT(handleInitialCleanupFinished()));
|
||||
@@ -296,7 +297,6 @@ void AbstractMaemoRunControl::handleRunThreadFinished()
|
||||
|
||||
const QString AbstractMaemoRunControl::executableOnHost() const
|
||||
{
|
||||
qDebug("runconfig->executable: %s", qPrintable(m_runConfig->executable()));
|
||||
return m_runConfig->executable();
|
||||
}
|
||||
|
||||
@@ -307,7 +307,7 @@ const QString AbstractMaemoRunControl::executableFileName() const
|
||||
|
||||
const QString AbstractMaemoRunControl::remoteDir() const
|
||||
{
|
||||
return homeDirOnDevice(m_devConfig.uname);
|
||||
return homeDirOnDevice(m_devConfig.server.uname);
|
||||
}
|
||||
|
||||
QString AbstractMaemoRunControl::remoteSudo() const
|
||||
@@ -384,7 +384,7 @@ MaemoDebugRunControl::MaemoDebugRunControl(RunConfiguration *runConfiguration)
|
||||
m_startParams->startMode = Debugger::StartRemote;
|
||||
m_startParams->executable = executableOnHost();
|
||||
m_startParams->remoteChannel
|
||||
= m_devConfig.host % QLatin1Char(':') % gdbServerPort();
|
||||
= m_devConfig.server.host % QLatin1Char(':') % gdbServerPort();
|
||||
m_startParams->remoteArchitecture = QLatin1String("arm");
|
||||
m_startParams->sysRoot = m_runConfig->sysRoot();
|
||||
m_startParams->toolChainType = ToolChain::GCC_MAEMO;
|
||||
|
||||
@@ -190,31 +190,31 @@ void MaemoSettingsWidget::display(const MaemoDeviceConfig &devConfig)
|
||||
otherConfig = &m_lastConfigHW;
|
||||
m_ui->simulatorButton->setChecked(true);
|
||||
}
|
||||
otherConfig->authentication = devConfig.authentication;
|
||||
otherConfig->timeout = devConfig.timeout;
|
||||
otherConfig->pwd = devConfig.pwd;
|
||||
otherConfig->keyFile = devConfig.keyFile;
|
||||
otherConfig->server.authType = devConfig.server.authType;
|
||||
otherConfig->server.timeout = devConfig.server.timeout;
|
||||
otherConfig->server.pwd = devConfig.server.pwd;
|
||||
otherConfig->server.privateKeyFile = devConfig.server.privateKeyFile;
|
||||
|
||||
if (devConfig.authentication == MaemoDeviceConfig::Password)
|
||||
if (devConfig.server.authType == Core::SshServerInfo::AuthByPwd)
|
||||
m_ui->passwordButton->setChecked(true);
|
||||
else
|
||||
m_ui->keyButton->setChecked(true);
|
||||
m_ui->detailsWidget->setEnabled(true);
|
||||
m_nameValidator->setDisplayName(devConfig.name);
|
||||
m_ui->timeoutSpinBox->setValue(devConfig.timeout);
|
||||
m_ui->timeoutSpinBox->setValue(devConfig.server.timeout);
|
||||
fillInValues();
|
||||
}
|
||||
|
||||
void MaemoSettingsWidget::fillInValues()
|
||||
{
|
||||
m_ui->nameLineEdit->setText(currentConfig().name);
|
||||
m_ui->hostLineEdit->setText(currentConfig().host);
|
||||
m_ui->sshPortSpinBox->setValue(currentConfig().sshPort);
|
||||
m_ui->hostLineEdit->setText(currentConfig().server.host);
|
||||
m_ui->sshPortSpinBox->setValue(currentConfig().server.port);
|
||||
m_ui->gdbServerPortSpinBox->setValue(currentConfig().gdbServerPort);
|
||||
m_ui->timeoutSpinBox->setValue(currentConfig().timeout);
|
||||
m_ui->userLineEdit->setText(currentConfig().uname);
|
||||
m_ui->pwdLineEdit->setText(currentConfig().pwd);
|
||||
m_ui->keyFileLineEdit->setPath(currentConfig().keyFile);
|
||||
m_ui->timeoutSpinBox->setValue(currentConfig().server.timeout);
|
||||
m_ui->userLineEdit->setText(currentConfig().server.uname);
|
||||
m_ui->pwdLineEdit->setText(currentConfig().server.pwd);
|
||||
m_ui->keyFileLineEdit->setPath(currentConfig().server.privateKeyFile);
|
||||
|
||||
const bool isSimulator
|
||||
= currentConfig().type == MaemoDeviceConfig::Simulator;
|
||||
@@ -269,9 +269,8 @@ void MaemoSettingsWidget::deviceTypeChanged()
|
||||
void MaemoSettingsWidget::authenticationTypeChanged()
|
||||
{
|
||||
const bool usePassword = m_ui->passwordButton->isChecked();
|
||||
currentConfig().authentication = usePassword
|
||||
? MaemoDeviceConfig::Password
|
||||
: MaemoDeviceConfig::Key;
|
||||
currentConfig().server.authType
|
||||
= usePassword ? Core::SshServerInfo::AuthByPwd : Core::SshServerInfo::AuthByKey;
|
||||
m_ui->pwdLineEdit->setEnabled(usePassword);
|
||||
m_ui->passwordLabel->setEnabled(usePassword);
|
||||
m_ui->keyFileLineEdit->setEnabled(!usePassword);
|
||||
@@ -280,12 +279,12 @@ void MaemoSettingsWidget::authenticationTypeChanged()
|
||||
|
||||
void MaemoSettingsWidget::hostNameEditingFinished()
|
||||
{
|
||||
currentConfig().host = m_ui->hostLineEdit->text();
|
||||
currentConfig().server.host = m_ui->hostLineEdit->text();
|
||||
}
|
||||
|
||||
void MaemoSettingsWidget::sshPortEditingFinished()
|
||||
{
|
||||
currentConfig().sshPort = m_ui->sshPortSpinBox->value();
|
||||
currentConfig().server.port = m_ui->sshPortSpinBox->value();
|
||||
}
|
||||
|
||||
void MaemoSettingsWidget::gdbServerPortEditingFinished()
|
||||
@@ -295,22 +294,22 @@ void MaemoSettingsWidget::gdbServerPortEditingFinished()
|
||||
|
||||
void MaemoSettingsWidget::timeoutEditingFinished()
|
||||
{
|
||||
currentConfig().timeout = m_ui->timeoutSpinBox->value();
|
||||
currentConfig().server.timeout = m_ui->timeoutSpinBox->value();
|
||||
}
|
||||
|
||||
void MaemoSettingsWidget::userNameEditingFinished()
|
||||
{
|
||||
currentConfig().uname = m_ui->userLineEdit->text();
|
||||
currentConfig().server.uname = m_ui->userLineEdit->text();
|
||||
}
|
||||
|
||||
void MaemoSettingsWidget::passwordEditingFinished()
|
||||
{
|
||||
currentConfig().pwd = m_ui->pwdLineEdit->text();
|
||||
currentConfig().server.pwd = m_ui->pwdLineEdit->text();
|
||||
}
|
||||
|
||||
void MaemoSettingsWidget::keyFileEditingFinished()
|
||||
{
|
||||
currentConfig().keyFile = m_ui->keyFileLineEdit->path();
|
||||
currentConfig().server.privateKeyFile = m_ui->keyFileLineEdit->path();
|
||||
}
|
||||
|
||||
void MaemoSettingsWidget::testConfig()
|
||||
@@ -322,18 +321,9 @@ void MaemoSettingsWidget::testConfig()
|
||||
void MaemoSettingsWidget::showGenerateSshKeyDialog()
|
||||
{
|
||||
MaemoSshConfigDialog dialog(this);
|
||||
connect(&dialog, SIGNAL(publicKeyGenerated(QString)), this,
|
||||
SLOT(setPublicKey(QString)));
|
||||
connect(&dialog, SIGNAL(privateKeyGenerated(QString)), this,
|
||||
SLOT(setPrivateKey(QString)));
|
||||
dialog.exec();
|
||||
}
|
||||
|
||||
void MaemoSettingsWidget::setPublicKey(const QString &path)
|
||||
{
|
||||
m_publicKeyFileName = path;
|
||||
}
|
||||
|
||||
void MaemoSettingsWidget::setPrivateKey(const QString &path)
|
||||
{
|
||||
m_ui->keyFileLineEdit->setPath(path);
|
||||
@@ -345,30 +335,29 @@ void MaemoSettingsWidget::deployKey()
|
||||
if (m_keyDeployer)
|
||||
return;
|
||||
|
||||
if (!QFileInfo(m_publicKeyFileName).exists()) {
|
||||
const QString &dir = QFileInfo(currentConfig().keyFile).path();
|
||||
m_publicKeyFileName = QFileDialog::getOpenFileName(this,
|
||||
tr("Choose public key file"), dir,
|
||||
tr("Public Key Files(*.pub);;All Files (*)"));
|
||||
}
|
||||
|
||||
if (m_publicKeyFileName.isEmpty())
|
||||
const QString &dir
|
||||
= QFileInfo(currentConfig().server.privateKeyFile).path();
|
||||
QString publicKeyFileName = QFileDialog::getOpenFileName(this,
|
||||
tr("Choose public key file"), dir,
|
||||
tr("Public Key Files(*.pub);;All Files (*)"));
|
||||
if (publicKeyFileName.isEmpty())
|
||||
return;
|
||||
QFile keyFile(m_publicKeyFileName);
|
||||
|
||||
QFile keyFile(publicKeyFileName);
|
||||
QByteArray key;
|
||||
const bool keyFileAccessible = keyFile.open(QIODevice::ReadOnly);
|
||||
if (keyFileAccessible)
|
||||
key = keyFile.readAll();
|
||||
if (!keyFileAccessible || keyFile.error() != QFile::NoError) {
|
||||
QMessageBox::critical(this, tr("Deployment Failed"),
|
||||
tr("Could not read public key file '%1'.").arg(m_publicKeyFileName));
|
||||
tr("Could not read public key file '%1'.").arg(publicKeyFileName));
|
||||
return;
|
||||
}
|
||||
|
||||
m_ui->deployKeyButton->disconnect();
|
||||
const QString command = QLatin1String("test -d .ssh || mkdir .ssh && echo '")
|
||||
+ key + QLatin1String("' >> .ssh/authorized_keys");
|
||||
m_keyDeployer = new MaemoSshRunner(currentConfig(), command);
|
||||
m_keyDeployer = new MaemoSshRunner(currentConfig().server, command);
|
||||
connect(m_keyDeployer, SIGNAL(finished()),
|
||||
this, SLOT(handleDeployThreadFinished()));
|
||||
m_ui->deployKeyButton->setText(tr("Stop deploying"));
|
||||
@@ -399,7 +388,7 @@ void MaemoSettingsWidget::stopDeploying()
|
||||
m_keyDeployer->stop();
|
||||
delete m_keyDeployer;
|
||||
m_keyDeployer = 0;
|
||||
m_ui->deployKeyButton->setText(tr("Deploy Key ..."));
|
||||
m_ui->deployKeyButton->setText(tr("Deploy Public Key ..."));
|
||||
connect(m_ui->deployKeyButton, SIGNAL(clicked()), this, SLOT(deployKey()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,6 @@ private slots:
|
||||
void testConfig();
|
||||
|
||||
void showGenerateSshKeyDialog();
|
||||
void setPublicKey(const QString &path);
|
||||
void setPrivateKey(const QString &path);
|
||||
|
||||
// For key deploying.
|
||||
@@ -104,7 +103,6 @@ private:
|
||||
MaemoDeviceConfig m_lastConfigSim;
|
||||
NameValidator * const m_nameValidator;
|
||||
MaemoSshRunner *m_keyDeployer;
|
||||
QString m_publicKeyFileName;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>563</width>
|
||||
<width>596</width>
|
||||
<height>336</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -335,7 +335,7 @@
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Deploy public Key ...</string>
|
||||
<string>Deploy Public Key ...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -35,23 +35,23 @@
|
||||
#include "maemosshconfigdialog.h"
|
||||
|
||||
#include "maemodeviceconfigurations.h"
|
||||
#include "ne7sshobject.h"
|
||||
|
||||
#include <ne7ssh.h>
|
||||
#include <coreplugin/ssh/sshkeygenerator.h>
|
||||
|
||||
#include <QtCore/QDir>
|
||||
|
||||
#include <QtNetwork/QHostInfo>
|
||||
|
||||
#include <QtGui/QApplication>
|
||||
#include <QtGui/QDesktopServices>
|
||||
#include <QtGui/QFileDialog>
|
||||
#include <QtGui/QMessageBox>
|
||||
#include <QtNetwork/QHostInfo>
|
||||
|
||||
|
||||
using namespace Qt4ProjectManager::Internal;
|
||||
|
||||
MaemoSshConfigDialog::MaemoSshConfigDialog(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, home(QDesktopServices::storageLocation(QDesktopServices::HomeLocation))
|
||||
, m_keyGenerator(new Core::SshKeyGenerator)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
|
||||
@@ -75,26 +75,22 @@ void MaemoSshConfigDialog::slotToggled()
|
||||
|
||||
void MaemoSshConfigDialog::generateSshKey()
|
||||
{
|
||||
algorithm = m_ui.rsa->isChecked() ? "rsa" : "dsa";
|
||||
tmpKey = QDir::tempPath().append(QLatin1Char('/') + algorithm).toUtf8();
|
||||
const Core::SshKeyGenerator::KeyType keyType = m_ui.rsa->isChecked()
|
||||
? Core::SshKeyGenerator::Rsa
|
||||
: Core::SshKeyGenerator::Dsa;
|
||||
|
||||
QByteArray userId = QString(home.mid(home.lastIndexOf(QLatin1Char('/')) + 1)
|
||||
+ QLatin1Char('@') + QHostInfo::localHostName()).toUtf8();
|
||||
|
||||
QFile::remove(tmpKey);
|
||||
QFile::remove(tmpKey + ".pub");
|
||||
|
||||
QApplication::setOverrideCursor(Qt::BusyCursor);
|
||||
|
||||
QSharedPointer<ne7ssh> ssh = Ne7SshObject::instance()->get();
|
||||
if (ssh->generateKeyPair(algorithm, userId, tmpKey, tmpKey + ".pub",
|
||||
m_ui.comboBox->currentText().toUShort())) {
|
||||
QFile file(tmpKey + ".pub");
|
||||
if (file.open(QIODevice::ReadOnly))
|
||||
m_ui.plainTextEdit->setPlainText(file.readAll());
|
||||
if (m_keyGenerator->generateKeys(keyType, userId,
|
||||
m_ui.comboBox->currentText().toUShort())) {
|
||||
m_ui.plainTextEdit->setPlainText(m_keyGenerator->publicKey());
|
||||
m_ui.savePublicKey->setEnabled(true);
|
||||
m_ui.savePrivateKey->setEnabled(true);
|
||||
} else {
|
||||
m_ui.plainTextEdit->setPlainText(tr("Could not create SSH key pair."));
|
||||
m_ui.plainTextEdit->setPlainText(m_keyGenerator->error());
|
||||
}
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
@@ -102,18 +98,12 @@ void MaemoSshConfigDialog::generateSshKey()
|
||||
|
||||
void MaemoSshConfigDialog::savePublicKey()
|
||||
{
|
||||
checkSshDir();
|
||||
copyFile(QFileDialog::getSaveFileName(this, tr("Choose folder to save "
|
||||
"public key file"), home + QString::fromLatin1("/.ssh/id_%1.pub")
|
||||
.arg(algorithm.constData())), true);
|
||||
saveKey(true);
|
||||
}
|
||||
|
||||
void MaemoSshConfigDialog::savePrivateKey()
|
||||
{
|
||||
checkSshDir();
|
||||
copyFile(QFileDialog::getSaveFileName(this, tr("Choose folder to save "
|
||||
"private key file"), home + QString::fromLatin1("/.ssh/id_%1")
|
||||
.arg(algorithm.constData())), false);
|
||||
saveKey(false);
|
||||
}
|
||||
|
||||
void MaemoSshConfigDialog::checkSshDir()
|
||||
@@ -123,15 +113,31 @@ void MaemoSshConfigDialog::checkSshDir()
|
||||
dir.mkpath(home + QString::fromLatin1("/.ssh"));
|
||||
}
|
||||
|
||||
void MaemoSshConfigDialog::copyFile(const QString &file, bool pubKey)
|
||||
void MaemoSshConfigDialog::saveKey(bool publicKey)
|
||||
{
|
||||
if (!file.isEmpty()) {
|
||||
if (!QFile::exists(file) || QFile::remove(file)) {
|
||||
QFile(tmpKey + (pubKey ? ".pub" : "")).copy(file);
|
||||
if (pubKey)
|
||||
emit publicKeyGenerated(file);
|
||||
else
|
||||
emit privateKeyGenerated(file);
|
||||
}
|
||||
checkSshDir();
|
||||
const QString suggestedTypeSuffix =
|
||||
m_keyGenerator->type() == Core::SshKeyGenerator::Rsa ? "rsa" : "dsa";
|
||||
const QString suggestedName = home + QString::fromLatin1("/.ssh/id_%1%2")
|
||||
.arg(suggestedTypeSuffix).arg(publicKey ? ".pub" : "");
|
||||
const QString dlgTitle
|
||||
= publicKey ? tr("Save public key file") : tr("Save private key file");
|
||||
const QString fileName
|
||||
= QFileDialog::getSaveFileName(this, dlgTitle, suggestedName);
|
||||
if (fileName.isEmpty())
|
||||
return;
|
||||
|
||||
QFile file(fileName);
|
||||
const bool canOpen = file.open(QIODevice::WriteOnly);
|
||||
if (canOpen)
|
||||
file.write(publicKey
|
||||
? m_keyGenerator->publicKey().toUtf8()
|
||||
: m_keyGenerator->privateKey().toUtf8());
|
||||
if (!canOpen || file.error() != QFile::NoError) {
|
||||
QMessageBox::critical(this, tr("Error writing file"),
|
||||
tr("Could not write file '%1':\n %2")
|
||||
.arg(fileName, file.errorString()));
|
||||
} else if (!publicKey) {
|
||||
emit privateKeyGenerated(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,8 +37,13 @@
|
||||
|
||||
#include "ui_maemosshconfigdialog.h"
|
||||
|
||||
#include <QtCore/QScopedPointer>
|
||||
#include <QtGui/QDialog>
|
||||
|
||||
namespace Core {
|
||||
class SshKeyGenerator;
|
||||
}
|
||||
|
||||
namespace Qt4ProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
@@ -46,11 +51,10 @@ class MaemoSshConfigDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MaemoSshConfigDialog(QWidget *parent = 0);
|
||||
~MaemoSshConfigDialog();
|
||||
MaemoSshConfigDialog(QWidget *parent = 0);
|
||||
~MaemoSshConfigDialog();
|
||||
|
||||
signals:
|
||||
void publicKeyGenerated(const QString &path);
|
||||
void privateKeyGenerated(const QString &path);
|
||||
|
||||
private slots:
|
||||
@@ -61,12 +65,11 @@ private slots:
|
||||
|
||||
private:
|
||||
void checkSshDir();
|
||||
void copyFile(const QString &file, bool pubKey);
|
||||
void saveKey(bool publicKey);
|
||||
|
||||
private:
|
||||
QString home;
|
||||
QByteArray tmpKey;
|
||||
QByteArray algorithm;
|
||||
QScopedPointer<Core::SshKeyGenerator> m_keyGenerator;
|
||||
Ui::MaemoSshConfigDialog m_ui;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,262 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt Creator.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** No Commercial Usage
|
||||
** This file contains pre-release code and may not be distributed.
|
||||
** You may use this file in accordance with the terms and conditions
|
||||
** contained in the Technology Preview License Agreement accompanying
|
||||
** this package.
|
||||
**
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at qt-info@nokia.com.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "maemosshconnection.h"
|
||||
|
||||
#include "maemodeviceconfigurations.h"
|
||||
#include "ne7sshobject.h"
|
||||
|
||||
#include <ne7ssh.h>
|
||||
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QScopedPointer>
|
||||
#include <QtCore/QStringBuilder>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
namespace Qt4ProjectManager {
|
||||
namespace Internal {
|
||||
namespace {
|
||||
char *alloc(size_t n)
|
||||
{
|
||||
return new char[n];
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Which encoding to use for file names? Unicode? Latin1? ASCII?
|
||||
|
||||
MaemoSshConnection::MaemoSshConnection(const MaemoDeviceConfig &devConf,
|
||||
bool shell)
|
||||
: ssh(Ne7SshObject::instance()->get()),
|
||||
m_channel(-1),
|
||||
m_stopRequested(false)
|
||||
{
|
||||
const QString *authString;
|
||||
int (ne7ssh::*connFunc)(const char *, int, const char *, const char *, bool, int);
|
||||
if (devConf.authentication == MaemoDeviceConfig::Password) {
|
||||
authString = &devConf.pwd;
|
||||
connFunc = &ne7ssh::connectWithPassword;
|
||||
} else {
|
||||
authString = &devConf.keyFile;
|
||||
connFunc = &ne7ssh::connectWithKey;
|
||||
}
|
||||
m_channel = (ssh.data()->*connFunc)(devConf.host.toLatin1(), devConf.sshPort,
|
||||
devConf.uname.toAscii(), authString->toLatin1(), shell, devConf.timeout);
|
||||
if (m_channel == -1)
|
||||
throw MaemoSshException(tr("Could not connect to host"));
|
||||
}
|
||||
|
||||
MaemoSshConnection::~MaemoSshConnection()
|
||||
{
|
||||
qDebug("%s", Q_FUNC_INFO);
|
||||
ssh->close(m_channel);
|
||||
}
|
||||
|
||||
const char *MaemoSshConnection::lastError()
|
||||
{
|
||||
return ssh->errors()->pop(channel());
|
||||
}
|
||||
|
||||
void MaemoSshConnection::stop()
|
||||
{
|
||||
m_stopRequested = true;
|
||||
}
|
||||
|
||||
MaemoInteractiveSshConnection::MaemoInteractiveSshConnection(const MaemoDeviceConfig &devConf)
|
||||
: MaemoSshConnection(devConf, true)
|
||||
{
|
||||
strcpy(m_prompt, devConf.uname == QLatin1String("root") ? "# " : "$ ");
|
||||
if (!ssh->waitFor(channel(), m_prompt, devConf.timeout)) {
|
||||
QScopedPointer<char, QScopedPointerArrayDeleter<char> >
|
||||
shellString(ssh->readAndReset(channel(), alloc));
|
||||
if (!shellString.data()) {
|
||||
const QString error
|
||||
= tr("Could not start remote shell: %1").arg(lastError());
|
||||
throw MaemoSshException(error);
|
||||
} else {
|
||||
const int length = strlen(shellString.data());
|
||||
strcpy(m_prompt, shellString.data() + length - qMin(2, length));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MaemoInteractiveSshConnection::~MaemoInteractiveSshConnection()
|
||||
{
|
||||
ssh->send("exit\n", channel());
|
||||
ssh->waitFor(channel(), m_prompt, 1);
|
||||
}
|
||||
|
||||
void MaemoInteractiveSshConnection::runCommand(const QString &command)
|
||||
{
|
||||
/*
|
||||
* We don't have access to the remote process management, so we
|
||||
* try to track the lifetime of the process by adding a second command
|
||||
* that prints a rare character. When it occurs for the second time (the
|
||||
* first one is the echo from the remote terminal), we assume the
|
||||
* process has finished. If anyone actually prints this special character
|
||||
* in their application, they are out of luck.
|
||||
*/
|
||||
const QString endMarker(QChar(0x13a0));
|
||||
const int endMarkerLen = strlen(endMarker.toUtf8());
|
||||
|
||||
const QString finalCommand
|
||||
= command + QLatin1String(";echo ") + endMarker + QLatin1Char('\n');
|
||||
if (!ssh->send(finalCommand.toUtf8().data(), channel())) {
|
||||
throw MaemoSshException(tr("Error running command: %1")
|
||||
.arg(lastError()));
|
||||
}
|
||||
|
||||
int endMarkerCount = 0;
|
||||
do {
|
||||
ssh->waitFor(channel(), endMarker.toUtf8(), 1); // TODO: Hack net7 to get rid of busy loop.
|
||||
const char * const error = lastError();
|
||||
if (error)
|
||||
throw MaemoSshException(tr("SSH error: %1").arg(error));
|
||||
QScopedPointer<char, QScopedPointerArrayDeleter<char> >
|
||||
output(ssh->readAndReset(channel(), alloc));
|
||||
|
||||
/*
|
||||
* The output the user should see is everything after the first
|
||||
* and before the last occurrence of our marker string.
|
||||
*/
|
||||
if (output.data()) {
|
||||
const char *firstCharToEmit;
|
||||
int charsToEmitCount;
|
||||
const char * const endMarkerPos
|
||||
= strstr(output.data(), endMarker.toUtf8());
|
||||
if (endMarkerPos) {
|
||||
if (endMarkerCount++ == 0) {
|
||||
emit remoteOutput(QLatin1String("========== Remote output starts now. ==========\n"));
|
||||
firstCharToEmit = endMarkerPos + endMarkerLen + 1;
|
||||
const char * const endMarkerPos2
|
||||
= strstr(firstCharToEmit, endMarker.toUtf8());
|
||||
if (endMarkerPos2) {
|
||||
++ endMarkerCount;
|
||||
charsToEmitCount = endMarkerPos2 - firstCharToEmit;
|
||||
} else {
|
||||
charsToEmitCount = -1;
|
||||
}
|
||||
} else {
|
||||
firstCharToEmit = output.data();
|
||||
charsToEmitCount = endMarkerPos - output.data();
|
||||
}
|
||||
} else {
|
||||
if (endMarkerCount == 0) {
|
||||
charsToEmitCount = 0;
|
||||
} else {
|
||||
firstCharToEmit = output.data();
|
||||
charsToEmitCount = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (charsToEmitCount != 0)
|
||||
emit remoteOutput(QString::fromUtf8(firstCharToEmit, charsToEmitCount));
|
||||
}
|
||||
} while (endMarkerCount < 2 && !stopRequested());
|
||||
emit remoteOutput(QLatin1String("========== Remote output ends now. ==========\n"));
|
||||
}
|
||||
|
||||
MaemoInteractiveSshConnection::Ptr MaemoInteractiveSshConnection::create(const MaemoDeviceConfig &devConf)
|
||||
{
|
||||
return Ptr(new MaemoInteractiveSshConnection(devConf));
|
||||
}
|
||||
|
||||
MaemoSftpConnection::MaemoSftpConnection(const MaemoDeviceConfig &devConf)
|
||||
: MaemoSshConnection(devConf, false),
|
||||
sftp(new Ne7SftpSubsystem)
|
||||
{
|
||||
if (!ssh->initSftp(*sftp, channel()) || !sftp->setTimeout(devConf.timeout))
|
||||
throw MaemoSshException(tr("Error setting up SFTP subsystem: %1")
|
||||
.arg(lastError()));
|
||||
}
|
||||
|
||||
MaemoSftpConnection::~MaemoSftpConnection()
|
||||
{
|
||||
}
|
||||
|
||||
class FileManager
|
||||
{
|
||||
public:
|
||||
FileManager(const QString &filePath)
|
||||
: m_file(fopen(filePath.toLatin1().data(), "rb")) {}
|
||||
~FileManager() { if (m_file) fclose(m_file); }
|
||||
FILE *file() const { return m_file; }
|
||||
private:
|
||||
FILE * const m_file;
|
||||
};
|
||||
|
||||
void MaemoSftpConnection::transferFiles(const QList<SshDeploySpec> &deploySpecs)
|
||||
{
|
||||
for (int i = 0; i < deploySpecs.count() && !stopRequested(); ++i) {
|
||||
const SshDeploySpec &deploySpec = deploySpecs.at(i);
|
||||
const QString &curSrcFile = deploySpec.srcFilePath();
|
||||
FileManager fileMgr(curSrcFile);
|
||||
if (!fileMgr.file())
|
||||
throw MaemoSshException(tr("Could not open file '%1'").arg(curSrcFile));
|
||||
const QString &curTgtFile = deploySpec.tgtFilePath();
|
||||
|
||||
// TODO: Is the mkdir() method recursive? If not, we have to
|
||||
// introduce a recursive version ourselves.
|
||||
if (deploySpec.mkdir()) {
|
||||
const QString &dir = QFileInfo(curTgtFile).path();
|
||||
sftp->mkdir(dir.toLatin1().data());
|
||||
}
|
||||
|
||||
qDebug("Deploying file %s to %s.", qPrintable(curSrcFile), qPrintable(curTgtFile));
|
||||
|
||||
if (!sftp->put(fileMgr.file(), curTgtFile.toLatin1().data())) {
|
||||
const QString &error = tr("Could not copy local file '%1' "
|
||||
"to remote file '%2': %3").arg(curSrcFile, curTgtFile)
|
||||
.arg(lastError());
|
||||
throw MaemoSshException(error);
|
||||
}
|
||||
emit fileCopied(curSrcFile);
|
||||
}
|
||||
}
|
||||
|
||||
MaemoSftpConnection::Ptr MaemoSftpConnection::create(const MaemoDeviceConfig &devConf)
|
||||
{
|
||||
return Ptr(new MaemoSftpConnection(devConf));
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Qt4ProjectManager
|
||||
@@ -1,152 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt Creator.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** No Commercial Usage
|
||||
** This file contains pre-release code and may not be distributed.
|
||||
** You may use this file in accordance with the terms and conditions
|
||||
** contained in the Technology Preview License Agreement accompanying
|
||||
** this package.
|
||||
**
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at qt-info@nokia.com.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef MAEMOSSHCONNECTION_H
|
||||
#define MAEMOSSHCONNECTION_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QScopedPointer>
|
||||
#include <QtCore/QSharedPointer>
|
||||
#include <QtCore/QString>
|
||||
|
||||
class ne7ssh;
|
||||
class Ne7SftpSubsystem;
|
||||
|
||||
namespace Qt4ProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
class MaemoDeviceConfig;
|
||||
|
||||
class MaemoSshException
|
||||
{
|
||||
public:
|
||||
MaemoSshException(const QString &error) : m_error(error) {}
|
||||
const QString &error() const { return m_error; }
|
||||
private:
|
||||
const QString m_error;
|
||||
};
|
||||
|
||||
class MaemoSshConnection : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(MaemoSshConnection)
|
||||
public:
|
||||
typedef QSharedPointer<MaemoSshConnection> Ptr;
|
||||
|
||||
void stop();
|
||||
virtual ~MaemoSshConnection();
|
||||
|
||||
protected:
|
||||
MaemoSshConnection(const MaemoDeviceConfig &devConf, bool shell);
|
||||
int channel() const { return m_channel; }
|
||||
bool stopRequested() const {return m_stopRequested; }
|
||||
const char *lastError();
|
||||
|
||||
QSharedPointer<ne7ssh> ssh;
|
||||
private:
|
||||
int m_channel;
|
||||
volatile bool m_stopRequested;
|
||||
};
|
||||
|
||||
class MaemoInteractiveSshConnection : public MaemoSshConnection
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(MaemoInteractiveSshConnection)
|
||||
public:
|
||||
typedef QSharedPointer<MaemoInteractiveSshConnection> Ptr;
|
||||
|
||||
static Ptr create(const MaemoDeviceConfig &devConf);
|
||||
void runCommand(const QString &command);
|
||||
virtual ~MaemoInteractiveSshConnection();
|
||||
|
||||
signals:
|
||||
void remoteOutput(const QString &output);
|
||||
|
||||
private:
|
||||
MaemoInteractiveSshConnection(const MaemoDeviceConfig &devConf);
|
||||
|
||||
char m_prompt[3];
|
||||
};
|
||||
|
||||
|
||||
class SshDeploySpec
|
||||
{
|
||||
public:
|
||||
SshDeploySpec(const QString &srcFilePath, const QString &tgtFilePath,
|
||||
bool mkdir = false)
|
||||
: m_srcFilePath(srcFilePath), m_tgtFilePath(tgtFilePath), m_mkdir(mkdir)
|
||||
{
|
||||
}
|
||||
|
||||
QString srcFilePath() const { return m_srcFilePath; }
|
||||
QString tgtFilePath() const { return m_tgtFilePath; }
|
||||
bool mkdir() const { return m_mkdir; }
|
||||
|
||||
private:
|
||||
QString m_srcFilePath;
|
||||
QString m_tgtFilePath;
|
||||
bool m_mkdir;
|
||||
};
|
||||
|
||||
class MaemoSftpConnection : public MaemoSshConnection
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(MaemoSftpConnection)
|
||||
public:
|
||||
typedef QSharedPointer<MaemoSftpConnection> Ptr;
|
||||
|
||||
static Ptr create(const MaemoDeviceConfig &devConf);
|
||||
void transferFiles(const QList<SshDeploySpec> &deploySpecs);
|
||||
virtual ~MaemoSftpConnection();
|
||||
|
||||
signals:
|
||||
void fileCopied(const QString &filePath);
|
||||
|
||||
private:
|
||||
MaemoSftpConnection(const MaemoDeviceConfig &devConf);
|
||||
|
||||
QScopedPointer<Ne7SftpSubsystem> sftp;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Qt4ProjectManager
|
||||
|
||||
#endif // MAEMOSSHCONNECTION_H
|
||||
@@ -41,86 +41,164 @@
|
||||
|
||||
#include "maemosshthread.h"
|
||||
|
||||
#include <exception>
|
||||
|
||||
namespace Qt4ProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
MaemoSshThread::MaemoSshThread(const MaemoDeviceConfig &devConf)
|
||||
: m_stopRequested(false), m_devConf(devConf)
|
||||
template <class SshConnection> MaemoSshThread<SshConnection>::MaemoSshThread(const Core::SshServerInfo &server)
|
||||
: m_server(server), m_stopRequested(false)
|
||||
{
|
||||
}
|
||||
|
||||
MaemoSshThread::~MaemoSshThread()
|
||||
template <class SshConnection> MaemoSshThread<SshConnection>::~MaemoSshThread()
|
||||
{
|
||||
stop();
|
||||
wait();
|
||||
}
|
||||
|
||||
void MaemoSshThread::run()
|
||||
template <class SshConnection> void MaemoSshThread<SshConnection>::run()
|
||||
{
|
||||
try {
|
||||
if (!m_stopRequested)
|
||||
runInternal();
|
||||
} catch (const MaemoSshException &e) {
|
||||
m_error = e.error();
|
||||
} catch (const std::exception &e) {
|
||||
// Should in theory not be necessary, but Net7 leaks Botan exceptions.
|
||||
m_error = tr("Error in cryptography backend: %1").arg(QLatin1String(e.what()));
|
||||
}
|
||||
if (m_stopRequested)
|
||||
return;
|
||||
|
||||
if (!runInternal())
|
||||
m_error = m_connection->error();
|
||||
}
|
||||
|
||||
void MaemoSshThread::stop()
|
||||
template<class SshConnection> void MaemoSshThread<SshConnection>::stop()
|
||||
{
|
||||
m_mutex.lock();
|
||||
m_stopRequested = true;
|
||||
m_waitCond.wakeAll();
|
||||
const bool hasConnection = !m_connection.isNull();
|
||||
m_mutex.unlock();
|
||||
if (hasConnection)
|
||||
m_connection->stop();
|
||||
m_connection->quit();
|
||||
m_mutex.unlock();
|
||||
}
|
||||
|
||||
template <class Conn> typename Conn::Ptr MaemoSshThread::createConnection()
|
||||
template<class SshConnection> void MaemoSshThread<SshConnection>::waitForStop()
|
||||
{
|
||||
typename Conn::Ptr connection = Conn::create(m_devConf);
|
||||
m_mutex.lock();
|
||||
while (!stopRequested())
|
||||
m_waitCond.wait(&m_mutex);
|
||||
m_mutex.unlock();
|
||||
}
|
||||
|
||||
template<class SshConnection> void MaemoSshThread<SshConnection>::createConnection()
|
||||
{
|
||||
typename SshConnection::Ptr connection = SshConnection::create(m_server);
|
||||
m_mutex.lock();
|
||||
m_connection = connection;
|
||||
m_mutex.unlock();
|
||||
return connection;
|
||||
}
|
||||
|
||||
MaemoSshRunner::MaemoSshRunner(const MaemoDeviceConfig &devConf,
|
||||
MaemoSshRunner::MaemoSshRunner(const Core::SshServerInfo &server,
|
||||
const QString &command)
|
||||
: MaemoSshThread(devConf), m_command(command)
|
||||
: MaemoSshThread<Core::InteractiveSshConnection>(server),
|
||||
m_command(command)
|
||||
{
|
||||
m_prompt = server.uname == QLatin1String("root") ? "#" : "$";
|
||||
}
|
||||
|
||||
void MaemoSshRunner::runInternal()
|
||||
bool MaemoSshRunner::runInternal()
|
||||
{
|
||||
MaemoInteractiveSshConnection::Ptr connection
|
||||
= createConnection<MaemoInteractiveSshConnection>();
|
||||
createConnection();
|
||||
connect(m_connection.data(), SIGNAL(remoteOutput(QByteArray)),
|
||||
this, SLOT(handleRemoteOutput(QByteArray)));
|
||||
m_endMarkerCount = 0;
|
||||
m_promptEncountered = false;
|
||||
if (!m_connection->start())
|
||||
return false;
|
||||
if (stopRequested())
|
||||
return true;
|
||||
|
||||
waitForStop();
|
||||
return !m_connection->hasError();
|
||||
}
|
||||
|
||||
void MaemoSshRunner::handleRemoteOutput(const QByteArray &output)
|
||||
{
|
||||
// Wait for a prompt before sending the command.
|
||||
if (!m_promptEncountered) {
|
||||
if (output.indexOf(m_prompt) != -1) {
|
||||
m_promptEncountered = true;
|
||||
|
||||
/*
|
||||
* We don't have access to the remote process management, so we
|
||||
* try to track the lifetime of the process by adding a second command
|
||||
* that prints a rare character. When it occurs for the second time (the
|
||||
* first one is the echo from the remote terminal), we assume the
|
||||
* process has finished. If anyone actually prints this special character
|
||||
* in their application, they are out of luck.
|
||||
*/
|
||||
const QString finalCommand = m_command + QLatin1String(";echo ")
|
||||
+ QString::fromUtf8(EndMarker) + QLatin1Char('\n');
|
||||
if (!m_connection->sendInput(finalCommand.toUtf8()))
|
||||
stop();
|
||||
}
|
||||
return;
|
||||
connect(connection.data(), SIGNAL(remoteOutput(QString)),
|
||||
this, SIGNAL(remoteOutput(QString)));
|
||||
connection->runCommand(m_command);
|
||||
}
|
||||
|
||||
/*
|
||||
* The output the user should see is everything after the first
|
||||
* and before the last occurrence of our marker string.
|
||||
* Note: We don't currently handle the case of an incomplete unicode
|
||||
* character being sent.
|
||||
*/
|
||||
int firstCharToEmit;
|
||||
int charsToEmitCount;
|
||||
const int endMarkerPos = output.indexOf(EndMarker);
|
||||
if (endMarkerPos != -1) {
|
||||
if (m_endMarkerCount++ == 0) {
|
||||
firstCharToEmit = endMarkerPos + EndMarker.count() + 1;
|
||||
int endMarkerPos2
|
||||
= output.indexOf(EndMarker, firstCharToEmit);
|
||||
if (endMarkerPos2 != -1) {
|
||||
++ m_endMarkerCount;
|
||||
charsToEmitCount = endMarkerPos2 - firstCharToEmit;
|
||||
} else {
|
||||
charsToEmitCount = -1;
|
||||
}
|
||||
} else {
|
||||
firstCharToEmit = 0;
|
||||
charsToEmitCount = endMarkerPos;
|
||||
}
|
||||
} else {
|
||||
if (m_endMarkerCount == 0) {
|
||||
charsToEmitCount = 0;
|
||||
} else {
|
||||
firstCharToEmit = 0;
|
||||
charsToEmitCount = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (charsToEmitCount != 0)
|
||||
emit remoteOutput(QString::fromUtf8(output.data() + firstCharToEmit,
|
||||
charsToEmitCount));
|
||||
if (m_endMarkerCount == 2)
|
||||
stop();
|
||||
}
|
||||
|
||||
MaemoSshDeployer::MaemoSshDeployer(const MaemoDeviceConfig &devConf,
|
||||
const QList<SshDeploySpec> &deploySpecs)
|
||||
: MaemoSshThread(devConf), m_deploySpecs(deploySpecs)
|
||||
const QByteArray MaemoSshRunner::EndMarker(QString(QChar(0x13a0)).toUtf8());
|
||||
|
||||
|
||||
MaemoSshDeployer::MaemoSshDeployer(const Core::SshServerInfo &server,
|
||||
const QList<Core::SftpTransferInfo> &deploySpecs)
|
||||
: MaemoSshThread<Core::SftpConnection>(server),
|
||||
m_deploySpecs(deploySpecs)
|
||||
{
|
||||
}
|
||||
|
||||
void MaemoSshDeployer::runInternal()
|
||||
bool MaemoSshDeployer::runInternal()
|
||||
{
|
||||
MaemoSftpConnection::Ptr connection
|
||||
= createConnection<MaemoSftpConnection>();
|
||||
createConnection();
|
||||
if (!m_connection->start())
|
||||
return false;
|
||||
if (stopRequested())
|
||||
return;
|
||||
connect(connection.data(), SIGNAL(fileCopied(QString)),
|
||||
return true;
|
||||
|
||||
connect(m_connection.data(), SIGNAL(fileCopied(QString)),
|
||||
this, SIGNAL(fileCopied(QString)));
|
||||
connection->transferFiles(m_deploySpecs);
|
||||
return m_connection->transferFiles(m_deploySpecs);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -43,18 +43,20 @@
|
||||
#define MAEMOSSHTHREAD_H
|
||||
|
||||
#include "maemodeviceconfigurations.h"
|
||||
#include "maemosshconnection.h"
|
||||
|
||||
#include <coreplugin/ssh/sshconnection.h>
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QMutex>
|
||||
#include <QtCore/QThread>
|
||||
#include <QtCore/QWaitCondition>
|
||||
|
||||
namespace Qt4ProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
class MaemoSshThread : public QThread
|
||||
template<class SshConnection> class MaemoSshThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(MaemoSshThread)
|
||||
public:
|
||||
QString error() const { return m_error; }
|
||||
@@ -64,53 +66,62 @@ public:
|
||||
~MaemoSshThread();
|
||||
|
||||
protected:
|
||||
MaemoSshThread(const MaemoDeviceConfig &devConf);
|
||||
template <class Conn> typename Conn::Ptr createConnection();
|
||||
MaemoSshThread(const Core::SshServerInfo &server);
|
||||
void createConnection();
|
||||
bool stopRequested() const { return m_stopRequested; }
|
||||
void waitForStop();
|
||||
|
||||
typename SshConnection::Ptr m_connection;
|
||||
|
||||
private:
|
||||
virtual void runInternal() = 0;
|
||||
virtual bool runInternal() = 0;
|
||||
|
||||
const Core::SshServerInfo m_server;
|
||||
bool m_stopRequested;
|
||||
QString m_error;
|
||||
QMutex m_mutex;
|
||||
const MaemoDeviceConfig m_devConf;
|
||||
MaemoSshConnection::Ptr m_connection;
|
||||
QWaitCondition m_waitCond;
|
||||
};
|
||||
|
||||
|
||||
class MaemoSshRunner : public MaemoSshThread
|
||||
class MaemoSshRunner : public MaemoSshThread<Core::InteractiveSshConnection>
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(MaemoSshRunner)
|
||||
public:
|
||||
MaemoSshRunner(const MaemoDeviceConfig &devConf, const QString &command);
|
||||
MaemoSshRunner(const Core::SshServerInfo &server, const QString &command);
|
||||
|
||||
signals:
|
||||
void remoteOutput(const QString &output);
|
||||
|
||||
private:
|
||||
virtual void runInternal();
|
||||
virtual bool runInternal();
|
||||
Q_SLOT void handleRemoteOutput(const QByteArray &output);
|
||||
|
||||
static const QByteArray EndMarker;
|
||||
|
||||
const QString m_command;
|
||||
const char *m_prompt;
|
||||
int m_endMarkerCount;
|
||||
bool m_promptEncountered;
|
||||
};
|
||||
|
||||
|
||||
class MaemoSshDeployer : public MaemoSshThread
|
||||
class MaemoSshDeployer : public MaemoSshThread<Core::SftpConnection>
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(MaemoSshDeployer)
|
||||
public:
|
||||
MaemoSshDeployer(const MaemoDeviceConfig &devConf,
|
||||
const QList<SshDeploySpec> &deploySpecs);
|
||||
MaemoSshDeployer(const Core::SshServerInfo &server,
|
||||
const QList<Core::SftpTransferInfo> &deploySpecs);
|
||||
|
||||
signals:
|
||||
void fileCopied(const QString &filePath);
|
||||
|
||||
private:
|
||||
virtual void runInternal();
|
||||
virtual bool runInternal();
|
||||
|
||||
const QList<SshDeploySpec> m_deploySpecs;
|
||||
const QList<Core::SftpTransferInfo> m_deploySpecs;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** No Commercial Usage
|
||||
** This file contains pre-release code and may not be distributed.
|
||||
** You may use this file in accordance with the terms and conditions
|
||||
** contained in the Technology Preview License Agreement accompanying
|
||||
** this package.
|
||||
**
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at qt-info@nokia.com.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "ne7sshobject.h"
|
||||
|
||||
#include <QtCore/QMutexLocker>
|
||||
|
||||
#include <ne7ssh.h>
|
||||
|
||||
namespace Qt4ProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
Ne7SshObject *Ne7SshObject::instance()
|
||||
{
|
||||
if (!m_instance)
|
||||
m_instance = new Ne7SshObject;
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
void Ne7SshObject::removeInstance()
|
||||
{
|
||||
delete m_instance;
|
||||
}
|
||||
|
||||
QSharedPointer<ne7ssh> Ne7SshObject::get()
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
QSharedPointer<ne7ssh> shared = m_weakRef.toStrongRef();
|
||||
if (!shared) {
|
||||
shared = QSharedPointer<ne7ssh>(new ne7ssh);
|
||||
m_weakRef = shared;
|
||||
}
|
||||
return shared;
|
||||
}
|
||||
|
||||
Ne7SshObject::Ne7SshObject()
|
||||
{
|
||||
}
|
||||
|
||||
Ne7SshObject *Ne7SshObject::m_instance = 0;
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Qt4ProjectManager
|
||||
@@ -1,76 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** No Commercial Usage
|
||||
** This file contains pre-release code and may not be distributed.
|
||||
** You may use this file in accordance with the terms and conditions
|
||||
** contained in the Technology Preview License Agreement accompanying
|
||||
** this package.
|
||||
**
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at qt-info@nokia.com.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef NE7SSHOBJECT_H
|
||||
#define NE7SSHOBJECT_H
|
||||
|
||||
#include <QtCore/QMutex>
|
||||
#include <QtCore/QSharedPointer>
|
||||
#include <QtCore/QWeakPointer>
|
||||
|
||||
class ne7ssh;
|
||||
|
||||
namespace Qt4ProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
class Ne7SshObject
|
||||
{
|
||||
public:
|
||||
static Ne7SshObject *instance();
|
||||
static void removeInstance();
|
||||
|
||||
QSharedPointer<ne7ssh> get();
|
||||
|
||||
private:
|
||||
Ne7SshObject();
|
||||
Ne7SshObject(const Ne7SshObject &);
|
||||
Ne7SshObject &operator=(const Ne7SshObject &);
|
||||
|
||||
static Ne7SshObject *m_instance;
|
||||
|
||||
QWeakPointer<ne7ssh> m_weakRef;
|
||||
QMutex m_mutex;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Qt4ProjectManager
|
||||
|
||||
#endif // NE7SSHOBJECT_H
|
||||
@@ -1,7 +1,3 @@
|
||||
INCLUDEPATH += $$PWD/../../../libs/3rdparty/botan/build
|
||||
INCLUDEPATH += $$PWD/../../../libs/3rdparty/net7ssh/src
|
||||
LIBS += -l$$qtLibraryTarget(Net7ssh) -l$$qtLibraryTarget(Botan)
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/maemoconfigtestdialog.h \
|
||||
$$PWD/maemoconstants.h \
|
||||
@@ -14,12 +10,10 @@ HEADERS += \
|
||||
$$PWD/maemosettingspage.h \
|
||||
$$PWD/maemosettingswidget.h \
|
||||
$$PWD/maemosshconfigdialog.h \
|
||||
$$PWD/maemosshconnection.h \
|
||||
$$PWD/maemosshthread.h \
|
||||
$$PWD/maemotoolchain.h \
|
||||
$$PWD/maemopackagecreationstep.h \
|
||||
$$PWD/maemopackagecreationfactory.h \
|
||||
$$PWD/ne7sshobject.h \
|
||||
$$PWD/maemopackagecreationwidget.h \
|
||||
$$PWD/maemopackagecontents.h
|
||||
|
||||
@@ -34,12 +28,10 @@ SOURCES += \
|
||||
$$PWD/maemosettingspage.cpp \
|
||||
$$PWD/maemosettingswidget.cpp \
|
||||
$$PWD/maemosshconfigdialog.cpp \
|
||||
$$PWD/maemosshconnection.cpp \
|
||||
$$PWD/maemosshthread.cpp \
|
||||
$$PWD/maemotoolchain.cpp \
|
||||
$$PWD/maemopackagecreationstep.cpp \
|
||||
$$PWD/maemopackagecreationfactory.cpp \
|
||||
$$PWD/ne7sshobject.cpp \
|
||||
$$PWD/maemopackagecreationwidget.cpp \
|
||||
$$PWD/maemopackagecontents.cpp
|
||||
|
||||
|
||||
Reference in New Issue
Block a user