mirror of
https://github.com/QuasarApp/installer-framework.git
synced 2025-05-05 09:49:32 +00:00
Introduce new classes for client-server communication.
Still based on what we had already, though more separated. Change-Id: I4cce298003a4ffc2ebcec01fea1a07adfbfdf990 Reviewed-by: Tim Jenssen <tim.jenssen@digia.com> Reviewed-by: Niels Weber <niels.weber@digia.com>
This commit is contained in:
parent
00c6f94d1d
commit
7c07130119
@ -112,7 +112,16 @@ HEADERS += packagemanagercore.h \
|
||||
metadatajob.h \
|
||||
metadatajob_p.h \
|
||||
installer_global.h \
|
||||
scriptengine_p.h
|
||||
scriptengine_p.h \
|
||||
protocol.h \
|
||||
remoteobject.h \
|
||||
remoteclient.h \
|
||||
remoteserver.h \
|
||||
remoteclient_p.h \
|
||||
remoteserver_p.h \
|
||||
remotefileengine.h \
|
||||
remoteserverconnection.h \
|
||||
remoteserverconnection_p.h
|
||||
|
||||
SOURCES += packagemanagercore.cpp \
|
||||
packagemanagercore_p.cpp \
|
||||
@ -180,7 +189,12 @@ HEADERS += packagemanagercore.h \
|
||||
downloadfiletask.cpp \
|
||||
unziptask.cpp \
|
||||
observer.cpp \
|
||||
metadatajob.cpp
|
||||
metadatajob.cpp \
|
||||
remoteobject.cpp \
|
||||
remoteclient.cpp \
|
||||
remoteserver.cpp \
|
||||
remotefileengine.cpp \
|
||||
remoteserverconnection.cpp
|
||||
|
||||
RESOURCES += resources/patch_file_lists.qrc \
|
||||
resources/installer.qrc
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012-2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2012-2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the Qt Installer Framework.
|
||||
|
160
src/libs/installer/protocol.h
Normal file
160
src/libs/installer/protocol.h
Normal file
@ -0,0 +1,160 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the Qt Installer Framework.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef PROTOCOL_H
|
||||
#define PROTOCOL_H
|
||||
|
||||
namespace QInstaller {
|
||||
namespace Protocol {
|
||||
|
||||
const char Create[] = "Create";
|
||||
const char Destroy[] = "Destroy";
|
||||
const char Shutdown[] = "Shutdown";
|
||||
const char Authorize[] = "Authorize";
|
||||
const char DebugAuthorizationKey[] = "DebugAuthorizationKey";
|
||||
|
||||
// QProcessWrapper
|
||||
const char QProcess[] = "QProcess";
|
||||
const char QProcessCloseWriteChannel[] = "QProcess::closeWriteChannel";
|
||||
const char QProcessExitCode[] = "QProcess::exitCode";
|
||||
const char QProcessExitStatus[] = "QProcess::exitStatus";
|
||||
const char QProcessKill[] = "QProcess::kill";
|
||||
const char QProcessReadAll[] = "QProcess::readAll";
|
||||
const char QProcessReadAllStandardOutput[] = "QProcess::readAllStandardOutput";
|
||||
const char QProcessReadAllStandardError[] = "QProcess::readAllStandardError";
|
||||
const char QProcessStartDetached[] = "QProcess::startDetached";
|
||||
const char QProcessSetWorkingDirectory[] = "QProcess::setWorkingDirectory";
|
||||
const char QProcessSetEnvironment[] = "QProcess::setEnvironment";
|
||||
const char QProcessEnvironment[] = "QProcess::environment";
|
||||
const char QProcessStart3Arg[] = "QProcess::start3";
|
||||
const char QProcessStart2Arg[] = "QProcess::start2";
|
||||
const char QProcessState[] = "QProcess::state";
|
||||
const char QProcessTerminate[] = "QProcess::terminate";
|
||||
const char QProcessWaitForFinished[] = "QProcess::waitForFinished";
|
||||
const char QProcessWaitForStarted[] = "QProcess::waitForStarted";
|
||||
const char QProcessWorkingDirectory[] = "QProcess::workingDirectory";
|
||||
const char QProcessErrorString[] = "QProcess::errorString";
|
||||
const char QProcessReadChannel[] = "QProcess::readChannel";
|
||||
const char QProcessSetReadChannel[] = "QProcess::setReadChannel";
|
||||
const char QProcessWrite[] = "QProcess::write";
|
||||
const char QProcessProcessChannelMode[] = "QProcess::processChannelMode";
|
||||
const char QProcessSetProcessChannelMode[] = "QProcess::setProcessChannelMode";
|
||||
const char QProcessSetNativeArguments[] = "QProcess::setNativeArguments";
|
||||
|
||||
const char GetQProcessSignals[] = "GetQProcessSignals";
|
||||
const char QProcessSignalBytesWritten[] = "QProcess::bytesWritten";
|
||||
const char QProcessSignalAboutToClose[] = "QProcess::aboutToClose";
|
||||
const char QProcessSignalReadChannelFinished[] = "QProcess::readChannelFinished";
|
||||
const char QProcessSignalError[] = "QProcess::error";
|
||||
const char QProcessSignalReadyReadStandardOutput[] = "QProcess::readyReadStandardOutput";
|
||||
const char QProcessSignalReadyReadStandardError[] = "QProcess::readyReadStandardError";
|
||||
const char QProcessSignalStarted[] = "QProcess::started";
|
||||
const char QProcessSignalReadyRead[] = "QProcess::readyRead";
|
||||
const char QProcessSignalStateChanged[] = "QProcess::stateChanged";
|
||||
const char QProcessSignalFinished[] = "QProcess::finished";
|
||||
|
||||
|
||||
// QSettingsWrapper
|
||||
const char QSettings[] = "QSettings";
|
||||
const char QSettingsAllKeys[] = "QSettings::allKeys";
|
||||
const char QSettingsBeginGroup[] = "QSettings::beginGroup";
|
||||
const char QSettingsBeginWriteArray[] = "QSettings::beginWriteArray";
|
||||
const char QSettingsBeginReadArray[] = "QSettings::beginReadArray";
|
||||
const char QSettingsChildGroups[] = "QSettings::childGroups";
|
||||
const char QSettingsChildKeys[] = "QSettings::childKeys";
|
||||
const char QSettingsClear[] = "QSettings::clear";
|
||||
const char QSettingsContains[] = "QSettings::contains";
|
||||
const char QSettingsEndArray[] = "QSettings::endArray";
|
||||
const char QSettingsEndGroup[] = "QSettings::endGroup";
|
||||
const char QSettingsFallbacksEnabled[] = "QSettings::fallbacksEnabled";
|
||||
const char QSettingsFileName[] = "QSettings::fileName";
|
||||
const char QSettingsGroup[] = "QSettings::group";
|
||||
const char QSettingsIsWritable[] = "QSettings::isWritable";
|
||||
const char QSettingsRemove[] = "QSettings::remove";
|
||||
const char QSettingsSetArrayIndex[] = "QSettings::setArrayIndex";
|
||||
const char QSettingsSetFallbacksEnabled[] = "QSettings::setFallbacksEnabled";
|
||||
const char QSettingsStatus[] = "QSettings::status";
|
||||
const char QSettingsSync[] = "QSettings::sync";
|
||||
const char QSettingsSetValue[] = "QSettings::setValue";
|
||||
const char QSettingsValue[] = "QSettings::value";
|
||||
const char QSettingsOrganizationName[] = "QSettings::organizationName";
|
||||
const char QSettingsApplicationName[] = "QSettings::applicationName";
|
||||
|
||||
|
||||
// RemoteFileEngine
|
||||
const char QAbstractFileEngine[] = "QAbstractFileEngine";
|
||||
const char QAbstractFileEngineAtEnd[] = "QAbstractFileEngine::atEnd";
|
||||
const char QAbstractFileEngineCaseSensitive[] = "QAbstractFileEngine::caseSensitive";
|
||||
const char QAbstractFileEngineClose[] = "QAbstractFileEngine::close";
|
||||
const char QAbstractFileEngineCopy[] = "QAbstractFileEngine::copy";
|
||||
const char QAbstractFileEngineEntryList[] = "QAbstractFileEngine::entryList";
|
||||
const char QAbstractFileEngineError[] = "QAbstractFileEngine::error";
|
||||
const char QAbstractFileEngineErrorString[] = "QAbstractFileEngine::errorString";
|
||||
const char QAbstractFileEngineFileFlags[] = "QAbstractFileEngine::fileFlags";
|
||||
const char QAbstractFileEngineFileName[] = "QAbstractFileEngine::fileName";
|
||||
const char QAbstractFileEngineFlush[] = "QAbstractFileEngine::flush";
|
||||
const char QAbstractFileEngineHandle[] = "QAbstractFileEngine::handle";
|
||||
const char QAbstractFileEngineIsRelativePath[] = "QAbstractFileEngine::isRelativePath";
|
||||
const char QAbstractFileEngineIsSequential[] = "QAbstractFileEngine::isSequential";
|
||||
const char QAbstractFileEngineLink[] = "QAbstractFileEngine::link";
|
||||
const char QAbstractFileEngineMkdir[] = "QAbstractFileEngine::mkdir";
|
||||
const char QAbstractFileEngineOpen[] = "QAbstractFileEngine::open";
|
||||
const char QAbstractFileEngineOwner[] = "QAbstractFileEngine::owner";
|
||||
const char QAbstractFileEngineOwnerId[] = "QAbstractFileEngine::ownerId";
|
||||
const char QAbstractFileEnginePos[] = "QAbstractFileEngine::pos";
|
||||
const char QAbstractFileEngineRead[] = "QAbstractFileEngine::read";
|
||||
const char QAbstractFileEngineReadLine[] = "QAbstractFileEngine::readLine";
|
||||
const char QAbstractFileEngineRemove[] = "QAbstractFileEngine::remove";
|
||||
const char QAbstractFileEngineRename[] = "QAbstractFileEngine::rename";
|
||||
const char QAbstractFileEngineRmdir[] = "QAbstractFileEngine::rmdir";
|
||||
const char QAbstractFileEngineSeek[] = "QAbstractFileEngine::seek";
|
||||
const char QAbstractFileEngineSetFileName[] = "QAbstractFileEngine::setFileName";
|
||||
const char QAbstractFileEngineSetPermissions[] = "QAbstractFileEngine::setPermissions";
|
||||
const char QAbstractFileEngineSetSize[] = "QAbstractFileEngine::setSize";
|
||||
const char QAbstractFileEngineSize[] = "QAbstractFileEngine::size";
|
||||
const char QAbstractFileEngineSupportsExtension[] = "QAbstractFileEngine::supportsExtension";
|
||||
const char QAbstractFileEngineExtension[] = "QAbstractFileEngine::extension";
|
||||
const char QAbstractFileEngineWrite[] = "QAbstractFileEngine::write";
|
||||
|
||||
} // namespace Protocol
|
||||
} // namespace QInstaller
|
||||
|
||||
#endif // PROTOCOL_H
|
160
src/libs/installer/remoteclient.cpp
Normal file
160
src/libs/installer/remoteclient.cpp
Normal file
@ -0,0 +1,160 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the Qt Installer Framework.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "remoteclient.h"
|
||||
|
||||
#include "protocol.h"
|
||||
#include "remoteclient_p.h"
|
||||
|
||||
#include <QElapsedTimer>
|
||||
#include <QUuid>
|
||||
|
||||
namespace QInstaller {
|
||||
|
||||
RemoteClient::RemoteClient()
|
||||
: d_ptr(new RemoteClientPrivate(this))
|
||||
{
|
||||
Q_D(RemoteClient);
|
||||
d->m_key = QUuid::createUuid().toString();
|
||||
}
|
||||
|
||||
RemoteClient::~RemoteClient()
|
||||
{
|
||||
Q_D(RemoteClient);
|
||||
d->m_quit = true;
|
||||
}
|
||||
|
||||
RemoteClient &RemoteClient::instance()
|
||||
{
|
||||
static RemoteClient instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
QString RemoteClient::authorizationKey() const
|
||||
{
|
||||
Q_D(const RemoteClient);
|
||||
return d->m_key;
|
||||
}
|
||||
|
||||
void RemoteClient::setAuthorizationKey(const QString &key)
|
||||
{
|
||||
Q_D(RemoteClient);
|
||||
if (d->m_serverStarted)
|
||||
return;
|
||||
d->m_key = key;
|
||||
}
|
||||
|
||||
void RemoteClient::init(quint16 port, const QHostAddress &address, Mode mode)
|
||||
{
|
||||
Q_D(RemoteClient);
|
||||
d->init(port, address, mode);
|
||||
}
|
||||
|
||||
QTcpSocket *RemoteClient::connect() const
|
||||
{
|
||||
Q_D(const RemoteClient);
|
||||
if (d->m_quit)
|
||||
return 0;
|
||||
|
||||
int tries = 3;
|
||||
QScopedPointer<QTcpSocket> socket(new QTcpSocket);
|
||||
while ((tries > 0) && (!d->m_quit)) {
|
||||
socket->connectToHost(d->m_address, d->m_port);
|
||||
|
||||
QElapsedTimer stopWatch;
|
||||
stopWatch.start();
|
||||
while ((socket->state() == QAbstractSocket::ConnectingState)
|
||||
&& (stopWatch.elapsed() < 10000) && (!d->m_quit)) {
|
||||
--tries;
|
||||
qApp->processEvents();
|
||||
continue;
|
||||
}
|
||||
if ((socket->state() != QAbstractSocket::ConnectedState) || d->m_quit)
|
||||
return 0;
|
||||
|
||||
QDataStream stream;
|
||||
stream.setDevice(socket.data());
|
||||
stream << QString::fromLatin1(Protocol::Authorize) << d->m_key;
|
||||
|
||||
socket->waitForBytesWritten(-1);
|
||||
if (!socket->bytesAvailable())
|
||||
socket->waitForReadyRead(-1);
|
||||
|
||||
quint32 size; stream >> size;
|
||||
bool authorized; stream >> authorized;
|
||||
if (authorized && (!d->m_quit))
|
||||
return socket.take();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool RemoteClient::isActive() const
|
||||
{
|
||||
Q_D(const RemoteClient);
|
||||
return d->m_active;
|
||||
}
|
||||
|
||||
void RemoteClient::setActive(bool active)
|
||||
{
|
||||
Q_D(RemoteClient);
|
||||
d->m_active = active;
|
||||
if (d->m_active) {
|
||||
d->maybeStartServer();
|
||||
d->m_active = d->m_serverStarted;
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteClient::setStartServerCommand(const QString &command, StartAs startAs)
|
||||
{
|
||||
setStartServerCommand(command, QStringList(), startAs);
|
||||
}
|
||||
|
||||
void RemoteClient::setStartServerCommand(const QString &command, const QStringList &arguments,
|
||||
StartAs startAs)
|
||||
{
|
||||
Q_D(RemoteClient);
|
||||
d->maybeStopServer();
|
||||
d->m_serverCommand = command;
|
||||
d->m_serverArguments = arguments;
|
||||
d->m_startServerAsAdmin = startAs;
|
||||
}
|
||||
|
||||
} // namespace QInstaller
|
98
src/libs/installer/remoteclient.h
Normal file
98
src/libs/installer/remoteclient.h
Normal file
@ -0,0 +1,98 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the Qt Installer Framework.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef REMOTECLIENT_H
|
||||
#define REMOTECLIENT_H
|
||||
|
||||
#include "installer_global.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QHostAddress;
|
||||
class QTcpSocket;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace QInstaller {
|
||||
|
||||
class RemoteClientPrivate;
|
||||
|
||||
class INSTALLER_EXPORT RemoteClient : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(RemoteClient)
|
||||
Q_DECLARE_PRIVATE(RemoteClient)
|
||||
|
||||
public:
|
||||
enum Mode {
|
||||
Debug,
|
||||
Release
|
||||
};
|
||||
|
||||
enum StartAs {
|
||||
User,
|
||||
Administrator
|
||||
};
|
||||
static RemoteClient &instance();
|
||||
|
||||
QTcpSocket *connect() const;
|
||||
void init(quint16 port, const QHostAddress &address, Mode mode);
|
||||
|
||||
QString authorizationKey() const;
|
||||
void setAuthorizationKey(const QString &key);
|
||||
|
||||
bool isActive() const;
|
||||
void setActive(bool active);
|
||||
|
||||
void setStartServerCommand(const QString &command, StartAs startAs);
|
||||
void setStartServerCommand(const QString &command, const QStringList &arguments, StartAs start);
|
||||
|
||||
private:
|
||||
RemoteClient();
|
||||
~RemoteClient();
|
||||
|
||||
private:
|
||||
QScopedPointer<RemoteClientPrivate> d_ptr;
|
||||
};
|
||||
|
||||
} // namespace QInstaller
|
||||
|
||||
#endif // REMOTECLIENT_H
|
240
src/libs/installer/remoteclient_p.h
Normal file
240
src/libs/installer/remoteclient_p.h
Normal file
@ -0,0 +1,240 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the Qt Installer Framework.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef REMOTECLIENT_P_H
|
||||
#define REMOTECLIENT_P_H
|
||||
|
||||
#include "adminauthorization.h"
|
||||
#include "messageboxhandler.h"
|
||||
#include "protocol.h"
|
||||
#include "remoteclient.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QElapsedTimer>
|
||||
#include <QHostAddress>
|
||||
#include <QMutex>
|
||||
#include <QPointer>
|
||||
#include <QTcpSocket>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
|
||||
namespace QInstaller {
|
||||
|
||||
class KeepAliveObject : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(KeepAliveObject)
|
||||
|
||||
public:
|
||||
KeepAliveObject(RemoteClient *client)
|
||||
: m_timer(0)
|
||||
, m_client(client)
|
||||
{
|
||||
}
|
||||
|
||||
public slots:
|
||||
void run()
|
||||
{
|
||||
m_timer = new QTimer(this);
|
||||
connect(m_timer, SIGNAL(timeout()), this, SLOT(onTimeout()));
|
||||
m_timer->start(1000);
|
||||
}
|
||||
|
||||
private slots:
|
||||
void onTimeout()
|
||||
{
|
||||
m_timer->stop();
|
||||
|
||||
if (!m_client)
|
||||
return;
|
||||
|
||||
{
|
||||
// Try to connect to the server. If we succeed the server side running watchdog gets
|
||||
// restarted and the server keeps running for another 30 seconds.
|
||||
QScopedPointer<QTcpSocket> socket(m_client->connect());
|
||||
}
|
||||
|
||||
m_timer->start(1000);
|
||||
}
|
||||
|
||||
private:
|
||||
QTimer *m_timer;
|
||||
QPointer<RemoteClient> m_client;
|
||||
};
|
||||
|
||||
class RemoteClientPrivate
|
||||
{
|
||||
Q_DECLARE_PUBLIC(RemoteClient)
|
||||
Q_DISABLE_COPY(RemoteClientPrivate)
|
||||
|
||||
public:
|
||||
RemoteClientPrivate(RemoteClient *parent)
|
||||
: q_ptr(parent)
|
||||
, m_mutex(QMutex::Recursive)
|
||||
, m_port(0)
|
||||
, m_startServerAsAdmin(false)
|
||||
, m_serverStarted(false)
|
||||
, m_serverStarting(false)
|
||||
, m_active(false)
|
||||
, m_quit(false)
|
||||
{
|
||||
}
|
||||
|
||||
~RemoteClientPrivate()
|
||||
{
|
||||
m_thread.quit();
|
||||
m_thread.wait();
|
||||
}
|
||||
|
||||
void init(quint16 port, const QHostAddress &address, RemoteClient::Mode mode)
|
||||
{
|
||||
m_port = port;
|
||||
m_mode = mode;
|
||||
m_address = address;
|
||||
|
||||
if (m_mode == RemoteClient::Release) {
|
||||
QObject *const object = new KeepAliveObject(q_ptr);
|
||||
object->moveToThread(&m_thread);
|
||||
QObject::connect(&m_thread, SIGNAL(finished()), object, SLOT(deleteLater()));
|
||||
m_thread.start();
|
||||
QTimer::singleShot(0, object, SLOT(run()));
|
||||
} else if (mode == RemoteClient::Debug) {
|
||||
m_active = true;
|
||||
m_serverStarted = true;
|
||||
m_key = QLatin1String(Protocol::DebugAuthorizationKey);
|
||||
} else {
|
||||
Q_ASSERT_X(false, Q_FUNC_INFO, "RemoteClient mode not set properly.");
|
||||
}
|
||||
}
|
||||
|
||||
void maybeStartServer() {
|
||||
if (m_serverStarted || m_serverCommand.isEmpty())
|
||||
return;
|
||||
|
||||
const QMutexLocker ml(&m_mutex);
|
||||
if (m_serverStarted)
|
||||
return;
|
||||
|
||||
m_serverStarting = true;
|
||||
|
||||
if (m_startServerAsAdmin) {
|
||||
AdminAuthorization auth;
|
||||
m_serverStarted = auth.authorize() && auth.execute(0, m_serverCommand, m_serverArguments);
|
||||
|
||||
if (!m_serverStarted) {
|
||||
// something went wrong with authorizing, either user pressed cancel or entered
|
||||
// wrong password
|
||||
const QString fallback = m_serverCommand + QLatin1String(" ") + m_serverArguments
|
||||
.join(QLatin1String(" "));
|
||||
|
||||
const QMessageBox::Button res =
|
||||
MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(),
|
||||
QObject::tr("Authorization Error"), QObject::tr("Could not get authorization."),
|
||||
QObject::tr("Could not get authorization that is needed for continuing the "
|
||||
"installation.\n Either abort the installation or use the fallback "
|
||||
"solution by running\n%1\nas root and then clicking ok.").arg(fallback),
|
||||
QMessageBox::Abort | QMessageBox::Ok, QMessageBox::Ok);
|
||||
|
||||
if (res == QMessageBox::Ok)
|
||||
m_serverStarted = true;
|
||||
}
|
||||
} else {
|
||||
m_serverStarted = QInstaller::startDetached(m_serverCommand, m_serverArguments,
|
||||
QCoreApplication::applicationDirPath());
|
||||
}
|
||||
|
||||
if (m_serverStarted) {
|
||||
QElapsedTimer t;
|
||||
t.start();
|
||||
// 30 seconds ought to be enough for the app to start
|
||||
while (m_serverStarting && m_serverStarted && t.elapsed() < 30000) {
|
||||
Q_Q(RemoteClient);
|
||||
QScopedPointer<QTcpSocket> socket(q->connect());
|
||||
if (socket)
|
||||
m_serverStarting = false;
|
||||
}
|
||||
}
|
||||
m_serverStarting = false;
|
||||
}
|
||||
|
||||
void maybeStopServer()
|
||||
{
|
||||
if (!m_serverStarted)
|
||||
return;
|
||||
|
||||
const QMutexLocker ml(&m_mutex);
|
||||
if (!m_serverStarted)
|
||||
return;
|
||||
|
||||
Q_Q(RemoteClient);
|
||||
QScopedPointer<QTcpSocket> socket(q->connect());
|
||||
if (socket) {
|
||||
QDataStream stream(socket.data());
|
||||
stream << QString::fromLatin1(Protocol::Authorize);
|
||||
stream << m_key;
|
||||
stream << QString::fromLatin1(Protocol::Shutdown);
|
||||
socket->flush();
|
||||
}
|
||||
m_serverStarted = false;
|
||||
}
|
||||
|
||||
private:
|
||||
RemoteClient *q_ptr;
|
||||
QMutex m_mutex;
|
||||
QHostAddress m_address;
|
||||
quint16 m_port;
|
||||
QString m_socket;
|
||||
bool m_startServerAsAdmin;
|
||||
bool m_serverStarted;
|
||||
bool m_serverStarting;
|
||||
bool m_active;
|
||||
QString m_serverCommand;
|
||||
QStringList m_serverArguments;
|
||||
QString m_key;
|
||||
QThread m_thread;
|
||||
RemoteClient::Mode m_mode;
|
||||
volatile bool m_quit;
|
||||
};
|
||||
|
||||
} // namespace QInstaller
|
||||
|
||||
#endif // REMOTECLIENT_P_H
|
519
src/libs/installer/remotefileengine.cpp
Normal file
519
src/libs/installer/remotefileengine.cpp
Normal file
@ -0,0 +1,519 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the Qt Installer Framework.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "remotefileengine.h"
|
||||
|
||||
#include "protocol.h"
|
||||
#include "remoteclient.h"
|
||||
|
||||
#include <QTcpSocket>
|
||||
|
||||
namespace QInstaller {
|
||||
|
||||
|
||||
// -- RemoteFileEngineHandler
|
||||
|
||||
QAbstractFileEngine* RemoteFileEngineHandler::create(const QString &fileName) const
|
||||
{
|
||||
if (!RemoteClient::instance().isActive())
|
||||
return 0;
|
||||
|
||||
static QRegExp re(QLatin1String("^[a-z0-9]*://.*$"));
|
||||
if (re.exactMatch(fileName)) // stuff like installer://
|
||||
return 0;
|
||||
|
||||
if (fileName.isEmpty() || fileName.startsWith(QLatin1String(":")))
|
||||
return 0; // empty filename or Qt resource
|
||||
|
||||
QScopedPointer<RemoteFileEngine> client(new RemoteFileEngine());
|
||||
client->setFileName(fileName);
|
||||
if (client->isConnectedToServer())
|
||||
return client.take();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// -- RemoteFileEngineIterator
|
||||
|
||||
class RemoteFileEngineIterator : public QAbstractFileEngineIterator
|
||||
{
|
||||
public:
|
||||
RemoteFileEngineIterator(QDir::Filters filters, const QStringList &nameFilters,
|
||||
const QStringList &files)
|
||||
: QAbstractFileEngineIterator(filters, nameFilters)
|
||||
, entries(files)
|
||||
, index(-1)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool hasNext() const
|
||||
{
|
||||
return index < entries.size() - 1;
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
QString next()
|
||||
{
|
||||
if (!hasNext())
|
||||
return QString();
|
||||
++index;
|
||||
return currentFilePath();
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
QString currentFileName() const
|
||||
{
|
||||
return entries.at(index);
|
||||
}
|
||||
|
||||
private:
|
||||
const QStringList entries;
|
||||
int index;
|
||||
};
|
||||
|
||||
|
||||
// -- RemoteFileEngine
|
||||
|
||||
RemoteFileEngine::RemoteFileEngine()
|
||||
: RemoteObject(QLatin1String(Protocol::QAbstractFileEngine))
|
||||
{
|
||||
}
|
||||
|
||||
RemoteFileEngine::~RemoteFileEngine()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool RemoteFileEngine::atEnd() const
|
||||
{
|
||||
if ((const_cast<RemoteFileEngine *>(this))->connectToServer())
|
||||
return callRemoteMethod<bool>(QString::fromLatin1(Protocol::QAbstractFileEngineAtEnd));
|
||||
return m_fileEngine.atEnd();
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
QAbstractFileEngine::Iterator* RemoteFileEngine::beginEntryList(QDir::Filters filters,
|
||||
const QStringList &filterNames)
|
||||
{
|
||||
QStringList entries = entryList(filters, filterNames);
|
||||
entries.removeAll(QString());
|
||||
return new RemoteFileEngineIterator(filters, filterNames, entries);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool RemoteFileEngine::caseSensitive() const
|
||||
{
|
||||
if ((const_cast<RemoteFileEngine *>(this))->connectToServer())
|
||||
return callRemoteMethod<bool>(QString::fromLatin1(Protocol::QAbstractFileEngineCaseSensitive));
|
||||
return m_fileEngine.caseSensitive();
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool RemoteFileEngine::close()
|
||||
{
|
||||
if (connectToServer())
|
||||
return callRemoteMethod<bool>(QString::fromLatin1(Protocol::QAbstractFileEngineClose));
|
||||
return m_fileEngine.close();
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool RemoteFileEngine::copy(const QString &newName)
|
||||
{
|
||||
if (connectToServer())
|
||||
return callRemoteMethod<bool>(QString::fromLatin1(Protocol::QAbstractFileEngineCopy), newName);
|
||||
return m_fileEngine.copy(newName);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
QStringList RemoteFileEngine::entryList(QDir::Filters filters, const QStringList &filterNames) const
|
||||
{
|
||||
if ((const_cast<RemoteFileEngine *>(this))->connectToServer()) {
|
||||
return callRemoteMethod<QStringList>
|
||||
(QString::fromLatin1(Protocol::QAbstractFileEngineEntryList), static_cast<int>(filters),
|
||||
filterNames);
|
||||
}
|
||||
return m_fileEngine.entryList(filters, filterNames);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
QFile::FileError RemoteFileEngine::error() const
|
||||
{
|
||||
if ((const_cast<RemoteFileEngine *>(this))->connectToServer()) {
|
||||
return static_cast<QFile::FileError>
|
||||
(callRemoteMethod<int>(QString::fromLatin1(Protocol::QAbstractFileEngineError)));
|
||||
}
|
||||
return m_fileEngine.error();
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
QString RemoteFileEngine::errorString() const
|
||||
{
|
||||
if ((const_cast<RemoteFileEngine *>(this))->connectToServer())
|
||||
return callRemoteMethod<QString>(QString::fromLatin1(Protocol::QAbstractFileEngineErrorString));
|
||||
return m_fileEngine.errorString();
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool RemoteFileEngine::extension(Extension extension, const ExtensionOption *eo, ExtensionReturn *er)
|
||||
{
|
||||
return false;
|
||||
if (extension == UnMapExtension || extension == MapExtension)
|
||||
return false;
|
||||
|
||||
if (connectToServer()) {
|
||||
return callRemoteMethod<bool>(QString::fromLatin1(Protocol::QAbstractFileEngineExtension),
|
||||
static_cast<qint32> (extension));
|
||||
}
|
||||
return m_fileEngine.extension(extension, eo, er);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
QAbstractFileEngine::FileFlags RemoteFileEngine::fileFlags(FileFlags type) const
|
||||
{
|
||||
if ((const_cast<RemoteFileEngine *>(this))->connectToServer()) {
|
||||
return static_cast<QAbstractFileEngine::FileFlags>
|
||||
(callRemoteMethod<int>(QString::fromLatin1(Protocol::QAbstractFileEngineFileFlags),
|
||||
static_cast<int>(type)));
|
||||
}
|
||||
return m_fileEngine.fileFlags(type);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
QString RemoteFileEngine::fileName(FileName file) const
|
||||
{
|
||||
if ((const_cast<RemoteFileEngine *>(this))->connectToServer()) {
|
||||
return callRemoteMethod<QString>(QString::fromLatin1(Protocol::QAbstractFileEngineFileName),
|
||||
static_cast<int>(file));
|
||||
}
|
||||
return m_fileEngine.fileName(file);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool RemoteFileEngine::flush()
|
||||
{
|
||||
if (connectToServer())
|
||||
return callRemoteMethod<bool>(QString::fromLatin1(Protocol::QAbstractFileEngineFlush));
|
||||
return m_fileEngine.flush();
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
int RemoteFileEngine::handle() const
|
||||
{
|
||||
if ((const_cast<RemoteFileEngine *>(this))->connectToServer())
|
||||
return callRemoteMethod<int>(QString::fromLatin1(Protocol::QAbstractFileEngineHandle));
|
||||
return m_fileEngine.handle();
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool RemoteFileEngine::isRelativePath() const
|
||||
{
|
||||
if ((const_cast<RemoteFileEngine *>(this))->connectToServer())
|
||||
return callRemoteMethod<bool>(QString::fromLatin1(Protocol::QAbstractFileEngineIsRelativePath));
|
||||
return m_fileEngine.isRelativePath();
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool RemoteFileEngine::isSequential() const
|
||||
{
|
||||
if ((const_cast<RemoteFileEngine *>(this))->connectToServer())
|
||||
return callRemoteMethod<bool>(QString::fromLatin1(Protocol::QAbstractFileEngineIsSequential));
|
||||
return m_fileEngine.isSequential();
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool RemoteFileEngine::link(const QString &newName)
|
||||
{
|
||||
if (connectToServer()) {
|
||||
return callRemoteMethod<bool>(QString::fromLatin1(Protocol::QAbstractFileEngineLink),
|
||||
newName);
|
||||
}
|
||||
return m_fileEngine.link(newName);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool RemoteFileEngine::mkdir(const QString &dirName, bool createParentDirectories) const
|
||||
{
|
||||
if ((const_cast<RemoteFileEngine *>(this))->connectToServer()) {
|
||||
return callRemoteMethod<bool>(QString::fromLatin1(Protocol::QAbstractFileEngineMkdir),
|
||||
dirName, createParentDirectories);
|
||||
}
|
||||
return m_fileEngine.mkdir(dirName, createParentDirectories);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool RemoteFileEngine::open(QIODevice::OpenMode mode)
|
||||
{
|
||||
if (connectToServer()) {
|
||||
return callRemoteMethod<bool>(QString::fromLatin1(Protocol::QAbstractFileEngineOpen),
|
||||
static_cast<int>(mode));
|
||||
}
|
||||
return m_fileEngine.open(mode);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
QString RemoteFileEngine::owner(FileOwner owner) const
|
||||
{
|
||||
if ((const_cast<RemoteFileEngine *>(this))->connectToServer()) {
|
||||
return callRemoteMethod<QString>(QString::fromLatin1(Protocol::QAbstractFileEngineOwner),
|
||||
static_cast<int>(owner));
|
||||
}
|
||||
return m_fileEngine.owner(owner);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
uint RemoteFileEngine::ownerId(FileOwner owner) const
|
||||
{
|
||||
if ((const_cast<RemoteFileEngine *>(this))->connectToServer()) {
|
||||
return callRemoteMethod<uint>(QString::fromLatin1(Protocol::QAbstractFileEngineOwnerId),
|
||||
static_cast<int>(owner));
|
||||
}
|
||||
return m_fileEngine.ownerId(owner);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
qint64 RemoteFileEngine::pos() const
|
||||
{
|
||||
if ((const_cast<RemoteFileEngine *>(this))->connectToServer())
|
||||
return callRemoteMethod<qint64>(QString::fromLatin1(Protocol::QAbstractFileEnginePos));
|
||||
return m_fileEngine.pos();
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool RemoteFileEngine::remove()
|
||||
{
|
||||
if (connectToServer())
|
||||
return callRemoteMethod<bool>(QString::fromLatin1(Protocol::QAbstractFileEngineRemove));
|
||||
return m_fileEngine.remove();
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool RemoteFileEngine::rename(const QString &newName)
|
||||
{
|
||||
if (connectToServer()) {
|
||||
return callRemoteMethod<bool>(QString::fromLatin1(Protocol::QAbstractFileEngineRename),
|
||||
newName);
|
||||
}
|
||||
return m_fileEngine.rename(newName);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool RemoteFileEngine::rmdir(const QString &dirName, bool recurseParentDirectories) const
|
||||
{
|
||||
if ((const_cast<RemoteFileEngine *>(this))->connectToServer()) {
|
||||
return callRemoteMethod<bool>(QString::fromLatin1(Protocol::QAbstractFileEngineRmdir),
|
||||
dirName, recurseParentDirectories);
|
||||
}
|
||||
return m_fileEngine.rmdir(dirName, recurseParentDirectories);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool RemoteFileEngine::seek(qint64 offset)
|
||||
{
|
||||
if (connectToServer())
|
||||
return callRemoteMethod<bool>(QString::fromLatin1(Protocol::QAbstractFileEngineSeek), offset);
|
||||
return m_fileEngine.seek(offset);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
void RemoteFileEngine::setFileName(const QString &fileName)
|
||||
{
|
||||
if (connectToServer()) {
|
||||
callRemoteMethod(QString::fromLatin1(Protocol::QAbstractFileEngineSetFileName), fileName,
|
||||
dummy);
|
||||
}
|
||||
m_fileEngine.setFileName(fileName);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool RemoteFileEngine::setPermissions(uint perms)
|
||||
{
|
||||
if (connectToServer()) {
|
||||
return callRemoteMethod<bool>(QString::fromLatin1(Protocol::QAbstractFileEngineSetPermissions),
|
||||
perms);
|
||||
}
|
||||
return m_fileEngine.setPermissions(perms);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool RemoteFileEngine::setSize(qint64 size)
|
||||
{
|
||||
if (connectToServer()) {
|
||||
return callRemoteMethod<bool>(QString::fromLatin1(Protocol::QAbstractFileEngineSetSize),
|
||||
size);
|
||||
}
|
||||
return m_fileEngine.setSize(size);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
qint64 RemoteFileEngine::size() const
|
||||
{
|
||||
if ((const_cast<RemoteFileEngine *>(this))->connectToServer())
|
||||
return callRemoteMethod<qint64>(QString::fromLatin1(Protocol::QAbstractFileEngineSize));
|
||||
return m_fileEngine.size();
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool RemoteFileEngine::supportsExtension(Extension extension) const
|
||||
{
|
||||
return false;
|
||||
if (extension == UnMapExtension || extension == MapExtension)
|
||||
return false;
|
||||
return m_fileEngine.supportsExtension(extension);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
qint64 RemoteFileEngine::read(char *data, qint64 maxlen)
|
||||
{
|
||||
if (!connectToServer())
|
||||
return m_fileEngine.read(data, maxlen);
|
||||
|
||||
QPair<qint64, QByteArray> result = callRemoteMethod<QPair<qint64, QByteArray> >
|
||||
(QString::fromLatin1(Protocol::QAbstractFileEngineRead), maxlen);
|
||||
|
||||
if (result.first <= 0)
|
||||
return result.first;
|
||||
|
||||
QDataStream dataStream(result.second);
|
||||
dataStream.readRawData(data, result.first);
|
||||
return result.first;
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
qint64 RemoteFileEngine::readLine(char *data, qint64 maxlen)
|
||||
{
|
||||
if (!connectToServer())
|
||||
return m_fileEngine.readLine(data, maxlen);
|
||||
|
||||
QPair<qint64, QByteArray> result = callRemoteMethod<QPair<qint64, QByteArray> >
|
||||
(QString::fromLatin1(Protocol::QAbstractFileEngineReadLine), maxlen);
|
||||
|
||||
if (result.first <= 0)
|
||||
return result.first;
|
||||
|
||||
QDataStream dataStream(result.second);
|
||||
dataStream.readRawData(data, result.first);
|
||||
return result.first;
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
qint64 RemoteFileEngine::write(const char *data, qint64 len)
|
||||
{
|
||||
if (!connectToServer())
|
||||
return m_fileEngine.write(data, len);
|
||||
|
||||
QByteArray ba(data, len);
|
||||
return callRemoteMethod<qint64>(QString::fromLatin1(Protocol::QAbstractFileEngineWrite), ba);
|
||||
}
|
||||
|
||||
} // namespace QInstaller
|
109
src/libs/installer/remotefileengine.h
Normal file
109
src/libs/installer/remotefileengine.h
Normal file
@ -0,0 +1,109 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the Qt Installer Framework.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef REMOTEFILEENGINE_H
|
||||
#define REMOTEFILEENGINE_H
|
||||
|
||||
#include "remoteobject.h"
|
||||
|
||||
#include <QtCore/private/qabstractfileengine_p.h>
|
||||
#include <QtCore/private/qfsfileengine_p.h>
|
||||
|
||||
namespace QInstaller {
|
||||
|
||||
class INSTALLER_EXPORT RemoteFileEngineHandler : public QAbstractFileEngineHandler
|
||||
{
|
||||
Q_DISABLE_COPY(RemoteFileEngineHandler)
|
||||
|
||||
public:
|
||||
RemoteFileEngineHandler() : QAbstractFileEngineHandler() {}
|
||||
QAbstractFileEngine* create(const QString &fileName) const Q_DECL_OVERRIDE;
|
||||
};
|
||||
|
||||
class RemoteFileEngine : public RemoteObject, public QAbstractFileEngine
|
||||
{
|
||||
Q_DISABLE_COPY(RemoteFileEngine)
|
||||
|
||||
public:
|
||||
RemoteFileEngine();
|
||||
~RemoteFileEngine();
|
||||
|
||||
bool atEnd() const;
|
||||
Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames);
|
||||
bool caseSensitive() const;
|
||||
bool close();
|
||||
bool copy(const QString &newName);
|
||||
QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const;
|
||||
QFile::FileError error() const;
|
||||
QString errorString() const;
|
||||
bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0);
|
||||
FileFlags fileFlags(FileFlags type = FileInfoAll) const;
|
||||
QString fileName(FileName file = DefaultName) const;
|
||||
bool flush();
|
||||
int handle() const;
|
||||
bool isRelativePath() const;
|
||||
bool isSequential() const;
|
||||
bool link(const QString &newName);
|
||||
bool mkdir(const QString &dirName, bool createParentDirectories) const;
|
||||
bool open(QIODevice::OpenMode mode);
|
||||
QString owner(FileOwner owner) const;
|
||||
uint ownerId(FileOwner owner) const;
|
||||
qint64 pos() const;
|
||||
qint64 read(char *data, qint64 maxlen);
|
||||
qint64 readLine(char *data, qint64 maxlen);
|
||||
bool remove();
|
||||
bool rename(const QString &newName);
|
||||
bool rmdir(const QString &dirName, bool recurseParentDirectories) const;
|
||||
bool seek(qint64 offset);
|
||||
void setFileName(const QString &fileName);
|
||||
bool setPermissions(uint perms);
|
||||
bool setSize(qint64 size);
|
||||
qint64 size() const;
|
||||
bool supportsExtension(Extension extension) const;
|
||||
qint64 write(const char *data, qint64 len);
|
||||
|
||||
private:
|
||||
QFSFileEngine m_fileEngine;
|
||||
};
|
||||
|
||||
} // namespace QInstaller
|
||||
|
||||
#endif // REMOTEFILEENGINE_H
|
105
src/libs/installer/remoteobject.cpp
Normal file
105
src/libs/installer/remoteobject.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the Qt Installer Framework.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "remoteobject.h"
|
||||
|
||||
#include "protocol.h"
|
||||
#include "remoteclient.h"
|
||||
|
||||
namespace QInstaller {
|
||||
|
||||
RemoteObject::RemoteObject(const QString &wrappedType, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_socket(0)
|
||||
, dummy(0)
|
||||
, m_type(wrappedType)
|
||||
{
|
||||
Q_ASSERT_X(!m_type.isEmpty(), Q_FUNC_INFO, "The wrapped Qt type needs to be passed as "
|
||||
"argument and cannot be empty.");
|
||||
}
|
||||
|
||||
RemoteObject::~RemoteObject()
|
||||
{
|
||||
if (m_socket) {
|
||||
m_stream << QString::fromLatin1(Protocol::Destroy) << m_type;
|
||||
m_socket->waitForBytesWritten(-1);
|
||||
}
|
||||
}
|
||||
|
||||
bool RemoteObject::connectToServer(const QVariantList &arguments)
|
||||
{
|
||||
if (!RemoteClient::instance().isActive())
|
||||
return false;
|
||||
|
||||
if (m_socket && (m_socket->state() == QAbstractSocket::ConnectedState))
|
||||
return true;
|
||||
|
||||
if (m_socket)
|
||||
m_socket->deleteLater();
|
||||
|
||||
m_socket = RemoteClient::instance().connect();
|
||||
if (!m_socket)
|
||||
return false;
|
||||
|
||||
m_stream.setDevice(m_socket);
|
||||
m_stream << QString::fromLatin1(Protocol::Create) << m_type;
|
||||
foreach (const QVariant &arg, arguments)
|
||||
m_stream << arg;
|
||||
m_socket->waitForBytesWritten(-1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RemoteObject::isConnectedToServer() const
|
||||
{
|
||||
if ((!m_socket) || (!RemoteClient::instance().isActive()))
|
||||
return false;
|
||||
if (m_socket && (m_socket->state() == QAbstractSocket::ConnectedState))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void RemoteObject::callRemoteMethod(const QString &name)
|
||||
{
|
||||
writeData(name, dummy, dummy, dummy);
|
||||
}
|
||||
|
||||
} // namespace QInstaller
|
166
src/libs/installer/remoteobject.h
Normal file
166
src/libs/installer/remoteobject.h
Normal file
@ -0,0 +1,166 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the Qt Installer Framework.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef REMOTEOBJECT_H
|
||||
#define REMOTEOBJECT_H
|
||||
|
||||
#include "errors.h"
|
||||
#include "installer_global.h"
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QObject>
|
||||
#include <QTcpSocket>
|
||||
|
||||
namespace QInstaller {
|
||||
|
||||
class INSTALLER_EXPORT RemoteObject : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(RemoteObject)
|
||||
|
||||
public:
|
||||
RemoteObject(const QString &wrappedType, QObject *parent = 0);
|
||||
virtual ~RemoteObject() = 0;
|
||||
|
||||
bool isConnectedToServer() const;
|
||||
void callRemoteMethod(const QString &name);
|
||||
|
||||
template<typename T1, typename T2>
|
||||
void callRemoteMethod(const QString &name, const T1 &arg, const T2 &arg2)
|
||||
{
|
||||
writeData(name, arg, arg2, dummy);
|
||||
}
|
||||
|
||||
template<typename T1, typename T2, typename T3>
|
||||
void callRemoteMethod(const QString &name, const T1 &arg, const T2 &arg2, const T3 & arg3)
|
||||
{
|
||||
writeData(name, arg, arg2, arg3);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T callRemoteMethod(const QString &name) const
|
||||
{
|
||||
return callRemoteMethod<T>(name, dummy, dummy, dummy);
|
||||
}
|
||||
|
||||
template<typename T, typename T1>
|
||||
T callRemoteMethod(const QString &name, const T1 &arg) const
|
||||
{
|
||||
return callRemoteMethod<T>(name, arg, dummy, dummy);
|
||||
}
|
||||
|
||||
template<typename T, typename T1, typename T2>
|
||||
T callRemoteMethod(const QString &name, const T1 & arg, const T2 &arg2) const
|
||||
{
|
||||
return callRemoteMethod<T>(name, arg, arg2, dummy);
|
||||
}
|
||||
|
||||
template<typename T, typename T1, typename T2, typename T3>
|
||||
T callRemoteMethod(const QString &name, const T1 &arg, const T2 &arg2, const T3 &arg3) const
|
||||
{
|
||||
writeData(name, arg, arg2, arg3);
|
||||
if (!m_socket->bytesAvailable())
|
||||
m_socket->waitForReadyRead(-1);
|
||||
|
||||
quint32 size; m_stream >> size;
|
||||
while (m_socket->bytesAvailable() < size) {
|
||||
if (!m_socket->waitForReadyRead(30000)) {
|
||||
throw Error(tr("Could not read all data after sending command: %1. "
|
||||
"Bytes expected: %2, Bytes received: %3. Error: %3").arg(name).arg(size)
|
||||
.arg(m_socket->bytesAvailable()).arg(m_socket->errorString()));
|
||||
}
|
||||
}
|
||||
|
||||
T result;
|
||||
m_stream >> result;
|
||||
return result;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool connectToServer(const QVariantList &arguments = QVariantList());
|
||||
|
||||
// Use this structure to allow derived classes to manipulate the template
|
||||
// function signature of the callRemoteMethod templates, since most of the
|
||||
// generated functions will differ in return type rather given arguments.
|
||||
struct Dummy {}; Dummy *dummy;
|
||||
|
||||
private:
|
||||
template<typename T> bool isValueType(T) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T> bool isValueType(T *dummy) const
|
||||
{
|
||||
// Force compiler error while passing anything different then Dummy* to the function.
|
||||
// It really doesn't make sense to send any pointer over to the server, so bail early.
|
||||
static_cast<Dummy*> (dummy);
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2, typename T3>
|
||||
void writeData(const QString &name, const T1 &arg, const T2 &arg2, const T3 &arg3) const
|
||||
{
|
||||
QByteArray data;
|
||||
QDataStream out(&data, QIODevice::WriteOnly);
|
||||
|
||||
if (isValueType(arg))
|
||||
out << arg;
|
||||
if (isValueType(arg2))
|
||||
out << arg2;
|
||||
if (isValueType(arg3))
|
||||
out << arg3;
|
||||
|
||||
m_stream << name;
|
||||
m_stream << quint32(data.size());
|
||||
m_stream << data;
|
||||
m_socket->waitForBytesWritten(-1);
|
||||
}
|
||||
|
||||
private:
|
||||
QString m_type;
|
||||
QTcpSocket *m_socket;
|
||||
mutable QDataStream m_stream;
|
||||
};
|
||||
|
||||
} // namespace QInstaller
|
||||
|
||||
#endif // REMOTEOBJECT_H
|
122
src/libs/installer/remoteserver.cpp
Normal file
122
src/libs/installer/remoteserver.cpp
Normal file
@ -0,0 +1,122 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the Qt Installer Framework.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "remoteserver.h"
|
||||
|
||||
#include "protocol.h"
|
||||
#include "remoteserver_p.h"
|
||||
|
||||
namespace QInstaller {
|
||||
|
||||
RemoteServer::RemoteServer(QObject *parent)
|
||||
: QObject(parent)
|
||||
, d_ptr(new RemoteServerPrivate(this))
|
||||
{
|
||||
}
|
||||
|
||||
RemoteServer::~RemoteServer()
|
||||
{
|
||||
Q_D(RemoteServer);
|
||||
d->m_thread.quit();
|
||||
d->m_thread.wait();
|
||||
}
|
||||
|
||||
/*!
|
||||
Starts the server. If started in debug mode, the watchdog that kills the server after
|
||||
30 seconds without usage is not started. The authorization key is set to "DebugMode".
|
||||
*/
|
||||
void RemoteServer::start()
|
||||
{
|
||||
Q_D(RemoteServer);
|
||||
if (d->m_tcpServer)
|
||||
return;
|
||||
|
||||
d->m_tcpServer = new TcpServer(d->m_port, d->m_address, this);
|
||||
d->m_tcpServer->moveToThread(&d->m_thread);
|
||||
connect(&d->m_thread, SIGNAL(finished()), d->m_tcpServer, SLOT(deleteLater()));
|
||||
connect (d->m_tcpServer, SIGNAL(newIncommingConnection()), this, SLOT(restartWatchdog()));
|
||||
d->m_thread.start();
|
||||
|
||||
if (d->m_mode == RemoteServer::Release) {
|
||||
connect(d->m_watchdog.data(), SIGNAL(timeout()), this, SLOT(deleteLater()));
|
||||
d->m_watchdog->start();
|
||||
} else {
|
||||
setAuthorizationKey(QLatin1String(Protocol::DebugAuthorizationKey));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the authorization key.
|
||||
*/
|
||||
QString RemoteServer::authorizationKey() const
|
||||
{
|
||||
Q_D(const RemoteServer);
|
||||
return d->m_key;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the authorization key \a authorizationKey this server is asking the clients for.
|
||||
*/
|
||||
void RemoteServer::setAuthorizationKey(const QString &authorizationKey)
|
||||
{
|
||||
Q_D(RemoteServer);
|
||||
d->m_key = authorizationKey;
|
||||
}
|
||||
|
||||
void RemoteServer::init(quint16 port, const QHostAddress &address, Mode mode)
|
||||
{
|
||||
Q_D(RemoteServer);
|
||||
d->m_port = port;
|
||||
d->m_address = address;
|
||||
d->m_mode = mode;
|
||||
}
|
||||
|
||||
/*!
|
||||
Restarts the watchdog that tries to kill the server.
|
||||
*/
|
||||
void RemoteServer::restartWatchdog()
|
||||
{
|
||||
Q_D(RemoteServer);
|
||||
if (d->m_watchdog)
|
||||
d->m_watchdog->start();
|
||||
}
|
||||
|
||||
} // namespace QInstaller
|
87
src/libs/installer/remoteserver.h
Normal file
87
src/libs/installer/remoteserver.h
Normal file
@ -0,0 +1,87 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the Qt Installer Framework.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef REMOTESERVER_H
|
||||
#define REMOTESERVER_H
|
||||
|
||||
#include "installer_global.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QHostAddress;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace QInstaller {
|
||||
|
||||
class RemoteServerPrivate;
|
||||
|
||||
class INSTALLER_EXPORT RemoteServer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(RemoteServer)
|
||||
Q_DECLARE_PRIVATE(RemoteServer)
|
||||
|
||||
public:
|
||||
enum Mode {
|
||||
Debug,
|
||||
Release
|
||||
};
|
||||
|
||||
explicit RemoteServer(QObject *parent = 0);
|
||||
~RemoteServer();
|
||||
|
||||
void start();
|
||||
void init(quint16 port, const QHostAddress &address, Mode mode);
|
||||
|
||||
QString authorizationKey() const;
|
||||
void setAuthorizationKey(const QString &key);
|
||||
|
||||
private slots:
|
||||
void restartWatchdog();
|
||||
|
||||
private:
|
||||
QScopedPointer<RemoteServerPrivate> d_ptr;
|
||||
};
|
||||
|
||||
} // namespace QInstaller
|
||||
|
||||
#endif // REMOTESERVER_H
|
123
src/libs/installer/remoteserver_p.h
Normal file
123
src/libs/installer/remoteserver_p.h
Normal file
@ -0,0 +1,123 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the Qt Installer Framework.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef REMOTESERVER_P_H
|
||||
#define REMOTESERVER_P_H
|
||||
|
||||
#include "remoteserver.h"
|
||||
#include "remoteserverconnection.h"
|
||||
|
||||
#include <QPointer>
|
||||
#include <QTcpServer>
|
||||
#include <QTimer>
|
||||
|
||||
namespace QInstaller {
|
||||
|
||||
class TcpServer : public QTcpServer
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(TcpServer)
|
||||
|
||||
public:
|
||||
TcpServer(quint16 port, const QHostAddress &address, RemoteServer *server)
|
||||
: QTcpServer(0)
|
||||
, m_port(port)
|
||||
, m_address(address)
|
||||
, m_server(server)
|
||||
{
|
||||
listen(m_address, m_port);
|
||||
}
|
||||
|
||||
~TcpServer() {
|
||||
const QList<QThread *> threads = findChildren<QThread *>();
|
||||
foreach (QThread *thread, threads) {
|
||||
thread->quit();
|
||||
thread->wait();
|
||||
}
|
||||
}
|
||||
|
||||
signals:
|
||||
void newIncommingConnection();
|
||||
|
||||
private:
|
||||
void incomingConnection(qintptr socketDescriptor) Q_DECL_OVERRIDE {
|
||||
QThread *const thread = new RemoteServerConnection(socketDescriptor, m_server);
|
||||
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
|
||||
thread->start();
|
||||
emit newIncommingConnection();
|
||||
}
|
||||
|
||||
private:
|
||||
quint16 m_port;
|
||||
QHostAddress m_address;
|
||||
QPointer<RemoteServer> m_server;
|
||||
};
|
||||
|
||||
class RemoteServerPrivate
|
||||
{
|
||||
Q_DECLARE_PUBLIC(RemoteServer)
|
||||
Q_DISABLE_COPY(RemoteServerPrivate)
|
||||
|
||||
public:
|
||||
explicit RemoteServerPrivate(RemoteServer *server)
|
||||
: q_ptr(server)
|
||||
, m_tcpServer(0)
|
||||
, m_watchdog(new QTimer)
|
||||
{
|
||||
m_watchdog->setInterval(30000);
|
||||
m_watchdog->setSingleShot(true);
|
||||
}
|
||||
|
||||
private:
|
||||
RemoteServer *q_ptr;
|
||||
TcpServer *m_tcpServer;
|
||||
|
||||
QString m_key;
|
||||
quint16 m_port;
|
||||
QThread m_thread;
|
||||
QHostAddress m_address;
|
||||
RemoteServer::Mode m_mode;
|
||||
QScopedPointer<QTimer> m_watchdog;
|
||||
};
|
||||
|
||||
} // namespace QInstaller
|
||||
|
||||
#endif // REMOTESERVER_P_H
|
525
src/libs/installer/remoteserverconnection.cpp
Normal file
525
src/libs/installer/remoteserverconnection.cpp
Normal file
@ -0,0 +1,525 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the Qt Installer Framework.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "remoteserverconnection.h"
|
||||
|
||||
#include "errors.h"
|
||||
#include "protocol.h"
|
||||
#include "remoteserver.h"
|
||||
#include "remoteserverconnection_p.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <QSettings>
|
||||
#include <QTcpSocket>
|
||||
|
||||
namespace QInstaller {
|
||||
|
||||
RemoteServerConnection::RemoteServerConnection(qintptr socketDescriptor, RemoteServer *parent)
|
||||
: m_socketDescriptor(socketDescriptor)
|
||||
, m_process(0)
|
||||
, m_settings(0)
|
||||
, m_engine(0)
|
||||
, m_server(parent)
|
||||
, m_signalReceiver(0)
|
||||
{
|
||||
}
|
||||
|
||||
void RemoteServerConnection::run()
|
||||
{
|
||||
QTcpSocket socket;
|
||||
socket.setSocketDescriptor(m_socketDescriptor);
|
||||
|
||||
QDataStream stream;
|
||||
stream.setDevice(&socket);
|
||||
|
||||
bool authorized = false;
|
||||
while (socket.state() == QAbstractSocket::ConnectedState) {
|
||||
// Use a polling approach here to kill the thread as soon as the connections
|
||||
// closes. This seems to be related to the fact that the keep alive thread connects
|
||||
// every second and immediately throws away the socket and therefor the connection.
|
||||
if (!socket.bytesAvailable() && !socket.waitForReadyRead(250))
|
||||
continue;
|
||||
|
||||
QString command;
|
||||
stream >> command;
|
||||
|
||||
if (authorized && command == QLatin1String(Protocol::Shutdown)) {
|
||||
// this is a graceful shutdown
|
||||
socket.close();
|
||||
if (m_server)
|
||||
m_server->deleteLater();
|
||||
return;
|
||||
} else if (command == QLatin1String(Protocol::Authorize)) {
|
||||
QString key;
|
||||
stream >> key;
|
||||
sendData(stream, (authorized = (m_server && (key == m_server->authorizationKey()))));
|
||||
if (!authorized)
|
||||
socket.close();
|
||||
} else if (authorized) {
|
||||
if (command.isEmpty())
|
||||
continue;
|
||||
|
||||
if (command == QLatin1String(Protocol::Create)) {
|
||||
QString type;
|
||||
stream >> type;
|
||||
if (type == QLatin1String(Protocol::QSettings)) {
|
||||
QVariant application;
|
||||
QVariant organization;
|
||||
QVariant scope, format;
|
||||
QVariant fileName;
|
||||
stream >> application; stream >> organization; stream >> scope; stream >> format;
|
||||
stream >> fileName;
|
||||
|
||||
if (m_settings)
|
||||
m_settings->deleteLater();
|
||||
if (fileName.toString().isEmpty()) {
|
||||
m_settings = new QSettings(QSettings::Format(format.toInt()),
|
||||
QSettings::Scope(scope.toInt()), organization.toString(), application
|
||||
.toString());
|
||||
} else {
|
||||
m_settings = new QSettings(fileName.toString(), QSettings::NativeFormat);
|
||||
}
|
||||
} else if (type == QLatin1String(Protocol::QProcess)) {
|
||||
if (m_process)
|
||||
m_process->deleteLater();
|
||||
m_process = new QProcess;
|
||||
m_signalReceiver = new QProcessSignalReceiver(m_process);
|
||||
} else if (type == QLatin1String(Protocol::QAbstractFileEngine)) {
|
||||
if (m_engine)
|
||||
delete m_engine;
|
||||
m_engine = new QFSFileEngine;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (command == QLatin1String(Protocol::Destroy)) {
|
||||
QString type;
|
||||
stream >> type;
|
||||
if (type == QLatin1String(Protocol::QSettings)) {
|
||||
m_settings->deleteLater();
|
||||
m_settings = 0;
|
||||
} else if (command == QLatin1String(Protocol::QProcess)) {
|
||||
m_signalReceiver->m_receivedSignals.clear();
|
||||
m_process->deleteLater();
|
||||
m_process = 0;
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngine)) {
|
||||
delete m_engine;
|
||||
m_engine = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (command == QLatin1String(Protocol::GetQProcessSignals)) {
|
||||
if (m_signalReceiver) {
|
||||
QMutexLocker _(&m_signalReceiver->m_lock);
|
||||
sendData(stream, m_signalReceiver->m_receivedSignals);
|
||||
m_signalReceiver->m_receivedSignals.clear();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (command.startsWith(QLatin1String(Protocol::QProcess))) {
|
||||
handleQProcess(command, stream);
|
||||
} else if (command.startsWith(QLatin1String(Protocol::QSettings))) {
|
||||
handleQSettings(command, stream);
|
||||
} else if (command.startsWith(QLatin1String(Protocol::QAbstractFileEngine))) {
|
||||
handleQFSFileEngine(command, stream);
|
||||
} else {
|
||||
qDebug() << "Unknown command:" << command;
|
||||
}
|
||||
} else {
|
||||
// authorization failed, connection not wanted
|
||||
socket.close();
|
||||
qDebug() << "Unknown command:" << command;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void RemoteServerConnection::sendData(QDataStream &stream, const T &data)
|
||||
{
|
||||
QByteArray result;
|
||||
QDataStream returnStream(&result, QIODevice::WriteOnly);
|
||||
returnStream << data;
|
||||
|
||||
stream << static_cast<quint32> (result.size());
|
||||
if (!result.isEmpty())
|
||||
stream.writeRawData(result.data(), result.size());
|
||||
}
|
||||
|
||||
void RemoteServerConnection::handleQProcess(const QString &command, QDataStream &stream)
|
||||
{
|
||||
quint32 size;
|
||||
stream >> size;
|
||||
while (stream.device()->bytesAvailable() < size) {
|
||||
if (!stream.device()->waitForReadyRead(30000)) {
|
||||
throw Error(tr("Could not read all data after sending command: %1. "
|
||||
"Bytes expected: %2, Bytes received: %3. Error: %3").arg(command).arg(size)
|
||||
.arg(stream.device()->bytesAvailable()).arg(stream.device()->errorString()));
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray ba;
|
||||
stream >> ba;
|
||||
QDataStream data(ba);
|
||||
|
||||
if (command == QLatin1String(Protocol::QProcessCloseWriteChannel)) {
|
||||
m_process->closeWriteChannel();
|
||||
} else if (command == QLatin1String(Protocol::QProcessExitCode)) {
|
||||
sendData(stream, m_process->exitCode());
|
||||
} else if (command == QLatin1String(Protocol::QProcessExitStatus)) {
|
||||
sendData(stream, static_cast<int> (m_process->exitStatus()));
|
||||
} else if (command == QLatin1String(Protocol::QProcessKill)) {
|
||||
m_process->kill();
|
||||
} else if (command == QLatin1String(Protocol::QProcessReadAll)) {
|
||||
sendData(stream, m_process->readAll());
|
||||
} else if (command == QLatin1String(Protocol::QProcessReadAllStandardOutput)) {
|
||||
sendData(stream, m_process->readAllStandardOutput());
|
||||
} else if (command == QLatin1String(Protocol::QProcessReadAllStandardError)) {
|
||||
sendData(stream, m_process->readAllStandardError());
|
||||
} else if (command == QLatin1String(Protocol::QProcessStartDetached)) {
|
||||
QString program;
|
||||
QStringList arguments;
|
||||
QString workingDirectory;
|
||||
data >> program;
|
||||
data >> arguments;
|
||||
data >> workingDirectory;
|
||||
|
||||
qint64 pid = -1;
|
||||
bool success = QInstaller::startDetached(program, arguments, workingDirectory, &pid);
|
||||
sendData(stream, qMakePair< bool, qint64>(success, pid));
|
||||
} else if (command == QLatin1String(Protocol::QProcessSetWorkingDirectory)) {
|
||||
QString dir;
|
||||
data >> dir;
|
||||
m_process->setWorkingDirectory(dir);
|
||||
} else if (command == QLatin1String(Protocol::QProcessSetEnvironment)) {
|
||||
QStringList env;
|
||||
data >> env;
|
||||
m_process->setEnvironment(env);
|
||||
} else if (command == QLatin1String(Protocol::QProcessEnvironment)) {
|
||||
sendData(stream, m_process->environment());
|
||||
} else if (command == QLatin1String(Protocol::QProcessStart3Arg)) {
|
||||
QString program;
|
||||
QStringList arguments;
|
||||
int mode;
|
||||
data >> program;
|
||||
data >> arguments;
|
||||
data >> mode;
|
||||
m_process->start(program, arguments, static_cast<QIODevice::OpenMode> (mode));
|
||||
} else if (command == QLatin1String(Protocol::QProcessStart2Arg)) {
|
||||
QString program;
|
||||
int mode;
|
||||
data >> program;
|
||||
data >> mode;
|
||||
m_process->start(program, static_cast<QIODevice::OpenMode> (mode));
|
||||
} else if (command == QLatin1String(Protocol::QProcessState)) {
|
||||
sendData(stream, static_cast<int> (m_process->state()));
|
||||
} else if (command == QLatin1String(Protocol::QProcessTerminate)) {
|
||||
m_process->terminate();
|
||||
} else if (command == QLatin1String(Protocol::QProcessWaitForFinished)) {
|
||||
int msecs;
|
||||
data >> msecs;
|
||||
sendData(stream, m_process->waitForFinished(msecs));
|
||||
} else if (command == QLatin1String(Protocol::QProcessWaitForStarted)) {
|
||||
int msecs;
|
||||
data >> msecs;
|
||||
sendData(stream, m_process->waitForStarted(msecs));
|
||||
} else if (command == QLatin1String(Protocol::QProcessWorkingDirectory)) {
|
||||
sendData(stream, m_process->workingDirectory());
|
||||
} else if (command == QLatin1String(Protocol::QProcessErrorString)) {
|
||||
sendData(stream, m_process->errorString());
|
||||
} else if (command == QLatin1String(Protocol::QProcessReadChannel)) {
|
||||
sendData(stream, static_cast<int> (m_process->readChannel()));
|
||||
} else if (command == QLatin1String(Protocol::QProcessSetReadChannel)) {
|
||||
int processChannel;
|
||||
data >> processChannel;
|
||||
m_process->setReadChannel(static_cast<QProcess::ProcessChannel>(processChannel));
|
||||
} else if (command == QLatin1String(Protocol::QProcessWrite)) {
|
||||
QByteArray byteArray;
|
||||
data >> byteArray;
|
||||
sendData(stream, m_process->write(byteArray));
|
||||
} else if (command == QLatin1String(Protocol::QProcessProcessChannelMode)) {
|
||||
sendData(stream, static_cast<int> (m_process->processChannelMode()));
|
||||
} else if (command == QLatin1String(Protocol::QProcessSetProcessChannelMode)) {
|
||||
int processChannel;
|
||||
data >> processChannel;
|
||||
m_process->setProcessChannelMode(static_cast<QProcess::ProcessChannelMode>(processChannel));
|
||||
}
|
||||
#ifdef Q_OS_WIN
|
||||
else if (command == QLatin1String(Protocol::QProcessSetNativeArguments)) {
|
||||
QString arguments;
|
||||
data >> arguments;
|
||||
m_process->setNativeArguments(arguments);
|
||||
}
|
||||
#endif
|
||||
else if (!command.isEmpty()) {
|
||||
qDebug() << "Unknown QProcess command:" << command;
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteServerConnection::handleQSettings(const QString &command, QDataStream &stream)
|
||||
{
|
||||
quint32 size;
|
||||
stream >> size;
|
||||
while (stream.device()->bytesAvailable() < size) {
|
||||
if (!stream.device()->waitForReadyRead(30000)) {
|
||||
throw Error(tr("Could not read all data after sending command: %1. "
|
||||
"Bytes expected: %2, Bytes received: %3. Error: %3").arg(command).arg(size)
|
||||
.arg(stream.device()->bytesAvailable()).arg(stream.device()->errorString()));
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray ba;
|
||||
stream >> ba;
|
||||
QDataStream data(ba);
|
||||
|
||||
if (command == QLatin1String(Protocol::QSettingsAllKeys)) {
|
||||
sendData(stream, m_settings->allKeys());
|
||||
} else if (command == QLatin1String(Protocol::QSettingsBeginGroup)) {
|
||||
QString prefix;
|
||||
data >> prefix;
|
||||
m_settings->beginGroup(prefix);
|
||||
} else if (command == QLatin1String(Protocol::QSettingsBeginWriteArray)) {
|
||||
QString prefix;
|
||||
data >> prefix;
|
||||
int size;
|
||||
data >> size;
|
||||
m_settings->beginWriteArray(prefix, size);
|
||||
} else if (command == QLatin1String(Protocol::QSettingsBeginReadArray)) {
|
||||
QString prefix;
|
||||
data >> prefix;
|
||||
sendData(stream, m_settings->beginReadArray(prefix));
|
||||
} else if (command == QLatin1String(Protocol::QSettingsChildGroups)) {
|
||||
sendData(stream, m_settings->childGroups());
|
||||
} else if (command == QLatin1String(Protocol::QSettingsChildKeys)) {
|
||||
sendData(stream, m_settings->childKeys());
|
||||
} else if (command == QLatin1String(Protocol::QSettingsClear)) {
|
||||
m_settings->clear();
|
||||
} else if (command == QLatin1String(Protocol::QSettingsContains)) {
|
||||
QString key;
|
||||
data >> key;
|
||||
sendData(stream, m_settings->contains(key));
|
||||
} else if (command == QLatin1String(Protocol::QSettingsEndArray)) {
|
||||
m_settings->endArray();
|
||||
} else if (command == QLatin1String(Protocol::QSettingsEndGroup)) {
|
||||
m_settings->endGroup();
|
||||
} else if (command == QLatin1String(Protocol::QSettingsFallbacksEnabled)) {
|
||||
sendData(stream, m_settings->fallbacksEnabled());
|
||||
} else if (command == QLatin1String(Protocol::QSettingsFileName)) {
|
||||
sendData(stream, m_settings->fileName());
|
||||
} else if (command == QLatin1String(Protocol::QSettingsGroup)) {
|
||||
sendData(stream, m_settings->group());
|
||||
} else if (command == QLatin1String(Protocol::QSettingsIsWritable)) {
|
||||
sendData(stream, m_settings->isWritable());
|
||||
} else if (command == QLatin1String(Protocol::QSettingsRemove)) {
|
||||
QString key;
|
||||
data >> key;
|
||||
m_settings->remove(key);
|
||||
} else if (command == QLatin1String(Protocol::QSettingsSetArrayIndex)) {
|
||||
int i;
|
||||
data >> i;
|
||||
m_settings->setArrayIndex(i);
|
||||
} else if (command == QLatin1String(Protocol::QSettingsSetFallbacksEnabled)) {
|
||||
bool b;
|
||||
data >> b;
|
||||
m_settings->setFallbacksEnabled(b);
|
||||
} else if (command == QLatin1String(Protocol::QSettingsStatus)) {
|
||||
sendData(stream, m_settings->status());
|
||||
} else if (command == QLatin1String(Protocol::QSettingsSync)) {
|
||||
m_settings->sync();
|
||||
} else if (command == QLatin1String(Protocol::QSettingsSetValue)) {
|
||||
QString key;
|
||||
QVariant value;
|
||||
data >> key;
|
||||
data >> value;
|
||||
m_settings->setValue(key, value);
|
||||
} else if (command == QLatin1String(Protocol::QSettingsValue)) {
|
||||
QString key;
|
||||
QVariant defaultValue;
|
||||
data >> key;
|
||||
data >> defaultValue;
|
||||
sendData(stream, m_settings->value(key, defaultValue));
|
||||
} else if (command == QLatin1String(Protocol::QSettingsOrganizationName)) {
|
||||
sendData(stream, m_settings->organizationName());
|
||||
} else if (command == QLatin1String(Protocol::QSettingsApplicationName)) {
|
||||
sendData(stream, m_settings->applicationName());
|
||||
} else if (!command.isEmpty()) {
|
||||
qDebug() << "Unknown QSettings command:" << command;
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteServerConnection::handleQFSFileEngine(const QString &command, QDataStream &stream)
|
||||
{
|
||||
quint32 size;
|
||||
stream >> size;
|
||||
while (stream.device()->bytesAvailable() < size) {
|
||||
if (!stream.device()->waitForReadyRead(30000)) {
|
||||
throw Error(tr("Could not read all data after sending command: %1. "
|
||||
"Bytes expected: %2, Bytes received: %3. Error: %3").arg(command).arg(size)
|
||||
.arg(stream.device()->bytesAvailable()).arg(stream.device()->errorString()));
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray ba;
|
||||
stream >> ba;
|
||||
QDataStream data(ba);
|
||||
|
||||
if (command == QLatin1String(Protocol::QAbstractFileEngineAtEnd)) {
|
||||
sendData(stream, m_engine->atEnd());
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineCaseSensitive)) {
|
||||
sendData(stream, m_engine->caseSensitive());
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineClose)) {
|
||||
sendData(stream, m_engine->close());
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineCopy)) {
|
||||
QString newName;
|
||||
data >>newName;
|
||||
sendData(stream, m_engine->copy(newName));
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineEntryList)) {
|
||||
int filters;
|
||||
QStringList filterNames;
|
||||
data >>filters;
|
||||
data >>filterNames;
|
||||
sendData(stream, m_engine->entryList(static_cast<QDir::Filters> (filters), filterNames));
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineError)) {
|
||||
sendData(stream, static_cast<int> (m_engine->error()));
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineErrorString)) {
|
||||
sendData(stream, m_engine->errorString());
|
||||
}
|
||||
else if (command == QLatin1String(Protocol::QAbstractFileEngineFileFlags)) {
|
||||
int flags;
|
||||
data >>flags;
|
||||
sendData(stream,
|
||||
static_cast<int>(m_engine->fileFlags(static_cast<QAbstractFileEngine::FileFlags>(flags))));
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineFileName)) {
|
||||
int file;
|
||||
data >>file;
|
||||
sendData(stream, m_engine->fileName(static_cast<QAbstractFileEngine::FileName> (file)));
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineFlush)) {
|
||||
sendData(stream, m_engine->flush());
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineHandle)) {
|
||||
sendData(stream, m_engine->handle());
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineIsRelativePath)) {
|
||||
sendData(stream, m_engine->isRelativePath());
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineIsSequential)) {
|
||||
sendData(stream, m_engine->isSequential());
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineLink)) {
|
||||
QString newName;
|
||||
data >>newName;
|
||||
sendData(stream, m_engine->link(newName));
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineMkdir)) {
|
||||
QString dirName;
|
||||
bool createParentDirectories;
|
||||
data >>dirName;
|
||||
data >>createParentDirectories;
|
||||
sendData(stream, m_engine->mkdir(dirName, createParentDirectories));
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineOpen)) {
|
||||
int openMode;
|
||||
data >>openMode;
|
||||
sendData(stream, m_engine->open(static_cast<QIODevice::OpenMode> (openMode)));
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineOwner)) {
|
||||
int owner;
|
||||
data >>owner;
|
||||
sendData(stream, m_engine->owner(static_cast<QAbstractFileEngine::FileOwner> (owner)));
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineOwnerId)) {
|
||||
int owner;
|
||||
data >>owner;
|
||||
sendData(stream, m_engine->ownerId(static_cast<QAbstractFileEngine::FileOwner> (owner)));
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEnginePos)) {
|
||||
sendData(stream, m_engine->pos());
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineRead)) {
|
||||
qint64 maxlen;
|
||||
data >> maxlen;
|
||||
QByteArray byteArray(maxlen, '\0');
|
||||
const qint64 r = m_engine->read(byteArray.data(), maxlen);
|
||||
sendData(stream, qMakePair<qint64, QByteArray>(r, byteArray));
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineReadLine)) {
|
||||
qint64 maxlen;
|
||||
data >> maxlen;
|
||||
QByteArray byteArray(maxlen, '\0');
|
||||
const qint64 r = m_engine->readLine(byteArray.data(), maxlen);
|
||||
sendData(stream, qMakePair<qint64, QByteArray>(r, byteArray));
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineRemove)) {
|
||||
sendData(stream, m_engine->remove());
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineRename)) {
|
||||
QString newName;
|
||||
data >>newName;
|
||||
sendData(stream, m_engine->rename(newName));
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineRmdir)) {
|
||||
QString dirName;
|
||||
bool recurseParentDirectories;
|
||||
data >>dirName;
|
||||
data >>recurseParentDirectories;
|
||||
sendData(stream, m_engine->rmdir(dirName, recurseParentDirectories));
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineSeek)) {
|
||||
quint64 offset;
|
||||
data >>offset;
|
||||
sendData(stream, m_engine->seek(offset));
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineSetFileName)) {
|
||||
QString fileName;
|
||||
data >>fileName;
|
||||
m_engine->setFileName(fileName);
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineSetPermissions)) {
|
||||
uint perms;
|
||||
data >>perms;
|
||||
sendData(stream, m_engine->setPermissions(perms));
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineSetSize)) {
|
||||
qint64 size;
|
||||
data >>size;
|
||||
sendData(stream, m_engine->setSize(size));
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineSize)) {
|
||||
sendData(stream, m_engine->size());
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineSupportsExtension)) {
|
||||
// Implemented client side
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineExtension)) {
|
||||
qint32 extension;
|
||||
data >>extension;
|
||||
sendData(stream, m_engine->extension(static_cast<QAbstractFileEngine::Extension> (extension)));
|
||||
} else if (command == QLatin1String(Protocol::QAbstractFileEngineWrite)) {
|
||||
QByteArray content;
|
||||
data >> content;
|
||||
sendData(stream, m_engine->write(content.data(), content.size()));
|
||||
} else if (!command.isEmpty()) {
|
||||
qDebug() << "Unknown QAbstractFileEngine command:" << command;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace QInstaller
|
89
src/libs/installer/remoteserverconnection.h
Normal file
89
src/libs/installer/remoteserverconnection.h
Normal file
@ -0,0 +1,89 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the Qt Installer Framework.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef REMOTESERVERCONNECTION_H
|
||||
#define REMOTESERVERCONNECTION_H
|
||||
|
||||
#include <QPointer>
|
||||
#include <QThread>
|
||||
|
||||
#include <QtCore/private/qfsfileengine_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QProcess;
|
||||
class QSettings;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace QInstaller {
|
||||
|
||||
class QProcessSignalReceiver;
|
||||
class RemoteServer;
|
||||
|
||||
class RemoteServerConnection : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(RemoteServerConnection)
|
||||
|
||||
public:
|
||||
RemoteServerConnection(qintptr socketDescriptor, RemoteServer *parent);
|
||||
|
||||
void run() Q_DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
void sendData(QDataStream &stream, const T &arg);
|
||||
void handleQProcess(const QString &command, QDataStream &receivedStream);
|
||||
void handleQSettings(const QString &command, QDataStream &receivedStream);
|
||||
void handleQFSFileEngine(const QString &command, QDataStream &receivedStream);
|
||||
|
||||
private:
|
||||
qintptr m_socketDescriptor;
|
||||
|
||||
QProcess *m_process;
|
||||
QSettings *m_settings;
|
||||
QFSFileEngine *m_engine;
|
||||
QPointer<RemoteServer> m_server;
|
||||
QProcessSignalReceiver *m_signalReceiver;
|
||||
};
|
||||
|
||||
} // namespace QInstaller
|
||||
|
||||
#endif // REMOTESERVERCONNECTION_H
|
140
src/libs/installer/remoteserverconnection_p.h
Normal file
140
src/libs/installer/remoteserverconnection_p.h
Normal file
@ -0,0 +1,140 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the Qt Installer Framework.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef REMOTESERVERCONNECTION_P_H
|
||||
#define REMOTESERVERCONNECTION_P_H
|
||||
|
||||
#include "protocol.h"
|
||||
|
||||
#include <QMutex>
|
||||
#include <QProcess>
|
||||
#include <QVariant>
|
||||
|
||||
namespace QInstaller {
|
||||
|
||||
class QProcessSignalReceiver : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
friend class RemoteServerConnection;
|
||||
|
||||
private:
|
||||
explicit QProcessSignalReceiver(QProcess *process)
|
||||
: QObject(process)
|
||||
{
|
||||
connect(process, SIGNAL(bytesWritten(qint64)), SLOT(onBytesWritten(qint64)));
|
||||
connect(process, SIGNAL(aboutToClose()), SLOT(onAboutToClose()));
|
||||
connect(process, SIGNAL(readChannelFinished()), SLOT(onReadChannelFinished()));
|
||||
connect(process, SIGNAL(error(QProcess::ProcessError)),
|
||||
SLOT(onError(QProcess::ProcessError)));
|
||||
connect(process, SIGNAL(readyReadStandardOutput()), SLOT(onReadyReadStandardOutput()));
|
||||
connect(process, SIGNAL(readyReadStandardError()), SLOT(onReadyReadStandardError()));
|
||||
connect(process, SIGNAL(finished(int, QProcess::ExitStatus)),
|
||||
SLOT(onFinished(int, QProcess::ExitStatus)));
|
||||
connect(process, SIGNAL(readyRead()), SLOT(onReadyRead()));
|
||||
connect(process, SIGNAL(started()), SLOT(onStarted()));
|
||||
connect(process, SIGNAL(stateChanged(QProcess::ProcessState)),
|
||||
SLOT(onStateChanged(QProcess::ProcessState)));
|
||||
}
|
||||
|
||||
private Q_SLOTS:
|
||||
void onBytesWritten(qint64 count) {
|
||||
QMutexLocker _(&m_lock);
|
||||
m_receivedSignals.append(QLatin1String(Protocol::QProcessSignalBytesWritten));
|
||||
m_receivedSignals.append(count);
|
||||
}
|
||||
|
||||
void onAboutToClose() {
|
||||
QMutexLocker _(&m_lock);
|
||||
m_receivedSignals.append(QLatin1String(Protocol::QProcessSignalAboutToClose));
|
||||
}
|
||||
|
||||
void onReadChannelFinished() {
|
||||
QMutexLocker _(&m_lock);
|
||||
m_receivedSignals.append(QLatin1String(Protocol::QProcessSignalReadChannelFinished));
|
||||
}
|
||||
|
||||
void onError(QProcess::ProcessError error) {
|
||||
QMutexLocker _(&m_lock);
|
||||
m_receivedSignals.append(QLatin1String(Protocol::QProcessSignalError));
|
||||
m_receivedSignals.append(static_cast<int> (error));
|
||||
}
|
||||
|
||||
void onReadyReadStandardOutput() {
|
||||
QMutexLocker _(&m_lock);
|
||||
m_receivedSignals.append(QLatin1String(Protocol::QProcessSignalReadyReadStandardOutput));
|
||||
}
|
||||
|
||||
void onReadyReadStandardError() {
|
||||
QMutexLocker _(&m_lock);
|
||||
m_receivedSignals.append(QLatin1String(Protocol::QProcessSignalReadyReadStandardError));
|
||||
}
|
||||
|
||||
void onFinished(int exitCode, QProcess::ExitStatus exitStatus) {
|
||||
QMutexLocker _(&m_lock);
|
||||
m_receivedSignals.append(QLatin1String(Protocol::QProcessSignalFinished));
|
||||
m_receivedSignals.append(exitCode);
|
||||
m_receivedSignals.append(static_cast<int> (exitStatus));
|
||||
}
|
||||
|
||||
void onReadyRead() {
|
||||
QMutexLocker _(&m_lock);
|
||||
m_receivedSignals.append(QLatin1String(Protocol::QProcessSignalReadyRead));
|
||||
}
|
||||
|
||||
void onStarted() {
|
||||
QMutexLocker _(&m_lock);
|
||||
m_receivedSignals.append(QLatin1String(Protocol::QProcessSignalStarted));
|
||||
}
|
||||
|
||||
void onStateChanged(QProcess::ProcessState newState) {
|
||||
QMutexLocker _(&m_lock);
|
||||
m_receivedSignals.append(QLatin1String(Protocol::QProcessSignalStateChanged));
|
||||
m_receivedSignals.append(static_cast<int>(newState));
|
||||
}
|
||||
|
||||
private:
|
||||
QMutex m_lock;
|
||||
QVariantList m_receivedSignals;
|
||||
};
|
||||
|
||||
} // namespace QInstaller
|
||||
|
||||
#endif // REMOTESERVERCONNECTION_P_H
|
@ -1,6 +1,6 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012-2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the Qt Installer Framework.
|
||||
@ -84,6 +84,55 @@ void QInstaller::uiDetachedWait(int ms)
|
||||
} while (timer.elapsed() < ms);
|
||||
}
|
||||
|
||||
/*!
|
||||
Starts the program \a program with the arguments \a arguments in a new process, and detaches
|
||||
from it. Returns true on success; otherwise returns false. If the calling process exits, the
|
||||
detached process will continue to live.
|
||||
|
||||
Note that arguments that contain spaces are not passed to the process as separate arguments.
|
||||
|
||||
Unix: The started process will run in its own session and act like a daemon.
|
||||
Windows: Arguments that contain spaces are wrapped in quotes. The started process will run as
|
||||
a regular standalone process.
|
||||
|
||||
The process will be started in the directory \a workingDirectory.
|
||||
|
||||
If the function is successful then \a *pid is set to the process identifier of the started
|
||||
process.
|
||||
|
||||
Additional note: The difference in using this function over its equivalent from QProcess
|
||||
appears on Windows. While this function will truly detach and not show a GUI
|
||||
window for the started process, the QProcess version will.
|
||||
*/
|
||||
bool QInstaller::startDetached(const QString &program, const QStringList &arguments,
|
||||
const QString &workingDirectory, qint64 *pid)
|
||||
{
|
||||
bool success = false;
|
||||
#ifdef Q_OS_WIN
|
||||
PROCESS_INFORMATION pinfo;
|
||||
STARTUPINFOW startupInfo = { sizeof(STARTUPINFO), 0, 0, 0,
|
||||
static_cast<ulong>(CW_USEDEFAULT), static_cast<ulong>(CW_USEDEFAULT),
|
||||
static_cast<ulong>(CW_USEDEFAULT), static_cast<ulong>(CW_USEDEFAULT),
|
||||
0, 0, 0, STARTF_USESHOWWINDOW, SW_HIDE, 0, 0, 0, 0, 0
|
||||
}; // That's the difference over QProcess::startDetached(): STARTF_USESHOWWINDOW, SW_HIDE.
|
||||
|
||||
const QString commandline = QInstaller::createCommandline(program, arguments);
|
||||
if (CreateProcessW(0, (wchar_t*) commandline.utf16(),
|
||||
0, 0, false, CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE,
|
||||
0, workingDirectory.isEmpty() ? 0 : (wchar_t*) workingDirectory.utf16(),
|
||||
&startupInfo, &pinfo)) {
|
||||
success = true;
|
||||
CloseHandle(pinfo.hThread);
|
||||
CloseHandle(pinfo.hProcess);
|
||||
if (pid)
|
||||
*pid = pinfo.dwProcessId;
|
||||
}
|
||||
#else
|
||||
success = QProcess::startDetached(program, arguments, workingDirectory, pid);
|
||||
#endif
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool verb = false;
|
||||
|
||||
void QInstaller::setVerbose(bool v)
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012-2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the Qt Installer Framework.
|
||||
@ -58,6 +58,8 @@ QT_END_NAMESPACE
|
||||
|
||||
namespace QInstaller {
|
||||
void INSTALLER_EXPORT uiDetachedWait(int ms);
|
||||
bool INSTALLER_EXPORT startDetached(const QString &program, const QStringList &arguments,
|
||||
const QString &workingDirectory, qint64 *pid = 0);
|
||||
|
||||
QByteArray INSTALLER_EXPORT calculateHash(QIODevice *device, QCryptographicHash::Algorithm algo);
|
||||
QByteArray INSTALLER_EXPORT calculateHash(const QString &path, QCryptographicHash::Algorithm algo);
|
||||
@ -65,6 +67,7 @@ namespace QInstaller {
|
||||
QString INSTALLER_EXPORT replaceVariables(const QHash<QString,QString> &vars, const QString &str);
|
||||
QString INSTALLER_EXPORT replaceWindowsEnvironmentVariables(const QString &str);
|
||||
QStringList INSTALLER_EXPORT parseCommandLineArgs(int argc, char **argv);
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
QString createCommandline(const QString &program, const QStringList &arguments);
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user