changeset 364:dc4efb0a70cb

Add Linux support
author Andre Heinecke <aheinecke@intevation.de>
date Mon, 14 Apr 2014 16:58:20 +0000
parents d10d9bc2e84f
children 75f7288ad67b
files ui/installwrapper.cpp ui/installwrapper.h
diffstat 2 files changed, 92 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/ui/installwrapper.cpp	Mon Apr 14 16:57:41 2014 +0000
+++ b/ui/installwrapper.cpp	Mon Apr 14 16:58:20 2014 +0000
@@ -1,6 +1,7 @@
 #include "installwrapper.h"
 
 #include <QFileInfo>
+#include <QProcess>
 #include <QTemporaryFile>
 #include <QApplication>
 #include <QDir>
@@ -11,10 +12,10 @@
 #define INSTALL_TIMEOUT 3600000 /* Wait up to an hour */
 
 InstallWrapper::InstallWrapper(QObject* parent,
-        const QString& path, const QStringList& instructions):
+        const QString& path, const QStringList& choices):
     QThread(parent),
     mCertListFile(path),
-    mInstructions(instructions)
+    mChoices(choices)
 {
 }
 
@@ -28,16 +29,32 @@
     return QFileInfo(myDir.absoluteFilePath(instProcName));
 }
 
-#ifdef WIN32
+bool InstallWrapper::writeChoices(QTemporaryFile* choicesFile) const
+{
+    if (!choicesFile->open()) {
+        return false;
+    }
+
+    foreach (const QString &b64data, mChoices) {
+       if (!choicesFile->write(b64data.toLatin1())) {
+           return false;
+       }
+       if (!choicesFile->write("\n")) {
+           return false;
+       }
+    }
+
+    choicesFile->close();
+
+    return true;
+}
+
 void InstallWrapper::run()
 {
     /* TODO: We need errorcodes here so that we can see if a user
      * cancled the UAC elevation */
-    QTemporaryFile instructionsFile;
+    QTemporaryFile choicesFile;
     QFileInfo cinstProcInfo = getCinstProcInfo();
-    DWORD retval = 0;
-    SHELLEXECUTEINFOW shExecInfo;
-    memset (&shExecInfo, 0, sizeof(SHELLEXECUTEINFOW));
 
     QString cinstFileName = QDir::toNativeSeparators(
             getCinstProcInfo().absoluteFilePath());
@@ -47,17 +64,26 @@
         return;
     }
 
-    instructionsFile.open();
-
-    foreach (const QString &b64data, mInstructions) {
-       instructionsFile.write(b64data.toLatin1());
-       instructionsFile.write("\n");
+    if (!writeChoices(&choicesFile)) {
+        emit error(tr("Failed to write temporary file."));
+        return;
     }
 
-    instructionsFile.close();
+    QString parameters = "\"list=" + mCertListFile +
+        "\" \"choices=" + choicesFile.fileName() + "\"";
 
-    QString parameters = "\"list=" + mCertListFile + 
-        "\" \"instructions=" +instructionsFile.fileName() + "\"";
+#ifdef WIN32
+    /* QProcess on Windows uses CreateProcess but we have to
+     * use the runas shell command to get the UAC prompt if necessary.
+     * So we have to handle the process ourself. Starting with
+     * shell execute also means that we can not have stdout and stderr
+     * redirection. This is the reason we use command line parameters
+     * and not a pipe for communication. In debug mode the installer
+     * also makes use of output debug string. */
+    DWORD retval = 0;
+    SHELLEXECUTEINFOW shExecInfo;
+
+    memset (&shExecInfo, 0, sizeof(SHELLEXECUTEINFOW));
 
     shExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW);
     shExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
@@ -106,9 +132,35 @@
         /* TODO make this nicer */
         emit error (tr("The process failed with return code. %1").arg(retval));
     }
+    return;
+#else /* WIN32 */
+    QProcess installerProcess;
+    installerProcess.setProgram(cinstProcInfo.absoluteFilePath());
+    installerProcess.waitForStarted();
+    if (installerProcess.state() == QProcess::NotRunning) {
+        emit error (tr("Failed to start installer process."));
+        return;
+    }
+
+    installerProcess.waitForFinished();
+
+    if (installerProcess.exitStatus() == QProcess::CrashExit) {
+        /* Woops */
+        qWarning() << "Installer process crashed";
+    } else if (installerProcess.exitStatus() != QProcess::NormalExit) {
+        /* Can not Happen. there are only those two values but maybe
+         * qt changed.. */
+        qWarning() << "Exit status neither normal nor crash.";
+        return;
+    }
+
+    if (installerProcess.exitCode() == 0) {
+        qDebug() << "output: " << installerProcess.readAllStandardOutput();
+    } else {
+        /* TODO handle errors defined by errorcodes.h */
+        qDebug() << "Installer Process returned: " << installerProcess.exitCode();
+        qDebug() << "output: " << installerProcess.readAllStandardOutput();
+        return;
+    }
+#endif
 }
-#else
-void InstallWrapper::run()
-{
-}
-#endif
--- a/ui/installwrapper.h	Mon Apr 14 16:57:41 2014 +0000
+++ b/ui/installwrapper.h	Mon Apr 14 16:58:20 2014 +0000
@@ -1,14 +1,24 @@
 #ifndef UI_INSTALLWRAPPER_H
 #define UI_INSTALLWRAPPER_H
 
+#include <QFileInfo>
 #include <QString>
 #include <QStringList>
+#include <QTemporaryFile>
 #include <QThread>
 
 #include "certificate.h"
 /** @file installwrapper.h
  * @brief Wrapper around the call to the updated process */
 
+/** @brief Get the FileInfo for the installation process.
+ *
+ * This points to the file where the installation process is
+ * supposed to be.
+ *
+ * @returns A FileInfo with the path of the installation process.*/
+QFileInfo getCinstProcInfo();
+
  /** @brief wrapper around installer process
   *
   * This wrapper is mostly needed because QProcess executes
@@ -36,14 +46,22 @@
      *
      * @param[in] parent the parent object.
      * @param[in] listFileName the absolute path to the certificatelist.
-     * @param[in] instructions a list of instructions to execute.
+     * @param[in] choices a list of R: / I: <cert> lines to execute.
      */
     InstallWrapper(QObject* parent, const QString& path,
                    const QStringList& instructions);
 
 private:
+    /**@brief write the choices made into a temporary file 
+     *
+     * @param[in] choicesFile the temporary file to write.
+     *
+     * @returns true on success. false on error.
+     */
+    bool writeChoices(QTemporaryFile* choicesFile) const;
+
     const QString mCertListFile;
-    const QStringList mInstructions;
+    const QStringList mChoices;
 
 protected:
     void run();

http://wald.intevation.org/projects/trustbridge/