Mercurial > trustbridge
view ui/installwrapper.cpp @ 754:27043d74dc90
(Issue25) Align header contents in their own column.
We now also stretch column 3 so that the contents are aligned
with the descriptive labels without a space in between.
Sadly this causes the quit button to be resized to it's minimum
instead of sharing the space with the installation button as the
installation button is so large that it squeezes the push button.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 07 Jul 2014 12:38:33 +0200 |
parents | 51830f4912c2 |
children | 216a65d7fc4b |
line wrap: on
line source
/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik * Software engineering by Intevation GmbH * * This file is Free Software under the GNU GPL (v>=2) * and comes with ABSOLUTELY NO WARRANTY! * See LICENSE.txt for details. */ #include "installwrapper.h" #include <QFileInfo> #include <QProcess> #include <QTemporaryFile> #include <QApplication> #include <QDir> #include <QDebug> #include "logging.h" #include "util.h" #define INSTALL_TIMEOUT 3600000 /* Wait up to an hour */ InstallWrapper::InstallWrapper(QObject* parent, const QString& path, const QStringList& choices): QThread(parent), mCertListFile(path), mChoices(choices) { } QFileInfo getCinstProcInfo() { QFileInfo fi(QCoreApplication::applicationFilePath()); QDir myDir = fi.absoluteDir(); QString instProcName = "cinst"; if (!fi.suffix().isEmpty()) { instProcName += "." + fi.suffix(); } return QFileInfo(myDir.absoluteFilePath(instProcName)); } bool InstallWrapper::writeChoices(QTemporaryFile* choicesFile) const { if (!choicesFile->open()) { return false; } foreach (const QString &b64data, mChoices) { if (choicesFile->write(b64data.toLatin1()) == -1) { return false; } if (choicesFile->write("\n") == -1) { 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 choicesFile; QFileInfo cinstProcInfo = getCinstProcInfo(); QString cinstFileName = QDir::toNativeSeparators( getCinstProcInfo().absoluteFilePath()); if (!cinstProcInfo.isExecutable()) { emit error(tr("Could not find certificate installation process.")); return; } if (!writeChoices(&choicesFile)) { emit error(tr("Failed to write temporary file.")); return; } #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)); /* Windows needs each parameter packed in " */ QString parameters = "\"list=" + mCertListFile + "\" \"choices=" + choicesFile.fileName() + "\""; shExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW); shExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; if (!is_admin()) { shExecInfo.lpVerb = L"open"; } else { shExecInfo.lpVerb = L"runas"; } shExecInfo.lpFile = reinterpret_cast<LPCWSTR> (cinstFileName.utf16()); shExecInfo.lpParameters = reinterpret_cast<LPCWSTR> (parameters.utf16()); qDebug() << "Starting process " << cinstFileName <<" params: " << parameters; if (!ShellExecuteExW(&shExecInfo)) { char* errmsg = getLastErrorMsg(); QString qerrmsg = QString::fromUtf8(errmsg); free(errmsg); emit error(tr("Error executing process: %1").arg(qerrmsg)); return; } retval = WaitForSingleObject(shExecInfo.hProcess, INSTALL_TIMEOUT); if (retval != WAIT_OBJECT_0) { if (retval == WAIT_FAILED) { char* errmsg = getLastErrorMsg(); QString qerrmsg = QString::fromUtf8(errmsg); free(errmsg); emit error (tr("Error monitoring process: %1").arg(qerrmsg)); return; } else { emit error (tr("Certificate installation timed out.")); return; } } if (GetExitCodeProcess(shExecInfo.hProcess, &retval)) { if (retval == STILL_ACTIVE) { qDebug() << "Process still running, huh.."; } } else { char* errmsg = getLastErrorMsg(); QString qerrmsg = QString::fromUtf8(errmsg); free(errmsg); emit error (tr("Failed to check process status: %1").arg(qerrmsg)); CloseHandle(shExecInfo.hProcess); return; } CloseHandle(shExecInfo.hProcess); if (retval != 0) { /* TODO make this nicer */ emit error (tr("The process failed with return code. %1").arg(retval)); return; } #else /* WIN32 */ QProcess installerProcess; QStringList parameters; choicesFile.setAutoRemove(false); parameters << "list=" + mCertListFile << "choices=" + choicesFile.fileName(); bool sudo_started = false; bool use_sudo = is_admin(); if (use_sudo) { QStringList sudoPrograms; sudoPrograms << "gksudo" << "kdesudo" << "sudo"; QStringList sudoParams; sudoParams << cinstProcInfo.absoluteFilePath() << parameters; installerProcess.setArguments(sudoParams); foreach (const QString &sProg, sudoPrograms) { installerProcess.setProgram(sProg); qDebug() << "Starting process " << sProg <<" params: " << sudoParams; installerProcess.start(); if (!installerProcess.waitForStarted() || installerProcess.state() == QProcess::NotRunning) { continue; } else { sudo_started = true; break; } } } /* Fallback to start without sudo */ if (!use_sudo || !sudo_started) { installerProcess.setProgram(cinstProcInfo.absoluteFilePath()); installerProcess.setArguments(parameters); qDebug() << "Starting process " << cinstFileName <<" params: " << parameters; installerProcess.start(); if (!installerProcess.waitForStarted() || installerProcess.state() == QProcess::NotRunning) { emit error (tr("Failed to start installer process.")); return; } } installerProcess.waitForFinished(); if (installerProcess.exitStatus() == QProcess::CrashExit) { /* Woops */ emit error (tr("Failed to complete installation.")); return; } else if (installerProcess.exitStatus() != QProcess::NormalExit) { /* Can not Happen. there are only those two values but maybe * qt changed.. */ emit error (tr("Failed to complete installation.")); 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 emit installationSuccessful(); }