From 60f97e5cff42a59bcb78d02ee647353d1e684a15 Mon Sep 17 00:00:00 2001
From: ck <qt-info@nokia.com>
Date: Thu, 7 Jan 2010 16:42:01 +0100
Subject: [PATCH] Maemo: Add key deployment feature to options page.

---
 .../qt-maemo/maemodeviceconfigurations.cpp    | 13 +++
 .../qt-maemo/maemodeviceconfigurations.h      |  2 +
 .../qt-maemo/maemoruncontrol.cpp              |  8 +-
 .../qt-maemo/maemosettingspage.cpp            | 86 ++++++++++++++++++-
 .../qt-maemo/maemosettingswidget.ui           | 59 +++++++++----
 .../qt-maemo/maemosshconnection.cpp           | 24 +++---
 .../qt-maemo/maemosshconnection.h             |  8 +-
 7 files changed, 163 insertions(+), 37 deletions(-)

diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.cpp
index 39cd9d5c609..bd2e2aa06fc 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.cpp
@@ -37,6 +37,7 @@
 #include <coreplugin/icore.h>
 
 #include <QtCore/QSettings>
+#include <QtCore/QStringBuilder>
 #include <QtGui/QDesktopServices>
 
 #include <algorithm>
@@ -44,6 +45,18 @@
 namespace Qt4ProjectManager {
 namespace Internal {
 
+QString homeDirOnDevice(const QString &uname)
+{
+    const QString &dir = uname == QLatin1String("root")
+        ? QLatin1String("/root")
+            : uname == QLatin1String("developer")
+            ? QLatin1String("/var/local/mad-developer-home")
+                : QLatin1String("/home/") + uname;
+    qDebug("%s: user name %s is mapped to home dir %s",
+           Q_FUNC_INFO, qPrintable(uname), qPrintable(dir));
+    return dir;
+}
+
 namespace {
     const QLatin1String SettingsGroup("MaemoDeviceConfigs");
     const QLatin1String IdCounterKey("IdCounter");
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.h b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.h
index 887b82050c5..e79e19736d7 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeviceconfigurations.h
@@ -47,6 +47,8 @@ QT_END_NAMESPACE
 namespace Qt4ProjectManager {
 namespace Internal {
 
+QString homeDirOnDevice(const QString &uname);
+
 class MaemoDeviceConfig
 {
 public:
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.cpp
index 32c977cea32..de5f01476ae 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.cpp
@@ -123,8 +123,10 @@ void AbstractMaemoRunControl::deploy()
         foreach (const Deployable &deployable, deployables) {
             const QString srcFilePath
                 = deployable.dir % QDir::separator() % deployable.fileName;
+            const QString tgtFilePath
+                = remoteDir() % QDir::separator() % deployable.fileName;
             files << srcFilePath;
-            deploySpecs << SshDeploySpec(srcFilePath, remoteDir());
+            deploySpecs << SshDeploySpec(srcFilePath, tgtFilePath);
         }
         emit addToOutputWindow(this, tr("Files to deploy: %1.").arg(files.join(" ")));
         sshDeployer.reset(new MaemoSshDeployer(devConfig, deploySpecs));
@@ -249,9 +251,7 @@ const QString AbstractMaemoRunControl::executableFileName() const
 
 const QString AbstractMaemoRunControl::remoteDir() const
 {
-    return devConfig.uname == QString::fromLocal8Bit("root")
-        ? QString::fromLocal8Bit("/root")
-        : QString::fromLocal8Bit("/home/") + devConfig.uname;
+    return homeDirOnDevice(devConfig.uname);
 }
 
 const QStringList AbstractMaemoRunControl::options() const
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemosettingspage.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemosettingspage.cpp
index 236cd18a849..66575ff87e2 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemosettingspage.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemosettingspage.cpp
@@ -47,7 +47,9 @@
 #include "ui_maemosettingswidget.h"
 #include "maemosettingspage.h"
 
+#include <QtCore/QFileInfo>
 #include <QtCore/QRegExp>
+#include <QtGui/QFileDialog>
 #include <QtGui/QIntValidator>
 
 #include <algorithm>
@@ -136,11 +138,18 @@ private slots:
     void userNameEditingFinished();
     void passwordEditingFinished();
     void keyFileEditingFinished();
+
+    // For configuration testing.
     void testConfig();
     void processSshOutput(const QString &data);
-    void handleSshFinished();
+    void handleTestThreadFinished();
     void stopConfigTest();
 
+    // For key deploying.
+    void deployKey();
+    void handleDeployThreadFinished();
+    void stopDeploying();
+
 private:
     void initGui();
     void display(const MaemoDeviceConfig &devConfig);
@@ -156,6 +165,7 @@ private:
     PortAndTimeoutValidator m_timeoutValidator;
     NameValidator m_nameValidator;
 #ifdef USE_SSH_LIB
+    MaemoSshDeployer *m_keyDeployer;
     MaemoSshRunner *m_deviceTester;
 #endif
     QString m_deviceTestOutput;
@@ -237,6 +247,7 @@ void MaemoSettingsWidget::initGui()
 
 #ifndef USE_SSH_LIB // Password authentication does not currently work due to ssh/scp issues.
     m_ui->testConfigButton->hide();
+    m_ui->deployKeyButton->hide();
     m_ui->testResultEdit->hide();
     m_ui->authTypeLabel->hide();
     m_ui->authTypeButtonsWidget->hide();
@@ -347,6 +358,7 @@ void MaemoSettingsWidget::authenticationTypeChanged()
     m_ui->passwordLabel->setEnabled(usePassword);
     m_ui->keyFileLineEdit->setEnabled(!usePassword);
     m_ui->keyLabel->setEnabled(!usePassword);
+    m_ui->deployKeyButton->setEnabled(usePassword);
 }
 
 void MaemoSettingsWidget::hostNameEditingFinished()
@@ -407,7 +419,7 @@ void MaemoSettingsWidget::testConfig()
     connect(m_deviceTester, SIGNAL(remoteOutput(QString)),
             this, SLOT(processSshOutput(QString)));
     connect(m_deviceTester, SIGNAL(finished()),
-            this, SLOT(handleSshFinished()));
+            this, SLOT(handleTestThreadFinished()));
     m_ui->testConfigButton->setText(tr("Stop test"));
     connect(m_ui->testConfigButton, SIGNAL(clicked()),
             this, SLOT(stopConfigTest()));
@@ -421,7 +433,7 @@ void MaemoSettingsWidget::processSshOutput(const QString &data)
     m_deviceTestOutput.append(data);
 }
 
-void MaemoSettingsWidget::handleSshFinished()
+void MaemoSettingsWidget::handleTestThreadFinished()
 {
 #ifdef USE_SSH_LIB
     qDebug("================> %s", Q_FUNC_INFO);
@@ -490,12 +502,80 @@ QString MaemoSettingsWidget::parseTestOutput()
     return output;
 }
 
+void MaemoSettingsWidget::deployKey()
+{
+#ifdef USE_SSH_LIB
+    qDebug("Deploying key");
+    if (m_keyDeployer)
+        return;
+
+    const QString &dir = QFileInfo(currentConfig().keyFile).path();
+    const QString &keyFile
+        = QFileDialog::getOpenFileName(this, tr("Choose public key file"), dir);
+    if (keyFile.isEmpty())
+        return;
+
+    m_ui->deployKeyButton->disconnect();
+    SshDeploySpec deploySpec(keyFile,
+                             homeDirOnDevice(currentConfig().uname)
+                                 + QLatin1String("/.ssh/authorized_keys"),
+                             true);
+    m_keyDeployer = new MaemoSshDeployer(currentConfig(),
+                                         QList<SshDeploySpec>() << deploySpec);
+    connect(m_keyDeployer, SIGNAL(finished()),
+            this, SLOT(handleDeployThreadFinished()));
+    m_ui->deployKeyButton->setText(tr("Stop deploying"));
+    connect(m_ui->deployKeyButton, SIGNAL(clicked()),
+            this, SLOT(stopDeploying()));
+    m_keyDeployer->start();
+#endif
+}
+
+void MaemoSettingsWidget::handleDeployThreadFinished()
+{
+#ifdef USE_SSH_LIB
+    qDebug("================> %s", Q_FUNC_INFO);
+    if (!m_keyDeployer)
+        return;
+
+    QString output;
+    if (m_keyDeployer->hasError()) {
+        output = tr("Key deployment failed: ");
+        output.append(m_keyDeployer->error());
+    } else {
+        output = tr("Key was successfully deployed.");
+    }
+    m_ui->testResultEdit->setPlainText(output);
+    stopDeploying();
+#endif
+}
+
+void MaemoSettingsWidget::stopDeploying()
+{
+#ifdef USE_SSH_LIB
+    qDebug("================> %s", Q_FUNC_INFO);
+    if (m_keyDeployer) {
+        m_ui->deployKeyButton->disconnect();
+        const bool buttonWasEnabled = m_ui->deployKeyButton->isEnabled();
+        m_keyDeployer->disconnect();
+        m_keyDeployer->stop();
+        delete m_keyDeployer;
+        m_keyDeployer = 0;
+        m_ui->deployKeyButton->setText(tr("Deploy key ..."));
+        connect(m_ui->deployKeyButton, SIGNAL(clicked()),
+                this, SLOT(deployKey()));
+        m_ui->deployKeyButton->setEnabled(buttonWasEnabled);
+    }
+#endif
+}
+
 void MaemoSettingsWidget::selectionChanged()
 {
     const QList<QListWidgetItem *> &selectedItems =
         m_ui->configListWidget->selectedItems();
     Q_ASSERT(selectedItems.count() <= 1);
     stopConfigTest();
+    stopDeploying();
     m_ui->testResultEdit->setPlainText(m_defaultTestOutput);
     if (selectedItems.isEmpty()) {
         m_ui->removeConfigButton->setEnabled(false);
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemosettingswidget.ui b/src/plugins/qt4projectmanager/qt-maemo/maemosettingswidget.ui
index c7e95a5de3b..010dd4b6b49 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemosettingswidget.ui
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemosettingswidget.ui
@@ -187,8 +187,8 @@
          <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
 &lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
 p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;No current test results available.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Sans Serif';&quot;&gt;No current test results available.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
         </property>
        </widget>
       </item>
@@ -224,6 +224,16 @@ p, li { white-space: pre-wrap; }
        </property>
       </widget>
      </item>
+     <item>
+      <widget class="QPushButton" name="deployKeyButton">
+       <property name="enabled">
+        <bool>false</bool>
+       </property>
+       <property name="text">
+        <string>Deploy key ...</string>
+       </property>
+      </widget>
+     </item>
      <item>
       <spacer name="verticalSpacer">
        <property name="orientation">
@@ -278,8 +288,8 @@ p, li { white-space: pre-wrap; }
    <slot>deviceTypeChanged()</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>269</x>
-     <y>170</y>
+     <x>264</x>
+     <y>175</y>
     </hint>
     <hint type="destinationlabel">
      <x>511</x>
@@ -294,8 +304,8 @@ p, li { white-space: pre-wrap; }
    <slot>hostNameEditingFinished()</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>397</x>
-     <y>219</y>
+     <x>385</x>
+     <y>228</y>
     </hint>
     <hint type="destinationlabel">
      <x>424</x>
@@ -310,8 +320,8 @@ p, li { white-space: pre-wrap; }
    <slot>portEditingFinished()</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>397</x>
-     <y>243</y>
+     <x>385</x>
+     <y>255</y>
     </hint>
     <hint type="destinationlabel">
      <x>514</x>
@@ -326,8 +336,8 @@ p, li { white-space: pre-wrap; }
    <slot>timeoutEditingFinished()</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>397</x>
-     <y>268</y>
+     <x>385</x>
+     <y>282</y>
     </hint>
     <hint type="destinationlabel">
      <x>425</x>
@@ -342,8 +352,8 @@ p, li { white-space: pre-wrap; }
    <slot>userNameEditingFinished()</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>397</x>
-     <y>293</y>
+     <x>385</x>
+     <y>309</y>
     </hint>
     <hint type="destinationlabel">
      <x>422</x>
@@ -358,8 +368,8 @@ p, li { white-space: pre-wrap; }
    <slot>passwordEditingFinished()</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>394</x>
-     <y>317</y>
+     <x>385</x>
+     <y>336</y>
     </hint>
     <hint type="destinationlabel">
      <x>423</x>
@@ -374,8 +384,8 @@ p, li { white-space: pre-wrap; }
    <slot>deviceTypeChanged()</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>388</x>
-     <y>170</y>
+     <x>376</x>
+     <y>175</y>
     </hint>
     <hint type="destinationlabel">
      <x>426</x>
@@ -495,6 +505,22 @@ p, li { white-space: pre-wrap; }
     </hint>
    </hints>
   </connection>
+  <connection>
+   <sender>deployKeyButton</sender>
+   <signal>clicked()</signal>
+   <receiver>maemoSettingsWidget</receiver>
+   <slot>deployKey()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>438</x>
+     <y>119</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>510</x>
+     <y>458</y>
+    </hint>
+   </hints>
+  </connection>
  </connections>
  <slots>
   <slot>configNameEditingFinished()</slot>
@@ -510,5 +536,6 @@ p, li { white-space: pre-wrap; }
   <slot>authenticationTypeChanged()</slot>
   <slot>keyFileEditingFinished()</slot>
   <slot>testConfig()</slot>
+  <slot>deployKey()</slot>
  </slots>
 </ui>
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemosshconnection.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemosshconnection.cpp
index 3f8ef2a6452..9bf830ab89e 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemosshconnection.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemosshconnection.cpp
@@ -160,26 +160,30 @@ void MaemoSftpConnection::transferFiles(const QList<SshDeploySpec> &deploySpecs)
 {
     for (int i = 0; i < deploySpecs.count(); ++i) {
         const SshDeploySpec &deploySpec = deploySpecs.at(i);
-        const QString &curFile = deploySpec.srcFilePath();
-        QSharedPointer<FILE> filePtr(fopen(curFile.toLatin1().data(), "rb"),
+        const QString &curSrcFile = deploySpec.srcFilePath();
+        QSharedPointer<FILE> filePtr(fopen(curSrcFile.toLatin1().data(), "rb"),
                                      &std::fclose);
         if (filePtr.isNull())
-            throw MaemoSshException(tr("Could not open file '%1'").arg(curFile));
+            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())
-            sftp->mkdir(deploySpec.targetDir().toLatin1().data());
+        if (deploySpec.mkdir()) {
+            const QString &dir = QFileInfo(curTgtFile).path();
+            sftp->mkdir(dir.toLatin1().data());
+        }
+
+        qDebug("Deploying file %s to %s.", qPrintable(curSrcFile), qPrintable(curTgtFile));
 
-        const QString &targetFile = deploySpec.targetDir() % QLatin1String("/")
-                                    % QFileInfo(curFile).fileName();
-        if (!sftp->put(filePtr.data(), targetFile.toLatin1().data())) {
+        if (!sftp->put(filePtr.data(), curTgtFile.toLatin1().data())) {
             const QString &error = tr("Could not copy local file '%1' "
-                    "to remote file '%2': %3").arg(curFile, targetFile)
+                    "to remote file '%2': %3").arg(curSrcFile, curTgtFile)
                     .arg(lastError());
             throw MaemoSshException(error);
         }
-        emit fileCopied(curFile);
+        emit fileCopied(curSrcFile);
     }
 }
 
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemosshconnection.h b/src/plugins/qt4projectmanager/qt-maemo/maemosshconnection.h
index c438ba95131..83774ab3f76 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemosshconnection.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemosshconnection.h
@@ -109,19 +109,19 @@ private:
 class SshDeploySpec
 {
 public:
-    SshDeploySpec(const QString &srcFilePath, const QString &targetDir,
+    SshDeploySpec(const QString &srcFilePath, const QString &tgtFilePath,
                   bool mkdir = false)
-        : m_srcFilePath(srcFilePath), m_targetDir(targetDir), m_mkdir(mkdir)
+        : m_srcFilePath(srcFilePath), m_tgtFilePath(tgtFilePath), m_mkdir(mkdir)
     {
     }
 
     QString srcFilePath() const { return m_srcFilePath; }
-    QString targetDir() const { return m_targetDir; }
+    QString tgtFilePath() const { return m_tgtFilePath; }
     bool mkdir() const { return m_mkdir; }
 
 private:
     QString m_srcFilePath;
-    QString m_targetDir;
+    QString m_tgtFilePath;
     bool m_mkdir;
 };
 
-- 
GitLab