Replace client-server classes and update implementations.

Remove superfluous file engine tests. Introduce auto test
for newly added client server classes. Fix some wrong
implementations serverside for settings array handling and
broken arguments in process wrapper. Replace all other parts
that with new implementations. Remove now unused classes.
Change-Id: I6f9e836993096a2c2c06b06f2b06d7aa4b287e56
Reviewed-by: Tim Jenssen <tim.jenssen@digia.com>
This commit is contained in:
kh1 2014-06-02 12:31:17 +02:00 committed by Karsten Heimrich
parent 7c07130119
commit 05afd837fc
24 changed files with 841 additions and 2588 deletions

View File

@ -43,11 +43,11 @@
#include "errors.h"
#include "fileutils.h"
#include "fsengineclient.h"
#include "globals.h"
#include "lib7z_facade.h"
#include "messageboxhandler.h"
#include "packagemanagercore.h"
#include "remoteclient.h"
#include "settings.h"
#include <kdupdaterupdatesourcesinfo.h>
@ -912,7 +912,7 @@ OperationList Component::operations() const
void Component::addOperation(Operation *operation)
{
d->m_operations.append(operation);
if (FSEngineClientHandler::instance().isActive())
if (RemoteClient::instance().isActive())
operation->setValue(QLatin1String("admin"), true);
}

View File

@ -1,850 +0,0 @@
/**************************************************************************
**
** Copyright (C) 2012-2013 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 "fsengineclient.h"
#include "adminauthorization.h"
#include "messageboxhandler.h"
#include <QElapsedTimer>
#include <QtCore/QCoreApplication>
#include <QtCore/QMutex>
#include <QtCore/QProcess>
#include <QtCore/QThread>
#include <QtCore/QTimer>
#include <QtCore/QUuid>
#include <QtNetwork/QHostAddress>
#include <QtNetwork/QTcpSocket>
// -- StillAliveThread
/*!
This thread convinces the watchdog in the running server that the client has not crashed yet.
*/
class StillAliveThread : public QThread
{
Q_OBJECT
public:
void run()
{
QTimer stillAliveTimer;
connect(&stillAliveTimer, SIGNAL(timeout()), this, SLOT(stillAlive()));
stillAliveTimer.start(1000);
exec();
}
public Q_SLOTS:
void stillAlive()
{
if (!FSEngineClientHandler::instance().isServerRunning())
return;
// in case of the server not running, this will simply fail
QTcpSocket socket;
FSEngineClientHandler::instance().connect(&socket);
}
};
// -- FSEngineClient
class FSEngineClient : public QAbstractFileEngine
{
public:
FSEngineClient();
~FSEngineClient();
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:
// these should be inline, since debugging on VS2010 fails without it (not sure about the reason)
template<typename T> inline T returnWithType() const
{
socket->flush();
if (!socket->bytesAvailable())
socket->waitForReadyRead();
quint32 test;
stream >> test;
T result;
stream >> result;
return result;
}
template<typename T> inline T returnWithCastedType() const
{
socket->flush();
if (!socket->bytesAvailable())
socket->waitForReadyRead();
quint32 test;
stream >> test;
int result;
stream >> result;
return static_cast<T>(result);
}
private:
friend class FSEngineClientHandler;
mutable QTcpSocket *socket;
mutable QDataStream stream;
};
/*!
\internal
*/
class FSEngineClientIterator : public QAbstractFileEngineIterator
{
public:
FSEngineClientIterator(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;
};
FSEngineClient::FSEngineClient()
: socket(new QTcpSocket)
{
FSEngineClientHandler::instance().connect(socket);
stream.setDevice(socket);
stream.setVersion(QDataStream::Qt_4_2);
}
FSEngineClient::~FSEngineClient()
{
if (QThread::currentThread() == socket->thread()) {
socket->close();
delete socket;
} else {
socket->deleteLater();
}
}
/*!
\reimp
*/
bool FSEngineClient::atEnd() const
{
stream << QString::fromLatin1("QFSFileEngine::atEnd");
return returnWithType<bool>();
}
/*!
\reimp
*/
QAbstractFileEngine::Iterator* FSEngineClient::beginEntryList(QDir::Filters filters,
const QStringList &filterNames)
{
QStringList entries = entryList(filters, filterNames);
entries.removeAll(QString());
return new FSEngineClientIterator(filters, filterNames, entries);
}
/*!
\reimp
*/
bool FSEngineClient::caseSensitive() const
{
stream << QString::fromLatin1("QFSFileEngine::caseSensitive");
return returnWithType<bool>();
}
/*!
\reimp
*/
bool FSEngineClient::close()
{
stream << QString::fromLatin1("QFSFileEngine::close");
return returnWithType<bool>();
}
/*!
\reimp
*/
bool FSEngineClient::copy(const QString &newName)
{
stream << QString::fromLatin1("QFSFileEngine::copy");
stream << newName;
return returnWithType<bool>();
}
/*!
\reimp
*/
QStringList FSEngineClient::entryList(QDir::Filters filters, const QStringList &filterNames) const
{
stream << QString::fromLatin1("QFSFileEngine::entryList");
stream << static_cast<int>(filters);
stream << filterNames;
return returnWithType<QStringList>();
}
/*!
\reimp
*/
QFile::FileError FSEngineClient::error() const
{
stream << QString::fromLatin1("QFSFileEngine::error");
return returnWithCastedType<QFile::FileError>();
}
/*!
\reimp
*/
QString FSEngineClient::errorString() const
{
stream << QString::fromLatin1("QFSFileEngine::errorString");
return returnWithType<QString>();
}
/*!
\reimp
*/
bool FSEngineClient::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
{
Q_UNUSED(extension)
Q_UNUSED(option)
Q_UNUSED(output)
return false;
}
/*!
\reimp
*/
QAbstractFileEngine::FileFlags FSEngineClient::fileFlags(FileFlags type) const
{
stream << QString::fromLatin1("QFSFileEngine::fileFlags");
stream << static_cast<int>(type);
return returnWithCastedType<QAbstractFileEngine::FileFlags>();
}
/*!
\reimp
*/
QString FSEngineClient::fileName(FileName file) const
{
stream << QString::fromLatin1("QFSFileEngine::fileName");
stream << static_cast<int>(file);
return returnWithType<QString>();
}
/*!
\reimp
*/
bool FSEngineClient::flush()
{
stream << QString::fromLatin1("QFSFileEngine::flush");
return returnWithType<bool>();
}
/*!
\reimp
*/
int FSEngineClient::handle() const
{
stream << QString::fromLatin1("QFSFileEngine::handle");
return returnWithType<int>();
}
/*!
\reimp
*/
bool FSEngineClient::isRelativePath() const
{
stream << QString::fromLatin1("QFSFileEngine::isRelativePath");
return returnWithType<bool>();
}
/*!
\reimp
*/
bool FSEngineClient::isSequential() const
{
stream << QString::fromLatin1("QFSFileEngine::isSequential");
return returnWithType<bool>();
}
/*!
\reimp
*/
bool FSEngineClient::link(const QString &newName)
{
stream << QString::fromLatin1("QFSFileEngine::link");
stream << newName;
return returnWithType<bool>();
}
/*!
\reimp
*/
bool FSEngineClient::mkdir(const QString &dirName, bool createParentDirectories) const
{
stream << QString::fromLatin1("QFSFileEngine::mkdir");
stream << dirName;
stream << createParentDirectories;
return returnWithType<bool>();
}
/*!
\reimp
*/
bool FSEngineClient::open(QIODevice::OpenMode mode)
{
stream << QString::fromLatin1("QFSFileEngine::open");
stream << static_cast<int>(mode);
return returnWithType<bool>();
}
/*!
\reimp
*/
QString FSEngineClient::owner(FileOwner owner) const
{
stream << QString::fromLatin1("QFSFileEngine::owner");
stream << static_cast<int>(owner);
return returnWithType<QString>();
}
/*!
\reimp
*/
uint FSEngineClient::ownerId(FileOwner owner) const
{
stream << QString::fromLatin1("QFSFileEngine::ownerId");
stream << static_cast<int>(owner);
return returnWithType<uint>();
}
/*!
\reimp
*/
qint64 FSEngineClient::pos() const
{
stream << QString::fromLatin1("QFSFileEngine::pos");
return returnWithType<qint64>();
}
/*!
\reimp
*/
qint64 FSEngineClient::read(char *data, qint64 maxlen)
{
stream << QString::fromLatin1("QFSFileEngine::read");
stream << maxlen;
socket->flush();
if (!socket->bytesAvailable())
socket->waitForReadyRead();
quint32 size;
stream >> size;
qint64 result;
stream >> result;
qint64 read = 0;
while (read < result) {
if (!socket->bytesAvailable())
socket->waitForReadyRead();
read += socket->read(data + read, result - read);
}
return result;
}
/*!
\reimp
*/
qint64 FSEngineClient::readLine(char *data, qint64 maxlen)
{
stream << QString::fromLatin1("QFSFileEngine::readLine");
stream << maxlen;
socket->flush();
if (!socket->bytesAvailable())
socket->waitForReadyRead();
quint32 size;
stream >> size;
qint64 result;
stream >> result;
qint64 read = 0;
while (read < result) {
if (!socket->bytesAvailable())
socket->waitForReadyRead();
read += socket->read(data + read, result - read);
}
return result;
}
/*!
\reimp
*/
bool FSEngineClient::remove()
{
stream << QString::fromLatin1("QFSFileEngine::remove");
return returnWithType<bool>();
}
/*!
\reimp
*/
bool FSEngineClient::rename(const QString &newName)
{
stream << QString::fromLatin1("QFSFileEngine::rename");
stream << newName;
return returnWithType<bool>();
}
/*!
\reimp
*/
bool FSEngineClient::rmdir(const QString &dirName, bool recurseParentDirectories) const
{
stream << QString::fromLatin1("QFSFileEngine::rmdir");
stream << dirName;
stream << recurseParentDirectories;
return returnWithType<bool>();
}
/*!
\reimp
*/
bool FSEngineClient::seek(qint64 offset)
{
stream << QString::fromLatin1("QFSFileEngine::seek");
stream << offset;
return returnWithType<bool>();
}
/*!
\reimp
*/
void FSEngineClient::setFileName(const QString &fileName)
{
stream << QString::fromLatin1("QFSFileEngine::setFileName");
stream << fileName;
socket->flush();
if (!socket->bytesAvailable())
socket->waitForReadyRead();
quint32 test;
stream >> test;
}
/*!
\reimp
*/
bool FSEngineClient::setPermissions(uint perms)
{
stream << QString::fromLatin1("QFSFileEngine::setPermissions");
stream << perms;
return returnWithType<bool>();
}
/*!
\reimp
*/
bool FSEngineClient::setSize(qint64 size)
{
stream << QString::fromLatin1("QFSFileEngine::setSize");
stream << size;
return returnWithType<bool>();
}
/*!
\reimp
*/
qint64 FSEngineClient::size() const
{
stream << QString::fromLatin1("QFSFileEngine::size");
return returnWithType<qint64>();
}
/*!
\reimp
*/
bool FSEngineClient::supportsExtension(Extension extension) const
{
stream << QString::fromLatin1("QFSFileEngine::supportsExtension");
stream << static_cast<int>(extension);
return returnWithType<bool>();
}
/*!
\reimp
*/
qint64 FSEngineClient::write(const char *data, qint64 len)
{
stream << QString::fromLatin1("QFSFileEngine::write");
stream << len;
qint64 written = 0;
while (written < len) {
written += socket->write(data, len - written);
socket->waitForBytesWritten();
}
return returnWithType<qint64>();
}
class FSEngineClientHandler::Private
{
public:
Private()
: mutex(QMutex::Recursive)
, port(0)
, startServerAsAdmin(false)
, serverStarted(false)
, serverStarting(false)
, active(false)
, thread(new StillAliveThread)
{
thread->moveToThread(thread);
}
void maybeStartServer();
void maybeStopServer();
QMutex mutex;
QHostAddress address;
quint16 port;
QString socket;
bool startServerAsAdmin;
bool serverStarted;
bool serverStarting;
bool active;
QString serverCommand;
QStringList serverArguments;
QString key;
StillAliveThread *const thread;
};
/*!
Creates a new FSEngineClientHandler with no connection.
*/
FSEngineClientHandler::FSEngineClientHandler()
: d(new Private)
{
//don't do this in the Private ctor as createUuid() accesses QFileEngine, which accesses this
// half-constructed handler -> Crash (KDNDK-248)
d->key = QUuid::createUuid().toString();
}
void FSEngineClientHandler::enableTestMode()
{
d->key = QLatin1String("testAuthorizationKey");
d->serverStarted = true;
}
void FSEngineClientHandler::init(quint16 port, const QHostAddress &a)
{
d->address = a;
d->port = port;
d->thread->start();
}
bool FSEngineClientHandler::connect(QTcpSocket *socket)
{
int tries = 3;
while (tries > 0) {
socket->connectToHost(d->address, d->port);
if (!socket->waitForConnected(10000)) {
if (static_cast<QAbstractSocket::SocketError>(socket->error()) != QAbstractSocket::UnknownSocketError)
--tries;
qApp->processEvents();
continue;
}
QDataStream stream(socket);
stream << QString::fromLatin1("authorize");
stream << d->key;
socket->flush();
return true;
}
return false;
}
/*!
Destroys the FSEngineClientHandler. If the handler started a server instance, it gets shut down.
*/
FSEngineClientHandler::~FSEngineClientHandler()
{
QMetaObject::invokeMethod(d->thread, "quit");
//d->maybeStopServer();
delete d;
}
/*!
Returns a previously created FSEngineClientHandler instance.
*/
FSEngineClientHandler &FSEngineClientHandler::instance()
{
static FSEngineClientHandler instance;
return instance;
}
/*!
Returns a created authorization key which is sent to the server when connecting via the "authorize"
command after the server was started.
*/
QString FSEngineClientHandler::authorizationKey() const
{
return d->key;
}
/*!
Sets \a command as the command to be executed to startup the server. If \a startAsAdmin is set,
it is executed with admin privilegies.
*/
void FSEngineClientHandler::setStartServerCommand(const QString &command, bool startAsAdmin)
{
setStartServerCommand(command, QStringList(), startAsAdmin);
}
/*!
Sets \a command as the command to be executed to startup the server. If \a startAsAdmin is set, it is
executed with admin privilegies. A list of \a arguments is passed to the process.
*/
void FSEngineClientHandler::setStartServerCommand(const QString &command, const QStringList &arguments,
bool startAsAdmin)
{
d->maybeStopServer();
d->startServerAsAdmin = startAsAdmin;
d->serverCommand = command;
d->serverArguments = arguments;
}
/*!
\reimp
*/
QAbstractFileEngine* FSEngineClientHandler::create(const QString &fileName) const
{
if (d->serverStarting || !d->active)
return 0;
d->maybeStartServer();
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
FSEngineClient *const client = new FSEngineClient;
// authorize
client->stream << QString::fromLatin1("authorize");
client->stream << d->key;
client->socket->flush();
client->setFileName(fileName);
return client;
}
/*!
Sets the FSEngineClientHandler to \a active. I.e. to actually return FSEngineClients if asked for.
*/
void FSEngineClientHandler::setActive(bool active)
{
d->active = active;
if (active) {
d->maybeStartServer();
d->active = d->serverStarted;
}
}
/*!
Returns true when this FSEngineClientHandler is active.
*/
bool FSEngineClientHandler::isActive() const
{
return d->active;
}
/*!
Returns true, when the server already has been started.
*/
bool FSEngineClientHandler::isServerRunning() const
{
return d->serverStarted;
}
/*!
\internal
Starts the server if a command was set and it isn't already started.
*/
void FSEngineClientHandler::Private::maybeStartServer()
{
if (serverStarted || serverCommand.isEmpty())
return;
const QMutexLocker ml(&mutex);
if (serverStarted)
return;
serverStarting = true;
if (startServerAsAdmin) {
AdminAuthorization auth;
serverStarted = auth.authorize() && auth.execute(0, serverCommand, serverArguments);
if (!serverStarted) {
// something went wrong with authorizing, either user pressed cancel or entered
// wrong password
const QString fallback = serverCommand + QLatin1String(" ") + serverArguments
.join(QLatin1String(" "));
const QMessageBox::Button res =
QInstaller::MessageBoxHandler::critical(QInstaller::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)
serverStarted = true;
}
} else {
serverStarted = QProcess::startDetached(serverCommand, serverArguments);
}
if (serverStarted) {
QElapsedTimer t;
t.start();
while (serverStarting && serverStarted
&& t.elapsed() < 30000) { // 30 seconds ought to be enough for the app to start
QTcpSocket s;
if (FSEngineClientHandler::instance().connect(&s))
serverStarting = false;
}
}
serverStarting = false;
}
/*!
Stops the server if it was started before.
*/
void FSEngineClientHandler::Private::maybeStopServer()
{
if (!serverStarted)
return;
const QMutexLocker ml(&mutex);
if (!serverStarted)
return;
QTcpSocket s;
if (FSEngineClientHandler::instance().connect(&s)) {
QDataStream stream(&s);
stream.setVersion(QDataStream::Qt_4_2);
stream << QString::fromLatin1("authorize");
stream << key;
stream << QString::fromLatin1("shutdown");
s.flush();
}
serverStarted = false;
}
#include "fsengineclient.moc"

View File

@ -1,83 +0,0 @@
/**************************************************************************
**
** Copyright (C) 2012-2013 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 FSENGINECLIENT_H
#define FSENGINECLIENT_H
#include "installer_global.h"
#include <QtNetwork/QHostAddress>
#include <QtCore/private/qabstractfileengine_p.h>
QT_BEGIN_NAMESPACE
class QTcpSocket;
QT_END_NAMESPACE
class INSTALLER_EXPORT FSEngineClientHandler : public QAbstractFileEngineHandler
{
public:
static FSEngineClientHandler& instance();
QAbstractFileEngine* create(const QString &fileName) const;
void init(quint16 port, const QHostAddress &a = QHostAddress::LocalHost);
bool connect(QTcpSocket *socket);
bool isActive() const;
void setActive(bool active);
void enableTestMode();
bool isServerRunning() const;
QString authorizationKey() const;
void setStartServerCommand(const QString &command, bool startAsAdmin = false);
void setStartServerCommand(const QString &command, const QStringList &arguments, bool startAsAdmin = false);
protected:
FSEngineClientHandler();
~FSEngineClientHandler();
private:
class Private;
Private *d;
};
#endif

View File

@ -1,616 +0,0 @@
/**************************************************************************
**
** Copyright (C) 2012-2013 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 "fsengineserver.h"
#include "utils.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QProcess>
#include <QtCore/QSettings>
#include <QtCore/QStringList>
#include <QtCore/QThread>
#include <QtNetwork/QTcpSocket>
#include <QtCore/private/qfsfileengine_p.h>
typedef int descriptor_t;
#ifdef Q_OS_WIN
# include <windows.h>
#endif
bool startDetached(const QString &program, const QStringList &args, const QString &workingDirectory,
qint64 *pid)
{
#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
};
const QString arguments = QInstaller::createCommandline(program, args);
const bool success = CreateProcess(0, (wchar_t*)arguments.utf16(),
0, 0, false, CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE,
0, (wchar_t*)workingDirectory.utf16(),
&startupInfo, &pinfo);
if (success) {
CloseHandle(pinfo.hThread);
CloseHandle(pinfo.hProcess);
if (pid)
*pid = pinfo.dwProcessId;
}
return success;
#else
return QProcess::startDetached(program, args, workingDirectory, pid);
#endif
}
class QProcessSignalReceiver : public QObject
{
Q_OBJECT
public:
QProcessSignalReceiver(QObject *parent = 0)
: QObject(parent)
{
connect(parent, SIGNAL(finished(int, QProcess::ExitStatus)), this,
SLOT(processFinished(int, QProcess::ExitStatus)));
connect(parent, SIGNAL(error(QProcess::ProcessError)), this,
SLOT(processError(QProcess::ProcessError)));
connect(parent, SIGNAL(readyRead()), this, SLOT(processReadyRead()));
connect(parent, SIGNAL(started()), this, SLOT(processStarted()));
connect(parent, SIGNAL(stateChanged(QProcess::ProcessState)), this,
SLOT(processStateChanged(QProcess::ProcessState)));
}
QList<QVariant> receivedSignals;
private Q_SLOTS:
void processError(QProcess::ProcessError error);
void processFinished(int exitCode, QProcess::ExitStatus exitStatus);
void processReadyRead();
void processStarted();
void processStateChanged(QProcess::ProcessState newState);
};
/*!
\internal
*/
class FSEngineConnectionThread : public QThread
{
Q_OBJECT
public:
FSEngineConnectionThread(descriptor_t socketDescriptor, QObject *parent)
: QThread(parent)
, descriptor(socketDescriptor)
, settings(0)
, process(0)
, signalReceiver(0)
{}
protected:
void run();
private:
QByteArray handleCommand(const QString &command);
QFSFileEngine engine;
const descriptor_t descriptor;
QDataStream receivedStream;
QSettings *settings;
QProcess *process;
QProcessSignalReceiver *signalReceiver;
};
FSEngineServer::FSEngineServer(quint16 port, QObject *parent)
: QTcpServer(parent)
{
listen(QHostAddress::LocalHost, port);
connect(&watchdog, SIGNAL(timeout()), qApp, SLOT(quit()));
watchdog.setSingleShot(true);
watchdog.setInterval(30000);
watchdog.start();
}
FSEngineServer::FSEngineServer(const QHostAddress &address, quint16 port, QObject *parent)
: QTcpServer(parent)
{
listen(address, port);
connect(&watchdog, SIGNAL(timeout()), qApp, SLOT(quit()));
watchdog.setSingleShot(true);
watchdog.setInterval(30000);
watchdog.start();
}
/*!
Destroys the FSEngineServer.
*/
FSEngineServer::~FSEngineServer()
{
const QList<QThread *> threads = findChildren<QThread *>();
foreach (QThread *thread, threads)
thread->wait();
}
/*!
\reimp
*/
void FSEngineServer::incomingConnection(int socketDescriptor)
{
qApp->processEvents();
QThread *const thread = new FSEngineConnectionThread(socketDescriptor, this);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
watchdog.start();
}
void FSEngineServer::enableTestMode()
{
setAuthorizationKey(QLatin1String("testAuthorizationKey"));
//we don't want to kill the server,
//maybe we should introduce a call where the client can kill the server
watchdog.disconnect();
}
/*!
Sets the authorization key this server is asking the clients for to \a authorizationKey.
*/
void FSEngineServer::setAuthorizationKey(const QString &authorizationKey)
{
key = authorizationKey;
}
QString FSEngineServer::authorizationKey() const
{
return key;
}
void QProcessSignalReceiver::processError(QProcess::ProcessError error)
{
receivedSignals.push_back(QLatin1String("error"));
receivedSignals.push_back(static_cast<int> (error));
}
void QProcessSignalReceiver::processFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
receivedSignals.push_back(QLatin1String("finished"));
receivedSignals.push_back(exitCode);
receivedSignals.push_back(static_cast<int> (exitStatus));
}
void QProcessSignalReceiver::processStarted()
{
receivedSignals.push_back(QLatin1String("started"));
}
void QProcessSignalReceiver::processReadyRead()
{
receivedSignals.push_back(QLatin1String("readyRead"));
}
void QProcessSignalReceiver::processStateChanged(QProcess::ProcessState newState)
{
receivedSignals.push_back(QLatin1String("stateChanged"));
receivedSignals.push_back(static_cast<int>(newState));
}
/*!
\reimp
*/
void FSEngineConnectionThread::run()
{
QTcpSocket socket;
socket.setSocketDescriptor(descriptor);
receivedStream.setDevice(&socket);
receivedStream.setVersion(QDataStream::Qt_4_2);
bool authorized = false;
while (static_cast<QAbstractSocket::SocketState>(socket.state()) == QAbstractSocket::ConnectedState) {
if (!socket.bytesAvailable() && !socket.waitForReadyRead(250))
continue;
QString command;
receivedStream >> command;
if (authorized && command == QLatin1String("shutdown")) {
// this is a graceful shutdown
socket.close();
parent()->deleteLater();
return;
} else if (command == QLatin1String("authorize")) {
QString k;
receivedStream >> k;
if (k != dynamic_cast<FSEngineServer*> (parent())->authorizationKey()) {
// this is closing the connection... auth failed
socket.close();
return;
}
authorized = true;
} else if (authorized) {
if (command.isEmpty())
continue;
const QByteArray result = handleCommand(command);
receivedStream << static_cast<quint32> (result.size());
if (!result.isEmpty())
receivedStream.writeRawData(result.data(), result.size());
} else {
// authorization failed, connection not wanted
socket.close();
return;
}
}
}
static QDataStream &operator<<(QDataStream &stream, const QSettings::Status &status)
{
return stream << static_cast<int>(status);
}
/*!
Handles \a command and returns a QByteArray which has the result streamed into it.
*/
QByteArray FSEngineConnectionThread::handleCommand(const QString &command)
{
QByteArray block;
QDataStream returnStream(&block, QIODevice::WriteOnly);
returnStream.setVersion(QDataStream::Qt_4_2);
// first, QSettings handling
if (command == QLatin1String("createQSettings")) {
QString fileName;
receivedStream >> fileName;
settings = new QSettings(fileName, QSettings::NativeFormat);
} else if (command == QLatin1String("destroyQSettings")) {
delete settings;
settings = 0;
} else if (command == QLatin1String("QSettings::allKeys")) {
returnStream << settings->allKeys();
} else if (command == QLatin1String("QSettings::beginGroup")) {
QString prefix;
receivedStream >> prefix;
settings->beginGroup(prefix);
} else if (command == QLatin1String("QSettings::beginReadArray")) {
QString prefix;
int size;
receivedStream >> prefix;
receivedStream >> size;
settings->beginWriteArray(prefix, size);
} else if (command == QLatin1String("QSettings::beginWriteArray")) {
QString prefix;
receivedStream >> prefix;
returnStream << settings->beginReadArray(prefix);
} else if (command == QLatin1String("QSettings::childGroups")) {
returnStream << settings->childGroups();
} else if (command == QLatin1String("QSettings::childKeys")) {
returnStream << settings->childKeys();
} else if (command == QLatin1String("QSettings::clear")) {
settings->clear();
} else if (command == QLatin1String("QSettings::contains")) {
QString key;
receivedStream >> key;
returnStream << settings->contains(key);
} else if (command == QLatin1String("QSettings::endArray")) {
settings->endArray();
} else if (command == QLatin1String("QSettings::endGroup")) {
settings->endGroup();
} else if (command == QLatin1String("QSettings::fallbacksEnabled")) {
returnStream << settings->fallbacksEnabled();
} else if (command == QLatin1String("QSettings::fileName")) {
returnStream << settings->fileName();
} else if (command == QLatin1String("QSettings::group")) {
returnStream << settings->group();
} else if (command == QLatin1String("QSettings::isWritable")) {
returnStream << settings->isWritable();
} else if (command == QLatin1String("QSettings::remove")) {
QString key;
receivedStream >> key;
settings->remove(key);
} else if (command == QLatin1String("QSettings::setArrayIndex")) {
int i;
receivedStream >> i;
settings->setArrayIndex(i);
} else if (command == QLatin1String("QSettings::setFallbacksEnabled")) {
bool b;
receivedStream >> b;
settings->setFallbacksEnabled(b);
} else if (command == QLatin1String("QSettings::status")) {
returnStream << settings->status();
} else if (command == QLatin1String("QSettings::sync")) {
settings->sync();
} else if (command == QLatin1String("QSettings::setValue")) {
QString key;
QVariant value;
receivedStream >> key;
receivedStream >> value;
settings->setValue(key, value);
} else if (command == QLatin1String("QSettings::value")) {
QString key;
QVariant defaultValue;
receivedStream >> key;
receivedStream >> defaultValue;
returnStream << settings->value(key, defaultValue);
}
// from here, QProcess handling
else if (command == QLatin1String("createQProcess")) {
process = new QProcess;
signalReceiver = new QProcessSignalReceiver(process);
} else if (command == QLatin1String("destroyQProcess")) {
signalReceiver->receivedSignals.clear();
process->deleteLater();
process = 0;
} else if (command == QLatin1String("getQProcessSignals")) {
returnStream << signalReceiver->receivedSignals;
signalReceiver->receivedSignals.clear();
qApp->processEvents();
} else if (command == QLatin1String("QProcess::closeWriteChannel")) {
process->closeWriteChannel();
} else if (command == QLatin1String("QProcess::exitCode")) {
returnStream << process->exitCode();
} else if (command == QLatin1String("QProcess::exitStatus")) {
returnStream << static_cast<int> (process->exitStatus());
} else if (command == QLatin1String("QProcess::kill")) {
process->kill();
} else if (command == QLatin1String("QProcess::readAll")) {
returnStream << process->readAll();
} else if (command == QLatin1String("QProcess::readAllStandardOutput")) {
returnStream << process->readAllStandardOutput();
} else if (command == QLatin1String("QProcess::readAllStandardError")) {
returnStream << process->readAllStandardError();
} else if (command == QLatin1String("QProcess::startDetached")) {
QString program;
QStringList arguments;
QString workingDirectory;
receivedStream >> program;
receivedStream >> arguments;
receivedStream >> workingDirectory;
qint64 pid;
const bool result = startDetached(program, arguments, workingDirectory, &pid);
returnStream << qMakePair< bool, qint64> (result, pid);
} else if (command == QLatin1String("QProcess::setWorkingDirectory")) {
QString dir;
receivedStream >> dir;
process->setWorkingDirectory(dir);
} else if (command == QLatin1String("QProcess::setEnvironment")) {
QStringList env;
receivedStream >> env;
process->setEnvironment(env);
} else if (command == QLatin1String("QProcess::start")) {
QString program;
QStringList arguments;
int mode;
receivedStream >> program;
receivedStream >> arguments;
receivedStream >> mode;
process->start(program, arguments, static_cast<QIODevice::OpenMode> (mode));
} else if (command == QLatin1String("QProcess::state")) {
returnStream << static_cast<int> (process->state());
} else if (command == QLatin1String("QProcess::terminate")) {
process->terminate();
} else if (command == QLatin1String("QProcess::waitForFinished")) {
int msecs;
receivedStream >> msecs;
returnStream << process->waitForFinished(msecs);
} else if (command == QLatin1String("QProcess::waitForStarted")) {
int msecs;
receivedStream >> msecs;
returnStream << process->waitForStarted(msecs);
} else if (command == QLatin1String("QProcess::workingDirectory")) {
returnStream << process->workingDirectory();
} else if (command == QLatin1String("QProcess::errorString")) {
returnStream << process->errorString();
} else if (command == QLatin1String("QProcess::write")) {
QByteArray byteArray;
receivedStream >> byteArray;
returnStream << process->write(byteArray);
} else if (command == QLatin1String("QProcess::readChannel")) {
returnStream << static_cast<int> (process->readChannel());
} else if (command == QLatin1String("QProcess::setReadChannel")) {
int processChannel;
receivedStream >> processChannel;
process->setReadChannel(static_cast<QProcess::ProcessChannel>(processChannel));
} else if (command == QLatin1String("QProcess::write")) {
QByteArray byteArray;
receivedStream >> byteArray;
returnStream << process->write(byteArray);
}
#ifdef Q_OS_WIN
else if (command == QLatin1String("QProcess::setNativeArguments")) {
QString arguments;
receivedStream >> arguments;
process->setNativeArguments(arguments);
}
#endif
// from here, QFSEngine handling
else if (command == QLatin1String("QFSFileEngine::atEnd")) {
returnStream << engine.atEnd();
} else if (command == QLatin1String("QFSFileEngine::caseSensitive")) {
returnStream << engine.caseSensitive();
} else if (command == QLatin1String("QFSFileEngine::close")) {
returnStream << engine.close();
} else if (command == QLatin1String("QFSFileEngine::copy")) {
QString newName;
receivedStream >> newName;
returnStream << engine.copy(newName);
} else if (command == QLatin1String("QFSFileEngine::entryList")) {
int filters;
QStringList filterNames;
receivedStream >> filters;
receivedStream >> filterNames;
returnStream << engine.entryList(static_cast<QDir::Filters> (filters), filterNames);
} else if (command == QLatin1String("QFSFileEngine::error")) {
returnStream << static_cast<int> (engine.error());
} else if (command == QLatin1String("QFSFileEngine::errorString")) {
returnStream << engine.errorString();
}
// extension
else if (command == QLatin1String("QFSFileEngine::fileFlags")) {
int flags;
receivedStream >> flags;
returnStream << static_cast<int>(engine.fileFlags(static_cast<QAbstractFileEngine::FileFlags>(flags)));
} else if (command == QLatin1String("QFSFileEngine::fileName")) {
int file;
receivedStream >> file;
returnStream << engine.fileName(static_cast<QAbstractFileEngine::FileName> (file));
} else if (command == QLatin1String("QFSFileEngine::flush")) {
returnStream << engine.flush();
} else if (command == QLatin1String("QFSFileEngine::handle")) {
returnStream << engine.handle();
} else if (command == QLatin1String("QFSFileEngine::isRelativePath")) {
returnStream << engine.isRelativePath();
} else if (command == QLatin1String("QFSFileEngine::isSequential")) {
returnStream << engine.isSequential();
} else if (command == QLatin1String("QFSFileEngine::link")) {
QString newName;
receivedStream >> newName;
returnStream << engine.link(newName);
} else if (command == QLatin1String("QFSFileEngine::mkdir")) {
QString dirName;
bool createParentDirectories;
receivedStream >> dirName;
receivedStream >> createParentDirectories;
returnStream << engine.mkdir(dirName, createParentDirectories);
} else if (command == QLatin1String("QFSFileEngine::open")) {
int openMode;
receivedStream >> openMode;
returnStream << engine.open(static_cast<QIODevice::OpenMode> (openMode));
} else if (command == QLatin1String("QFSFileEngine::owner")) {
int owner;
receivedStream >> owner;
returnStream << engine.owner(static_cast<QAbstractFileEngine::FileOwner> (owner));
} else if (command == QLatin1String("QFSFileEngine::ownerId")) {
int owner;
receivedStream >> owner;
returnStream << engine.ownerId(static_cast<QAbstractFileEngine::FileOwner> (owner));
} else if (command == QLatin1String("QFSFileEngine::pos")) {
returnStream << engine.pos();
} else if (command == QLatin1String("QFSFileEngine::read")) {
qint64 maxlen;
receivedStream >> maxlen;
QByteArray ba(maxlen, '\0');
const qint64 result = engine.read(ba.data(), maxlen);
returnStream << result;
int written = 0;
while (written < result)
written += returnStream.writeRawData(ba.data() + written, result - written);
} else if (command == QLatin1String("QFSFileEngine::readLine")) {
qint64 maxlen;
receivedStream >> maxlen;
QByteArray ba(maxlen, '\0');
const qint64 result = engine.readLine(ba.data(), maxlen);
returnStream << result;
int written = 0;
while (written < result)
written += returnStream.writeRawData(ba.data() + written, result - written);
} else if (command == QLatin1String("QFSFileEngine::remove")) {
returnStream << engine.remove();
} else if (command == QLatin1String("QFSFileEngine::rename")) {
QString newName;
receivedStream >> newName;
returnStream << engine.rename(newName);
} else if (command == QLatin1String("QFSFileEngine::rmdir")) {
QString dirName;
bool recurseParentDirectories;
receivedStream >> dirName;
receivedStream >> recurseParentDirectories;
returnStream << engine.rmdir(dirName, recurseParentDirectories);
} else if (command == QLatin1String("QFSFileEngine::seek")) {
quint64 offset;
receivedStream >> offset;
returnStream << engine.seek(offset);
} else if (command == QLatin1String("QFSFileEngine::setFileName")) {
QString fileName;
receivedStream >> fileName;
engine.setFileName(fileName);
} else if (command == QLatin1String("QFSFileEngine::setPermissions")) {
uint perms;
receivedStream >> perms;
returnStream << engine.setPermissions(perms);
} else if (command == QLatin1String("QFSFileEngine::setSize")) {
qint64 size;
receivedStream >> size;
returnStream << engine.setSize(size);
} else if (command == QLatin1String("QFSFileEngine::size")) {
returnStream << engine.size();
} else if (command == QLatin1String("QFSFileEngine::supportsExtension")) {
int extension;
receivedStream >> extension;
//returnStream << engine.supportsExtension(static_cast<QAbstractFileEngine::Extension> (extension));
returnStream << false;
} else if (command == QLatin1String("QFSFileEngine::write")) {
qint64 length;
receivedStream >> length;
qint64 read = 0;
qint64 written = 0;
QByteArray buffer(65536, '\0');
while (read < length) {
if (!receivedStream.device()->bytesAvailable())
receivedStream.device()->waitForReadyRead(-1);
const qint64 r = receivedStream.readRawData(buffer.data(), qMin(length - read,
static_cast<qint64> (buffer.length())));
read += r;
qint64 w = 0;
while (w < r)
w += engine.write(buffer.data(), r);
written += r;
}
returnStream << written;
} else if (!command.isEmpty()) {
qDebug() << "unknown command:" << command;
}
return block;
}
#include "fsengineserver.moc"
#include "moc_fsengineserver.cpp"

View File

@ -1,71 +0,0 @@
/**************************************************************************
**
** Copyright (C) 2012-2013 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 FSENGINESERVER_H
#define FSENGINESERVER_H
#include "installer_global.h"
#include <QtCore/QTimer>
#include <QtNetwork/QTcpServer>
class INSTALLER_EXPORT FSEngineServer : public QTcpServer
{
Q_OBJECT
public:
explicit FSEngineServer(quint16 port, QObject *parent = 0);
FSEngineServer(const QHostAddress &address, quint16 port, QObject *parent = 0);
~FSEngineServer();
void enableTestMode();
void setAuthorizationKey(const QString &key);
QString authorizationKey() const;
protected:
void incomingConnection(int socketDescriptor);
private:
QString key;
QTimer watchdog;
};
#endif

View File

@ -44,10 +44,9 @@
#include "qinstallerglobal.h"
class QSettingsWrapper;
namespace QInstaller {
class QSettingsWrapper;
class INSTALLER_EXPORT GlobalSettingsOperation : public Operation
{
public:

View File

@ -74,8 +74,6 @@ HEADERS += packagemanagercore.h \
operationrunner.h \
updatesettings.h \
adminauthorization.h \
fsengineclient.h \
fsengineserver.h \
elevatedexecuteoperation.h \
fakestopprocessforupdateoperation.h \
lazyplaintextedit.h \
@ -158,8 +156,6 @@ SOURCES += packagemanagercore.cpp \
operationrunner.cpp \
updatesettings.cpp \
adminauthorization.cpp \
fsengineclient.cpp \
fsengineserver.cpp \
elevatedexecuteoperation.cpp \
fakestopprocessforupdateoperation.cpp \
lazyplaintextedit.cpp \
@ -170,7 +166,6 @@ SOURCES += packagemanagercore.cpp \
licenseoperation.cpp \
component_p.cpp \
qprocesswrapper.cpp \
templates.cpp \
qsettingswrapper.cpp \
settings.cpp \
packagemanagerproxyfactory.cpp \

View File

@ -47,13 +47,13 @@
#include "componentmodel.h"
#include "downloadarchivesjob.h"
#include "errors.h"
#include "fsengineclient.h"
#include "globals.h"
#include "messageboxhandler.h"
#include "packagemanagerproxyfactory.h"
#include "progresscoordinator.h"
#include "qprocesswrapper.h"
#include "qsettingswrapper.h"
#include "remoteclient.h"
#include "settings.h"
#include "utils.h"
@ -648,7 +648,7 @@ void PackageManagerCore::rollBackInstallation()
while (!d->m_performedOperationsCurrentSession.isEmpty()) {
try {
Operation *const operation = d->m_performedOperationsCurrentSession.takeLast();
const bool becameAdmin = !d->m_FSEngineClientHandler->isActive()
const bool becameAdmin = !RemoteClient::instance().isActive()
&& operation->value(QLatin1String("admin")).toBool() && gainAdminRights();
if (operation->hasValue(QLatin1String("uninstall-only"))) {
@ -1417,8 +1417,8 @@ bool PackageManagerCore::gainAdminRights()
if (AdminAuthorization::hasAdminRights())
return true;
d->m_FSEngineClientHandler->setActive(true);
if (!d->m_FSEngineClientHandler->isActive())
RemoteClient::instance().setActive(true);
if (!RemoteClient::instance().isActive())
throw Error(QObject::tr("Error while elevating access rights."));
return true;
}
@ -1432,7 +1432,7 @@ bool PackageManagerCore::gainAdminRights()
*/
void PackageManagerCore::dropAdminRights()
{
d->m_FSEngineClientHandler->setActive(false);
RemoteClient::instance().setActive(false);
}
/*!

View File

@ -47,7 +47,7 @@
#include "componentmodel.h"
#include "errors.h"
#include "fileutils.h"
#include "fsengineclient.h"
#include "remotefileengine.h"
#include "globals.h"
#include "graph.h"
#include "messageboxhandler.h"
@ -55,6 +55,7 @@
#include "progresscoordinator.h"
#include "qprocesswrapper.h"
#include "qsettingswrapper.h"
#include "remoteclient.h"
#include "kdsavefile.h"
#include "kdselfrestarter.h"
@ -130,26 +131,6 @@ static bool runOperation(Operation *operation, PackageManagerCorePrivate::Operat
return false;
}
/*!
\internal
Creates and initializes a FSEngineClientHandler -> makes us get admin rights for QFile operations
*/
static FSEngineClientHandler *sClientHandlerInstance = 0;
static FSEngineClientHandler *initFSEngineClientHandler()
{
if (sClientHandlerInstance == 0) {
sClientHandlerInstance = &FSEngineClientHandler::instance();
// Initialize the created FSEngineClientHandler instance.
const int port = 30000 + qrand() % 1000;
sClientHandlerInstance->init(port);
sClientHandlerInstance->setStartServerCommand(QCoreApplication::applicationFilePath(),
QStringList() << QLatin1String("--startserver") << QString::number(port)
<< sClientHandlerInstance->authorizationKey(), true);
}
return sClientHandlerInstance;
}
static QStringList checkRunningProcessesFromList(const QStringList &processList)
{
const QList<ProcessInfo> allProcesses = runningProcesses();
@ -205,7 +186,6 @@ static void deferredRename(const QString &oldName, const QString &newName, bool
PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core)
: m_updateFinder(0)
, m_updaterApplication(new DummyConfigurationInterface)
, m_FSEngineClientHandler(0)
, m_core(core)
, m_updates(false)
, m_repoFetched(false)
@ -217,6 +197,7 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core)
, m_defaultModel(0)
, m_updaterModel(0)
, m_guiObject(0)
, m_remoteFileEngineHandler(0)
{
}
@ -224,7 +205,6 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core, q
const OperationList &performedOperations)
: m_updateFinder(0)
, m_updaterApplication(new DummyConfigurationInterface)
, m_FSEngineClientHandler(initFSEngineClientHandler())
, m_status(PackageManagerCore::Unfinished)
, m_needsHardRestart(false)
, m_testChecksum(false)
@ -245,7 +225,16 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core, q
, m_defaultModel(0)
, m_updaterModel(0)
, m_guiObject(0)
, m_remoteFileEngineHandler(new RemoteFileEngineHandler)
{
// Creates and initializes a remote client, makes us get admin rights for QFile, QSettings
// and QProcess operations.
int port = 30000 + qrand() % 1000;
RemoteClient::instance().init(port, QHostAddress::LocalHost, RemoteClient::Release);
RemoteClient::instance().setStartServerCommand(QCoreApplication::applicationFilePath(),
QStringList() << QLatin1String("--startserver") << QString::number(port)
<< RemoteClient::instance().authorizationKey(), RemoteClient::Administrator);
connect(this, SIGNAL(installationStarted()), m_core, SIGNAL(installationStarted()));
connect(this, SIGNAL(installationFinished()), m_core, SIGNAL(installationFinished()));
connect(this, SIGNAL(uninstallationStarted()), m_core, SIGNAL(uninstallationStarted()));
@ -262,9 +251,7 @@ PackageManagerCorePrivate::~PackageManagerCorePrivate()
qDeleteAll(m_performedOperationsOld);
qDeleteAll(m_performedOperationsCurrentSession);
// check for fake installer case
if (m_FSEngineClientHandler)
m_FSEngineClientHandler->setActive(false);
RemoteClient::instance().setActive(false);
delete m_updateFinder;
delete m_proxyFactory;
@ -812,7 +799,7 @@ void PackageManagerCorePrivate::writeMaintenanceConfigFiles()
{
QFile tmp(iniPath); // force gaining admin rights in case we haven't done already and we need it
if (!tmp.open(QIODevice::ReadWrite) || !tmp.isWritable()) {
if (!m_FSEngineClientHandler->isActive()) // check if nobody did it before...
if (!RemoteClient::instance().isActive()) // check if nobody did it before...
gainedAdminRights = m_core->gainAdminRights();
}
tmp.close();

View File

@ -46,6 +46,7 @@
#include "packagemanagercore.h"
#include "packagemanagercoredata.h"
#include "qinstallerglobal.h"
#include "remotefileengine.h"
#include "kdsysinfo.h"
#include "kdupdaterapplication.h"
@ -54,7 +55,6 @@
#include <QObject>
class FSEngineClientHandler;
class KDJob;
QT_FORWARD_DECLARE_CLASS(QFile)
@ -204,7 +204,6 @@ signals:
public:
UpdateFinder *m_updateFinder;
Application m_updaterApplication;
FSEngineClientHandler *m_FSEngineClientHandler;
int m_status;
QString m_error;
@ -294,6 +293,7 @@ private:
ComponentModel *m_updaterModel;
QObject *m_guiObject;
QScopedPointer<RemoteFileEngineHandler> m_remoteFileEngineHandler;
private:
// remove once we deprecate isSelected, setSelected etc...

View File

@ -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.
@ -41,173 +41,97 @@
#include "qprocesswrapper.h"
#include "fsengineclient.h"
#include "templates.cpp"
#include "protocol.h"
#include "utils.h"
#include <QtCore/QThread>
#include <QDir>
#include <QtNetwork/QTcpSocket>
// -- QProcessWrapper::Private
class QProcessWrapper::Private
{
public:
Private(QProcessWrapper *qq)
: q(qq)
, ignoreTimer(false)
, socket(0)
{}
bool createSocket()
{
if (!FSEngineClientHandler::instance().isActive())
return false;
if (socket != 0 && socket->state() == static_cast<int>(QAbstractSocket::ConnectedState))
return true;
if (socket != 0)
delete socket;
socket = new QTcpSocket;
if (!FSEngineClientHandler::instance().connect(socket))
return false;
stream.setDevice(socket);
stream.setVersion(QDataStream::Qt_4_2);
stream << QString::fromLatin1("createQProcess");
socket->flush();
stream.device()->waitForReadyRead(-1);
quint32 test;
stream >> test;
stream.device()->readAll();
q->startTimer(250);
return true;
}
class TimerBlocker
{
public:
explicit TimerBlocker(const QProcessWrapper *wrapper)
: w(const_cast<QProcessWrapper *>(wrapper))
{
w->d->ignoreTimer = true;
}
~TimerBlocker()
{
w->d->ignoreTimer = false;
}
private:
QProcessWrapper *const w;
};
private:
QProcessWrapper *const q;
public:
bool ignoreTimer;
QProcess process;
mutable QTcpSocket *socket;
mutable QDataStream stream;
};
// -- QProcessWrapper
namespace QInstaller {
QProcessWrapper::QProcessWrapper(QObject *parent)
: QObject(parent)
, d(new Private(this))
: RemoteObject(QLatin1String(Protocol::QProcess), parent)
{
connect(&d->process, SIGNAL(bytesWritten(qint64)), SIGNAL(bytesWritten(qint64)));
connect(&d->process, SIGNAL(aboutToClose()), SIGNAL(aboutToClose()));
connect(&d->process, SIGNAL(readChannelFinished()), SIGNAL(readChannelFinished()));
connect(&d->process, SIGNAL(error(QProcess::ProcessError)), SIGNAL(error(QProcess::ProcessError)));
connect(&d->process, SIGNAL(readyReadStandardOutput()), SIGNAL(readyReadStandardOutput()));
connect(&d->process, SIGNAL(readyReadStandardError()), SIGNAL(readyReadStandardError()));
connect(&d->process, SIGNAL(finished(int)), SIGNAL(finished(int)));
connect(&d->process, SIGNAL(finished(int,QProcess::ExitStatus)), SIGNAL(finished(int,QProcess::ExitStatus)));
connect(&d->process, SIGNAL(readyRead()), SIGNAL(readyRead()));
connect(&d->process, SIGNAL(started()), SIGNAL(started()));
connect(&d->process, SIGNAL(stateChanged(QProcess::ProcessState)), SIGNAL(stateChanged(QProcess::ProcessState)));
qRegisterMetaType<QProcess::ExitStatus>();
qRegisterMetaType<QProcess::ProcessError>();
qRegisterMetaType<QProcess::ProcessState>();
m_timer.start(250);
connect(&m_timer, SIGNAL(timeout()), this, SLOT(processSignals()));
connect(&process, SIGNAL(bytesWritten(qint64)), SIGNAL(bytesWritten(qint64)));
connect(&process, SIGNAL(aboutToClose()), SIGNAL(aboutToClose()));
connect(&process, SIGNAL(readChannelFinished()), SIGNAL(readChannelFinished()));
connect(&process, SIGNAL(error(QProcess::ProcessError)), SIGNAL(error(QProcess::ProcessError)));
connect(&process, SIGNAL(readyReadStandardOutput()), SIGNAL(readyReadStandardOutput()));
connect(&process, SIGNAL(readyReadStandardError()), SIGNAL(readyReadStandardError()));
connect(&process, SIGNAL(finished(int)), SIGNAL(finished(int)));
connect(&process, SIGNAL(finished(int,QProcess::ExitStatus)),
SIGNAL(finished(int,QProcess::ExitStatus)));
connect(&process, SIGNAL(readyRead()), SIGNAL(readyRead()));
connect(&process, SIGNAL(started()), SIGNAL(started()));
connect(&process, SIGNAL(stateChanged(QProcess::ProcessState)),
SIGNAL(stateChanged(QProcess::ProcessState)));
}
QProcessWrapper::~QProcessWrapper()
{
if (d->socket != 0) {
d->stream << QString::fromLatin1("destroyQProcess");
d->socket->flush();
quint32 result;
d->stream >> result;
if (QThread::currentThread() == d->socket->thread()) {
d->socket->close();
delete d->socket;
} else {
d->socket->deleteLater();
}
}
delete d;
m_timer.stop();
}
void QProcessWrapper::timerEvent(QTimerEvent *event)
void QProcessWrapper::processSignals()
{
Q_UNUSED(event)
if (d->ignoreTimer)
if (!isConnectedToServer())
return;
QList<QVariant> receivedSignals;
{
const Private::TimerBlocker blocker(this);
if (!m_lock.tryLockForRead())
return;
d->stream << QString::fromLatin1("getQProcessSignals");
d->socket->flush();
d->stream.device()->waitForReadyRead(-1);
quint32 test;
d->stream >> test;
d->stream >> receivedSignals;
d->stream.device()->readAll();
}
QList<QVariant> receivedSignals =
callRemoteMethod<QList<QVariant> >(QString::fromLatin1(Protocol::GetQProcessSignals));
while (!receivedSignals.isEmpty()) {
const QString name = receivedSignals.takeFirst().toString();
if (name == QLatin1String("started")) {
if (name == QLatin1String(Protocol::QProcessSignalBytesWritten)) {
emit bytesWritten(receivedSignals.takeFirst().value<qint64>());
} else if (name == QLatin1String(Protocol::QProcessSignalAboutToClose)) {
emit aboutToClose();
} else if (name == QLatin1String(Protocol::QProcessSignalReadChannelFinished)) {
emit readChannelFinished();
} else if (name == QLatin1String(Protocol::QProcessSignalError)) {
emit error(static_cast<QProcess::ProcessError> (receivedSignals.takeFirst().toInt()));
} else if (name == QLatin1String(Protocol::QProcessSignalReadyReadStandardOutput)) {
emit readyReadStandardOutput();
} else if (name == QLatin1String(Protocol::QProcessSignalReadyReadStandardError)) {
emit readyReadStandardError();
} else if (name == QLatin1String(Protocol::QProcessSignalStarted)) {
emit started();
} else if (name == QLatin1String("readyRead")) {
} else if (name == QLatin1String(Protocol::QProcessSignalReadyRead)) {
emit readyRead();
} else if (name == QLatin1String("stateChanged")) {
const QProcess::ProcessState newState =
static_cast<QProcess::ProcessState> (receivedSignals.takeFirst().toInt());
emit stateChanged(newState);
} else if (name == QLatin1String("finished")) {
const int exitCode = receivedSignals.takeFirst().toInt();
const QProcess::ExitStatus exitStatus =
static_cast<QProcess::ExitStatus> (receivedSignals.takeFirst().toInt());
emit finished(exitCode);
emit finished(exitCode, exitStatus);
} else if (name == QLatin1String(Protocol::QProcessSignalStateChanged)) {
emit stateChanged(static_cast<QProcess::ProcessState> (receivedSignals.takeFirst()
.toInt()));
} else if (name == QLatin1String(Protocol::QProcessSignalFinished)) {
emit finished(receivedSignals.first().toInt());
emit finished(receivedSignals.takeFirst().toInt(),
static_cast<QProcess::ExitStatus> (receivedSignals.takeFirst().toInt()));
}
}
m_lock.unlock();
}
bool startDetached(const QString &program, const QStringList &args, const QString &workingDirectory,
qint64 *pid);
bool QProcessWrapper::startDetached(const QString &program, const QStringList &arguments,
const QString &workingDirectory, qint64 *pid)
{
QProcessWrapper w;
if (w.d->createSocket()) {
const QPair<bool, qint64> result = callRemoteMethod<QPair<bool, qint64> >(w.d->stream,
QLatin1String("QProcess::startDetached"), program, arguments, workingDirectory);
if (w.connectToServer()) {
const QPair<bool, qint64> result =
w.callRemoteMethod<QPair<bool, qint64> >(QLatin1String(Protocol::QProcessStartDetached),
program, arguments, workingDirectory);
if (pid != 0)
*pid = result.second;
w.processSignals();
return result.first;
}
return ::startDetached(program, arguments, workingDirectory, pid);
return QInstaller::startDetached(program, arguments, workingDirectory, pid);
}
bool QProcessWrapper::startDetached(const QString &program, const QStringList &arguments)
@ -222,12 +146,13 @@ bool QProcessWrapper::startDetached(const QString &program)
void QProcessWrapper::setProcessChannelMode(QProcessWrapper::ProcessChannelMode mode)
{
const Private::TimerBlocker blocker(this);
if (d->createSocket()) {
callRemoteVoidMethod(d->stream, QLatin1String("QProcess::setProcessChannelMode"),
static_cast<QProcess::ProcessChannelMode>(mode));
if (connectToServer()) {
m_lock.lockForWrite();
callRemoteMethod(QLatin1String(Protocol::QProcessSetProcessChannelMode),
static_cast<QProcess::ProcessChannelMode>(mode), dummy);
m_lock.unlock();
} else {
d->process.setProcessChannelMode(static_cast<QProcess::ProcessChannelMode>(mode));
process.setProcessChannelMode(static_cast<QProcess::ProcessChannelMode>(mode));
}
}
@ -246,193 +171,264 @@ void QProcessWrapper::cancel()
void QProcessWrapper::setReadChannel(QProcessWrapper::ProcessChannel chan)
{
const Private::TimerBlocker blocker(this);
if (d->createSocket()) {
callRemoteVoidMethod(d->stream, QLatin1String("QProcess::setReadChannel"),
static_cast<QProcess::ProcessChannel>(chan));
if (connectToServer()) {
m_lock.lockForWrite();
callRemoteMethod(QLatin1String(Protocol::QProcessSetReadChannel),
static_cast<QProcess::ProcessChannel>(chan), dummy);
m_lock.unlock();
} else {
d->process.setReadChannel(static_cast<QProcess::ProcessChannel>(chan));
process.setReadChannel(static_cast<QProcess::ProcessChannel>(chan));
}
}
bool QProcessWrapper::waitForFinished(int msecs)
{
const Private::TimerBlocker blocker(this);
if (d->createSocket())
return callRemoteMethod<bool>(d->stream, QLatin1String("QProcess::waitForFinished"), msecs);
return d->process.waitForFinished(msecs);
if (connectToServer()) {
m_lock.lockForWrite();
const bool value = callRemoteMethod<bool>(QLatin1String(Protocol::QProcessWaitForFinished),
msecs);
m_lock.unlock();
return value;
}
return process.waitForFinished(msecs);
}
bool QProcessWrapper::waitForStarted(int msecs)
{
const Private::TimerBlocker blocker(this);
if (d->createSocket())
return callRemoteMethod<bool>(d->stream, QLatin1String("QProcess::waitForStarted"), msecs);
return d->process.waitForStarted(msecs);
if (connectToServer()) {
m_lock.lockForWrite();
const bool value = callRemoteMethod<bool>(QLatin1String(Protocol::QProcessWaitForStarted),
msecs);
m_lock.unlock();
return value;
}
return process.waitForStarted(msecs);
}
qint64 QProcessWrapper::write(const QByteArray &data)
{
const Private::TimerBlocker blocker(this);
if (d->createSocket())
return callRemoteMethod<qint64>(d->stream, QLatin1String("QProcess::write"), data);
return d->process.write(data);
if (connectToServer()) {
m_lock.lockForWrite();
const qint64 value = callRemoteMethod<qint64>(QLatin1String(Protocol::QProcessWrite), data);
m_lock.unlock();
return value;
}
return process.write(data);
}
void QProcessWrapper::closeWriteChannel()
{
const Private::TimerBlocker blocker(this);
if (d->createSocket())
callRemoteVoidMethod<void>(d->stream, QLatin1String("QProcess::closeWriteChannel"));
else
d->process.closeWriteChannel();
if (connectToServer()) {
m_lock.lockForWrite();
callRemoteMethod(QLatin1String(Protocol::QProcessCloseWriteChannel));
m_lock.unlock();
} else {
process.closeWriteChannel();
}
}
int QProcessWrapper::exitCode() const
{
const Private::TimerBlocker blocker(this);
if (d->createSocket())
return callRemoteMethod<int>(d->stream, QLatin1String("QProcess::exitCode"));
return static_cast<int>(d->process.exitCode());
if ((const_cast<QProcessWrapper *>(this))->connectToServer()) {
m_lock.lockForWrite();
const int value = callRemoteMethod<qint32>(QLatin1String(Protocol::QProcessExitCode));
m_lock.unlock();
return value;
}
return static_cast<int>(process.exitCode());
}
QProcessWrapper::ExitStatus QProcessWrapper::exitStatus() const
{
const Private::TimerBlocker blocker(this);
if (d->createSocket())
return callRemoteMethod<QProcessWrapper::ExitStatus>(d->stream, QLatin1String("QProcess::exitStatus"));
return static_cast<QProcessWrapper::ExitStatus>(d->process.exitStatus());
if ((const_cast<QProcessWrapper *>(this))->connectToServer()) {
m_lock.lockForWrite();
const int status = callRemoteMethod<qint32>(QLatin1String(Protocol::QProcessExitStatus));
m_lock.unlock();
return static_cast<QProcessWrapper::ExitStatus>(status);
}
return static_cast<QProcessWrapper::ExitStatus>(process.exitStatus());
}
void QProcessWrapper::kill()
{
const Private::TimerBlocker blocker(this);
if (d->createSocket())
callRemoteVoidMethod<void>(d->stream, QLatin1String("QProcess::kill"));
else
d->process.kill();
if (connectToServer()) {
m_lock.lockForWrite();
callRemoteMethod(QLatin1String(Protocol::QProcessKill));
m_lock.unlock();
} else {
process.kill();
}
}
QByteArray QProcessWrapper::readAll()
{
const Private::TimerBlocker blocker(this);
if (d->createSocket())
return callRemoteMethod<QByteArray>(d->stream, QLatin1String("QProcess::readAll"));
return d->process.readAll();
if (connectToServer()) {
m_lock.lockForWrite();
const QByteArray ba = callRemoteMethod<QByteArray>(QLatin1String(Protocol::QProcessReadAll));
m_lock.unlock();
return ba;
}
return process.readAll();
}
QByteArray QProcessWrapper::readAllStandardOutput()
{
const Private::TimerBlocker blocker(this);
if (d->createSocket())
return callRemoteMethod<QByteArray>(d->stream, QLatin1String("QProcess::readAllStandardOutput"));
return d->process.readAllStandardOutput();
if (connectToServer()) {
m_lock.lockForWrite();
const QByteArray ba =
callRemoteMethod<QByteArray>(QLatin1String(Protocol::QProcessReadAllStandardOutput));
m_lock.unlock();
return ba;
}
return process.readAllStandardOutput();
}
QByteArray QProcessWrapper::readAllStandardError()
{
const Private::TimerBlocker blocker(this);
if (d->createSocket())
return callRemoteMethod<QByteArray>(d->stream, QLatin1String("QProcess::readAllStandardError"));
return d->process.readAllStandardError();
if (connectToServer()) {
m_lock.lockForWrite();
const QByteArray ba =
callRemoteMethod<QByteArray>(QLatin1String(Protocol::QProcessReadAllStandardError));
m_lock.unlock();
return ba;
}
return process.readAllStandardError();
}
void QProcessWrapper::start(const QString &param1, const QStringList &param2, QIODevice::OpenMode param3)
void QProcessWrapper::start(const QString &param1, const QStringList &param2,
QIODevice::OpenMode param3)
{
const Private::TimerBlocker blocker(this);
if (d->createSocket())
callRemoteVoidMethod(d->stream, QLatin1String("QProcess::start"), param1, param2, param3);
else
d->process.start(param1, param2, param3);
if (connectToServer()) {
m_lock.lockForWrite();
callRemoteMethod(QLatin1String(Protocol::QProcessStart3Arg), param1, param2, param3);
m_lock.unlock();
} else {
process.start(param1, param2, param3);
}
}
void QProcessWrapper::start(const QString &param1)
void QProcessWrapper::start(const QString &param1, QIODevice::OpenMode param2)
{
const Private::TimerBlocker blocker(this);
if (d->createSocket())
callRemoteVoidMethod(d->stream, QLatin1String("QProcess::start"), param1);
else
d->process.start(param1);
if (connectToServer()) {
m_lock.lockForWrite();
callRemoteMethod(QLatin1String(Protocol::QProcessStart2Arg), param1, param2);
m_lock.unlock();
} else {
process.start(param1, param2);
}
}
QProcessWrapper::ProcessState QProcessWrapper::state() const
{
const Private::TimerBlocker blocker(this);
if (d->createSocket())
return callRemoteMethod<QProcessWrapper::ProcessState>(d->stream, QLatin1String("QProcess::state"));
return static_cast<QProcessWrapper::ProcessState>(d->process.state());
if ((const_cast<QProcessWrapper *>(this))->connectToServer()) {
m_lock.lockForWrite();
const int state = callRemoteMethod<qint32>(QLatin1String(Protocol::QProcessState));
m_lock.unlock();
return static_cast<QProcessWrapper::ProcessState>(state);
}
return static_cast<QProcessWrapper::ProcessState>(process.state());
}
void QProcessWrapper::terminate()
{
const Private::TimerBlocker blocker(this);
if (d->createSocket())
callRemoteVoidMethod<void>(d->stream, QLatin1String("QProcess::terminate"));
else
d->process.terminate();
if (connectToServer()) {
m_lock.lockForWrite();
callRemoteMethod(QLatin1String(Protocol::QProcessTerminate));
m_lock.unlock();
} else {
process.terminate();
}
}
QProcessWrapper::ProcessChannel QProcessWrapper::readChannel() const
{
const Private::TimerBlocker blocker(this);
if (d->createSocket()) {
return callRemoteMethod<QProcessWrapper::ProcessChannel>(d->stream,
QLatin1String("QProcess::readChannel"));
if ((const_cast<QProcessWrapper *>(this))->connectToServer()) {
m_lock.lockForWrite();
const int channel = callRemoteMethod<qint32>(QLatin1String(Protocol::QProcessReadChannel));
m_lock.unlock();
return static_cast<QProcessWrapper::ProcessChannel>(channel);
}
return static_cast<QProcessWrapper::ProcessChannel>(d->process.readChannel());
return static_cast<QProcessWrapper::ProcessChannel>(process.readChannel());
}
QProcessWrapper::ProcessChannelMode QProcessWrapper::processChannelMode() const
{
const Private::TimerBlocker blocker(this);
if (d->createSocket()) {
return callRemoteMethod<QProcessWrapper::ProcessChannelMode>(d->stream,
QLatin1String("QProcess::processChannelMode"));
if ((const_cast<QProcessWrapper *>(this))->connectToServer()) {
m_lock.lockForWrite();
const int mode = callRemoteMethod<qint32>(QLatin1String(Protocol::QProcessProcessChannelMode));
m_lock.unlock();
return static_cast<QProcessWrapper::ProcessChannelMode>(mode);
}
return static_cast<QProcessWrapper::ProcessChannelMode>(d->process.processChannelMode());
return static_cast<QProcessWrapper::ProcessChannelMode>(process.processChannelMode());
}
QString QProcessWrapper::workingDirectory() const
{
const Private::TimerBlocker blocker(this);
if (d->createSocket())
return callRemoteMethod<QString>(d->stream, QLatin1String("QProcess::workingDirectory"));
return static_cast<QString>(d->process.workingDirectory());
if ((const_cast<QProcessWrapper *>(this))->connectToServer()) {
m_lock.lockForWrite();
const QString dir = callRemoteMethod<QString>(QLatin1String(Protocol::QProcessWorkingDirectory));
m_lock.unlock();
return dir;
}
return static_cast<QString>(process.workingDirectory());
}
QString QProcessWrapper::errorString() const
{
const Private::TimerBlocker blocker(this);
if (d->createSocket())
return callRemoteMethod<QString>(d->stream, QLatin1String("QProcess::errorString"));
return static_cast<QString>(d->process.errorString());
if ((const_cast<QProcessWrapper *>(this))->connectToServer()) {
m_lock.lockForWrite();
const QString error = callRemoteMethod<QString>(QLatin1String(Protocol::QProcessErrorString));
m_lock.unlock();
return error;
}
return static_cast<QString>(process.errorString());
}
QStringList QProcessWrapper::environment() const
{
if ((const_cast<QProcessWrapper *>(this))->connectToServer()) {
m_lock.lockForWrite();
const QStringList env =
callRemoteMethod<QStringList>(QLatin1String(Protocol::QProcessEnvironment));
m_lock.unlock();
return env;
}
return process.environment();
}
void QProcessWrapper::setEnvironment(const QStringList &param1)
{
const Private::TimerBlocker blocker(this);
if (d->createSocket())
callRemoteVoidMethod(d->stream, QLatin1String("QProcess::setEnvironment"), param1);
else
d->process.setEnvironment(param1);
if (connectToServer()) {
m_lock.lockForWrite();
callRemoteMethod(QLatin1String(Protocol::QProcessSetEnvironment), param1, dummy);
m_lock.unlock();
} else {
process.setEnvironment(param1);
}
}
#ifdef Q_OS_WIN
void QProcessWrapper::setNativeArguments(const QString &param1)
{
const Private::TimerBlocker blocker(this);
if (d->createSocket())
callRemoteVoidMethod(d->stream, QLatin1String("QProcess::setNativeArguments"), param1);
else
d->process.setNativeArguments(param1);
if (connectToServer()) {
m_lock.lockForWrite();
callRemoteMethod(QLatin1String(Protocol::QProcessSetNativeArguments), param1, dummy);
m_lock.unlock();
} else {
process.setNativeArguments(param1);
}
}
#endif
void QProcessWrapper::setWorkingDirectory(const QString &param1)
{
const Private::TimerBlocker blocker(this);
if (d->createSocket())
callRemoteVoidMethod(d->stream, QLatin1String("QProcess::setWorkingDirectory"), param1);
else
d->process.setWorkingDirectory(param1);
if (connectToServer()) {
m_lock.lockForWrite();
callRemoteMethod(QLatin1String(Protocol::QProcessSetWorkingDirectory), param1, dummy);
m_lock.unlock();
} else {
process.setWorkingDirectory(param1);
}
}
} // namespace QInstaller

View File

@ -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.
@ -42,15 +42,20 @@
#ifndef QPROCESSWRAPPER_H
#define QPROCESSWRAPPER_H
#include <installer_global.h>
#include "remoteobject.h"
#include<QtCore/QIODevice>
#include<QtCore/QObject>
#include<QtCore/QProcess>
#include <QIODevice>
#include <QProcess>
#include <QReadWriteLock>
#include <QTimer>
class INSTALLER_EXPORT QProcessWrapper : public QObject
namespace QInstaller {
class INSTALLER_EXPORT QProcessWrapper : public RemoteObject
{
Q_OBJECT
Q_DISABLE_COPY(QProcessWrapper)
public:
enum ProcessState {
NotRunning,
@ -77,36 +82,43 @@ public:
explicit QProcessWrapper(QObject *parent = 0);
~QProcessWrapper();
void closeWriteChannel();
int exitCode() const;
ProcessState state() const;
ExitStatus exitStatus() const;
QString workingDirectory() const;
void setWorkingDirectory(const QString &dir);
QStringList environment() const;
void setEnvironment(const QStringList &environment);
QProcessWrapper::ProcessChannel readChannel() const;
void setReadChannel(QProcessWrapper::ProcessChannel channel);
QProcessWrapper::ProcessChannelMode processChannelMode() const;
void setProcessChannelMode(QProcessWrapper::ProcessChannelMode channel);
bool waitForStarted(int msecs = 30000);
bool waitForFinished(int msecs = 30000);
void start(const QString &program, const QStringList &arguments,
QIODevice::OpenMode mode = QIODevice::ReadWrite);
void start(const QString &program, QIODevice::OpenMode mode = QIODevice::ReadWrite);
void closeWriteChannel();
void kill();
void terminate();
QByteArray readAll();
QByteArray readAllStandardOutput();
QByteArray readAllStandardError();
void setWorkingDirectory(const QString &dir);
void start(const QString &program);
void start(const QString &program, const QStringList &arguments,
QIODevice::OpenMode mode = QIODevice::ReadWrite);
static bool startDetached(const QString &program);
static bool startDetached(const QString &program, const QStringList &arguments);
static bool startDetached(const QString &program, const QStringList &arguments,
const QString &workingDirectory, qint64 *pid = 0);
ProcessState state() const;
bool waitForStarted(int msecs = 30000);
bool waitForFinished(int msecs = 30000);
void setEnvironment(const QStringList &environment);
QString workingDirectory() const;
QString errorString() const;
qint64 write(const QByteArray &byteArray);
QProcessWrapper::ProcessChannel readChannel() const;
void setReadChannel(QProcessWrapper::ProcessChannel channel);
QProcessWrapper::ProcessChannelMode processChannelMode() const;
void setProcessChannelMode(QProcessWrapper::ProcessChannelMode channel);
#ifdef Q_OS_WIN
void setNativeArguments(const QString &arguments);
#endif
@ -127,12 +139,19 @@ Q_SIGNALS:
public Q_SLOTS:
void cancel();
protected:
void timerEvent(QTimerEvent *event);
private slots:
void processSignals();
private:
class Private;
Private *d;
QTimer m_timer;
QProcess process;
mutable QReadWriteLock m_lock;
};
} // namespace QInstaller
Q_DECLARE_METATYPE(QProcess::ExitStatus)
Q_DECLARE_METATYPE(QProcess::ProcessError)
Q_DECLARE_METATYPE(QProcess::ProcessState)
#endif // QPROCESSWRAPPER_H

View File

@ -41,13 +41,10 @@
#include "qsettingswrapper.h"
#include "fsengineclient.h"
#include "templates.cpp"
#include <QSettings>
#include <QStringList>
#include <QtCore/QSettings>
#include <QtCore/QThread>
#include <QtNetwork/QTcpSocket>
namespace QInstaller {
// -- QSettingsWrapper::Private
@ -56,320 +53,286 @@ class QSettingsWrapper::Private
{
public:
Private(const QString &organization, const QString &application)
: native(true)
: m_native(true)
, m_application(application)
, m_organization(organization)
, m_scope(QSettings::UserScope)
, m_format(QSettings::NativeFormat)
, settings(organization, application)
, socket(0)
{
}
Private(QSettings::Scope scope, const QString &organization, const QString &application)
: native(true)
: m_native(true)
, m_application(application)
, m_organization(organization)
, m_scope(scope)
, m_format(QSettings::NativeFormat)
, settings(scope, organization, application)
, socket(0)
{
}
Private(QSettings::Format format, QSettings::Scope scope, const QString &organization,
const QString &application)
: native(format == QSettings::NativeFormat)
: m_native(format == QSettings::NativeFormat)
, m_application(application)
, m_organization(organization)
, m_scope(scope)
, m_format(format)
, settings(format, scope, organization, application)
, socket(0)
{
}
Private(const QString &fileName, QSettings::Format format)
: native(format == QSettings::NativeFormat)
, fileName(fileName)
: m_native(format == QSettings::NativeFormat)
, m_filename(fileName)
, settings(fileName, format)
, socket(0)
{
m_format = format;
m_scope = settings.scope();
m_application = settings.applicationName();
m_organization = settings.organizationName();
}
Private()
: native(true)
, socket(0)
{
}
bool createSocket()
{
if (!native || !FSEngineClientHandler::instance().isActive())
return false;
if (socket != 0 && socket->state() == static_cast<int>(QAbstractSocket::ConnectedState))
return true;
if (socket != 0)
delete socket;
socket = new QTcpSocket;
if (!FSEngineClientHandler::instance().connect(socket))
return false;
stream.setDevice(socket);
stream.setVersion(QDataStream::Qt_4_2);
stream << QString::fromLatin1("createQSettings");
stream << this->fileName;
socket->flush();
stream.device()->waitForReadyRead(-1);
quint32 test;
stream >> test;
stream.device()->readAll();
return true;
}
const bool native;
const QString fileName;
bool m_native;
QSettings settings;
mutable QTcpSocket *socket;
mutable QDataStream stream;
QString m_filename;
QString m_application;
QString m_organization;
QSettings::Scope m_scope;
QSettings::Format m_format;
};
// -- QSettingsWrapper
QSettingsWrapper::QSettingsWrapper(const QString &organization, const QString &application, QObject *parent)
: QObject(parent)
QSettingsWrapper::QSettingsWrapper(const QString &organization, const QString &application,
QObject *parent)
: RemoteObject(QLatin1String(Protocol::QSettings), parent)
, d(new Private(organization, application))
{
}
QSettingsWrapper::QSettingsWrapper(QSettingsWrapper::Scope scope, const QString &organization,
const QString &application, QObject *parent)
: QObject(parent)
: RemoteObject(QLatin1String(Protocol::QSettings), parent)
, d(new Private(static_cast<QSettings::Scope>(scope), organization, application))
{
}
QSettingsWrapper::QSettingsWrapper(QSettingsWrapper::Format format, QSettingsWrapper::Scope scope,
const QString &organization, const QString &application, QObject *parent)
: QObject(parent)
: RemoteObject(QLatin1String(Protocol::QSettings), parent)
, d(new Private(static_cast<QSettings::Format>(format), static_cast<QSettings::Scope> (scope),
organization, application))
{
}
QSettingsWrapper::QSettingsWrapper(const QString &fileName, QSettingsWrapper::Format format, QObject *parent)
: QObject(parent)
QSettingsWrapper::QSettingsWrapper(const QString &fileName, QSettingsWrapper::Format format,
QObject *parent)
: RemoteObject(QLatin1String(Protocol::QSettings), parent)
, d(new Private(fileName, static_cast<QSettings::Format>(format)))
{
}
QSettingsWrapper::QSettingsWrapper(QObject *parent)
: QObject(parent)
, d(new Private)
{
}
QSettingsWrapper::~QSettingsWrapper()
{
if (d->socket != 0) {
d->stream << QString::fromLatin1("destroyQSettings");
d->socket->flush();
quint32 result;
d->stream >> result;
if (QThread::currentThread() == d->socket->thread()) {
d->socket->close();
delete d->socket;
} else {
d->socket->deleteLater();
}
}
delete d;
}
QStringList QSettingsWrapper::allKeys() const
{
if (d->createSocket())
return callRemoteMethod<QStringList>(d->stream, QLatin1String("QSettings::allKeys"));
return static_cast<QStringList>(d->settings.allKeys());
if (createSocket())
return callRemoteMethod<QStringList>(QLatin1String(Protocol::QSettingsAllKeys));
return d->settings.allKeys();
}
QString QSettingsWrapper::applicationName() const
{
if (d->createSocket())
return callRemoteMethod<QString>(d->stream, QLatin1String("QSettings::applicationName"));
return static_cast<QString>(d->settings.applicationName());
if (createSocket())
return callRemoteMethod<QString>(QLatin1String(Protocol::QSettingsApplicationName));
return d->settings.applicationName();
}
void QSettingsWrapper::beginGroup(const QString &param1)
{
if (d->createSocket())
callRemoteVoidMethod(d->stream, QLatin1String("QSettings::beginGroup"), param1);
if (createSocket())
callRemoteMethod(QLatin1String(Protocol::QSettingsBeginGroup), param1, dummy);
else
d->settings.beginGroup(param1);
}
int QSettingsWrapper::beginReadArray(const QString &param1)
{
if (d->createSocket())
return callRemoteMethod<int>(d->stream, QLatin1String("QSettings::beginReadArray"), param1);
if (createSocket())
return callRemoteMethod<int>(QLatin1String(Protocol::QSettingsBeginReadArray), param1);
return d->settings.beginReadArray(param1);
}
void QSettingsWrapper::beginWriteArray(const QString &param1, int param2)
{
if (d->createSocket())
callRemoteVoidMethod(d->stream, QLatin1String("QSettings::beginWriteArray"), param1, param2);
if (createSocket())
callRemoteMethod(QLatin1String(Protocol::QSettingsBeginWriteArray), param1, param2);
else
d->settings.beginWriteArray(param1, param2);
}
QStringList QSettingsWrapper::childGroups() const
{
if (d->createSocket())
return callRemoteMethod<QStringList>(d->stream, QLatin1String("QSettings::childGroups"));
return static_cast<QStringList>(d->settings.childGroups());
if (createSocket())
return callRemoteMethod<QStringList>(QLatin1String(Protocol::QSettingsChildGroups));
return d->settings.childGroups();
}
QStringList QSettingsWrapper::childKeys() const
{
if (d->createSocket())
return callRemoteMethod<QStringList>(d->stream, QLatin1String("QSettings::childKeys"));
return static_cast<QStringList>(d->settings.childKeys());
if (createSocket())
return callRemoteMethod<QStringList>(QLatin1String(Protocol::QSettingsChildKeys));
return d->settings.childKeys();
}
void QSettingsWrapper::clear()
{
if (d->createSocket())
callRemoteVoidMethod<void>(d->stream, QLatin1String("QSettings::clear"));
if (createSocket())
callRemoteMethod(QLatin1String(Protocol::QSettingsClear));
else d->settings.clear();
}
bool QSettingsWrapper::contains(const QString &param1) const
{
if (d->createSocket())
return callRemoteMethod<bool>(d->stream, QLatin1String("QSettings::contains"), param1);
if (createSocket())
return callRemoteMethod<bool>(QLatin1String(Protocol::QSettingsContains), param1);
return d->settings.contains(param1);
}
void QSettingsWrapper::endArray()
{
if (d->createSocket())
callRemoteVoidMethod<void>(d->stream, QLatin1String("QSettings::endArray"));
if (createSocket())
callRemoteMethod(QLatin1String(Protocol::QSettingsEndArray));
else
d->settings.endArray();
}
void QSettingsWrapper::endGroup()
{
if (d->createSocket())
callRemoteVoidMethod<void>(d->stream, QLatin1String("QSettings::endGroup"));
if (createSocket())
callRemoteMethod(QLatin1String(Protocol::QSettingsEndGroup));
else
d->settings.endGroup();
}
bool QSettingsWrapper::fallbacksEnabled() const
{
if (d->createSocket())
return callRemoteMethod<bool>(d->stream, QLatin1String("QSettings::fallbacksEnabled"));
return static_cast<bool>(d->settings.fallbacksEnabled());
if (createSocket())
return callRemoteMethod<bool>(QLatin1String(Protocol::QSettingsFallbacksEnabled));
return d->settings.fallbacksEnabled();
}
QString QSettingsWrapper::fileName() const
{
if (d->createSocket())
return callRemoteMethod<QString>(d->stream, QLatin1String("QSettings::fileName"));
return static_cast<QString>(d->settings.fileName());
if (createSocket())
return callRemoteMethod<QString>(QLatin1String(Protocol::QSettingsFileName));
return d->settings.fileName();
}
QSettingsWrapper::Format QSettingsWrapper::format() const
{
// No need to talk to the server, we've setup the local settings object the same way.
return static_cast<QSettingsWrapper::Format>(d->settings.format());
}
QString QSettingsWrapper::group() const
{
if (d->createSocket())
return callRemoteMethod<QString>(d->stream, QLatin1String("QSettings::group"));
return static_cast<QString>(d->settings.group());
}
QTextCodec* QSettingsWrapper::iniCodec() const
{
return d->settings.iniCodec();
if (createSocket())
return callRemoteMethod<QString>(QLatin1String(Protocol::QSettingsGroup));
return d->settings.group();
}
bool QSettingsWrapper::isWritable() const
{
if (d->createSocket())
return callRemoteMethod<bool>(d->stream, QLatin1String("QSettings::isWritable"));
return static_cast<bool>(d->settings.isWritable());
if (createSocket())
return callRemoteMethod<bool>(QLatin1String(Protocol::QSettingsIsWritable));
return d->settings.isWritable();
}
QString QSettingsWrapper::organizationName() const
{
if (d->createSocket())
return callRemoteMethod<QString>(d->stream, QLatin1String("QSettings::organizationName"));
return static_cast<QString>(d->settings.organizationName());
if (createSocket())
return callRemoteMethod<QString>(QLatin1String(Protocol::QSettingsOrganizationName));
return d->settings.organizationName();
}
void QSettingsWrapper::remove(const QString &param1)
{
if (d->createSocket())
callRemoteVoidMethod(d->stream, QLatin1String("QSettings::remove"), param1);
else d->settings.remove(param1);
if (createSocket())
callRemoteMethod(QLatin1String(Protocol::QSettingsRemove), param1, dummy);
else
d->settings.remove(param1);
}
QSettingsWrapper::Scope QSettingsWrapper::scope() const
{
// No need to talk to the server, we've setup the local settings object the same way.
return static_cast<QSettingsWrapper::Scope>(d->settings.scope());
}
void QSettingsWrapper::setArrayIndex(int param1)
{
if (d->createSocket())
callRemoteVoidMethod(d->stream, QLatin1String("QSettings::setArrayIndex"), param1);
if (createSocket())
callRemoteMethod(QLatin1String(Protocol::QSettingsSetArrayIndex), param1, dummy);
else
d->settings.setArrayIndex(param1);
}
void QSettingsWrapper::setFallbacksEnabled(bool param1)
{
if (d->createSocket())
callRemoteVoidMethod(d->stream, QLatin1String("QSettings::setFallbacksEnabled"), param1);
if (createSocket())
callRemoteMethod(QLatin1String(Protocol::QSettingsSetFallbacksEnabled), param1, dummy);
else
d->settings.setFallbacksEnabled(param1);
}
void QSettingsWrapper::setIniCodec(QTextCodec *codec)
{
d->settings.setIniCodec(codec);
}
void QSettingsWrapper::setIniCodec(const char *codecName)
{
d->settings.setIniCodec(codecName);
}
void QSettingsWrapper::setValue(const QString &param1, const QVariant &param2)
{
if (d->createSocket())
callRemoteVoidMethod(d->stream, QLatin1String("QSettings::setValue"), param1, param2);
if (createSocket())
callRemoteMethod(QLatin1String(Protocol::QSettingsSetValue), param1, param2);
else
d->settings.setValue(param1, param2);
}
QSettingsWrapper::Status QSettingsWrapper::status() const
{
if (d->createSocket())
return callRemoteMethod<QSettingsWrapper::Status>(d->stream, QLatin1String("QSettings::status"));
if (createSocket()) {
return static_cast<QSettingsWrapper::Status>
(callRemoteMethod<int>(QLatin1String(Protocol::QSettingsStatus)));
}
return static_cast<QSettingsWrapper::Status>(d->settings.status());
}
void QSettingsWrapper::sync()
{
if (d->createSocket())
callRemoteVoidMethod<void>(d->stream, QLatin1String("QSettings::sync"));
if (createSocket())
callRemoteMethod(QLatin1String(Protocol::QSettingsSync));
else
d->settings.sync();
}
QVariant QSettingsWrapper::value(const QString &param1, const QVariant &param2) const
{
if (d->createSocket())
return callRemoteMethod<QVariant>(d->stream, QLatin1String("QSettings::value"), param1, param2);
if (createSocket())
return callRemoteMethod<QVariant>(QLatin1String(Protocol::QSettingsValue), param1, param2);
return d->settings.value(param1, param2);
}
// -- private
bool QSettingsWrapper::createSocket() const
{
if (!d->m_native)
return false;
return (const_cast<QSettingsWrapper *>(this))->connectToServer(QVariantList()
<< d->m_application << d->m_organization << d->m_scope << d->m_format << d->m_filename);
}
} // namespace QInstaller

View File

@ -42,26 +42,29 @@
#ifndef QSETTINGSWRAPPER_H
#define QSETTINGSWRAPPER_H
#include <installer_global.h>
#include "protocol.h"
#include "remoteobject.h"
#include <QtCore/QObject>
#include <QtCore/QVariant>
#include <QVariant>
class INSTALLER_EXPORT QSettingsWrapper : public QObject
namespace QInstaller {
class INSTALLER_EXPORT QSettingsWrapper : public RemoteObject
{
Q_OBJECT
Q_DISABLE_COPY(QSettingsWrapper)
public:
enum Status {
NoError = 0,
AccessError,
FormatError
};
enum Format {
NativeFormat,
IniFormat,
InvalidFormat
};
enum Status {
NoError,
AccessError,
FormatError
InvalidFormat = 16
};
enum Scope {
@ -69,48 +72,85 @@ public:
SystemScope
};
explicit QSettingsWrapper(QObject *parent = 0);
explicit QSettingsWrapper(const QString &organization, const QString &application = QString(),
QObject *parent = 0);
QSettingsWrapper(const QString &fileName, QSettingsWrapper::Format format, QObject *parent = 0);
QSettingsWrapper(QSettingsWrapper::Scope scope, const QString &organization,
explicit QSettingsWrapper(const QString &organization,
const QString &application = QString(), QObject *parent = 0);
QSettingsWrapper(QSettingsWrapper::Format format, QSettingsWrapper::Scope scope,
const QString &organization, const QString &application = QString(), QObject *parent = 0);
QSettingsWrapper(Scope scope, const QString &organization,
const QString &application = QString(), QObject *parent = 0);
QSettingsWrapper(Format format, Scope scope, const QString &organization,
const QString &application = QString(), QObject *parent = 0);
QSettingsWrapper(const QString &fileName, Format format, QObject *parent = 0);
~QSettingsWrapper();
QStringList allKeys() const;
QString applicationName() const;
void clear();
void sync();
Status status() const;
void beginGroup(const QString &prefix);
void endGroup();
QString group() const;
int beginReadArray(const QString &prefix);
void beginWriteArray(const QString &prefix, int size = -1);
QStringList childGroups() const;
QStringList childKeys() const;
void clear();
bool contains(const QString &key) const;
void endArray();
void endGroup();
bool fallbacksEnabled() const;
QString fileName() const;
QSettingsWrapper::Format format() const;
QString group() const;
QTextCodec* iniCodec() const;
bool isWritable() const;
QString organizationName() const;
void remove(const QString &key);
QSettingsWrapper::Scope scope() const;
void setArrayIndex(int i);
void setFallbacksEnabled(bool b);
void setIniCodec(QTextCodec *codec);
void setIniCodec(const char *codecName);
QStringList allKeys() const;
QStringList childKeys() const;
QStringList childGroups() const;
bool isWritable() const;
void setValue(const QString &key, const QVariant &value);
QSettingsWrapper::Status status() const;
void sync();
QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const;
void remove(const QString &key);
bool contains(const QString &key) const;
void setFallbacksEnabled(bool b);
bool fallbacksEnabled() const;
QString fileName() const;
Format format() const;
Scope scope() const;
QString organizationName() const;
QString applicationName() const;
private:
bool createSocket() const;
private: // we cannot support the following functionality
explicit QSettingsWrapper(QObject *parent = 0)
: RemoteObject(QLatin1String(Protocol::QSettings), parent)
{}
void setIniCodec(QTextCodec * /*codec*/);
void setIniCodec(const char * /*codecName*/);
QTextCodec *iniCodec() const { return 0; }
static void setDefaultFormat(Format /*format*/);
static Format defaultFormat() { return NativeFormat; }
static void setSystemIniPath(const QString & /*dir*/);
static void setUserIniPath(const QString & /*dir*/);
static void setPath(Format /*format*/, Scope /*scope*/, const QString & /*path*/);
typedef QMap<QString, QVariant> SettingsMap;
typedef bool(*ReadFunc)(QIODevice &device, SettingsMap &map);
typedef bool(*WriteFunc)(QIODevice &device, const SettingsMap &map);
static Format registerFormat(const QString &extension, ReadFunc readFunc, WriteFunc writeFunc,
Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive)
{
Q_UNUSED(extension)
Q_UNUSED(readFunc)
Q_UNUSED(writeFunc)
Q_UNUSED(caseSensitivity)
return NativeFormat;
}
private:
class Private;
Private *d;
};
} // namespace QInstaller
#endif // QSETTINGSWRAPPER_H

View File

@ -1,185 +0,0 @@
/**************************************************************************
**
** Copyright (C) 2012-2013 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<QtCore/QIODevice>
template<typename T>
QDataStream &operator>>(QDataStream &stream, T &state)
{
int s;
stream >> s;
state = static_cast<T> (s);
return stream;
}
template<typename UNUSED>
void callRemoteVoidMethod(QDataStream &stream, const QString &name)
{
stream.device()->readAll();
stream << name;
stream.device()->waitForBytesWritten(-1);
if (!stream.device()->bytesAvailable())
stream.device()->waitForReadyRead(-1);
quint32 test;
stream >> test;
stream.device()->readAll();
return;
}
template<typename T>
void callRemoteVoidMethod(QDataStream & stream, const QString &name, const T &param1)
{
stream.device()->readAll();
stream << name;
stream << param1;
stream.device()->waitForBytesWritten(-1);
if (!stream.device()->bytesAvailable())
stream.device()->waitForReadyRead(-1);
quint32 test;
stream >> test;
stream.device()->readAll();
return;
}
template<typename T1, typename T2>
void callRemoteVoidMethod(QDataStream &stream, const QString &name, const T1 &param1, const T2 &param2)
{
stream.device()->readAll();
stream << name;
stream << param1;
stream << param2;
stream.device()->waitForBytesWritten(-1);
if (!stream.device()->bytesAvailable())
stream.device()->waitForReadyRead(-1);
quint32 test;
stream >> test;
stream.device()->readAll();
return;
}
template<typename T1, typename T2, typename T3>
void callRemoteVoidMethod(QDataStream &stream, const QString &name, const T1 &param1, const T2 &param2,
const T3 & param3)
{
stream.device()->readAll();
stream << name;
stream << param1;
stream << param2;
stream << param3;
stream.device()->waitForBytesWritten(-1);
if (!stream.device()->bytesAvailable())
stream.device()->waitForReadyRead(-1);
quint32 test;
stream >> test;
stream.device()->readAll();
return;
}
template<typename RESULT>
RESULT callRemoteMethod(QDataStream &stream, const QString &name)
{
stream.device()->readAll();
stream << name;
stream.device()->waitForBytesWritten(-1);
if (!stream.device()->bytesAvailable())
stream.device()->waitForReadyRead(-1);
quint32 test;
stream >> test;
RESULT result;
stream >> result;
stream.device()->readAll();
return result;
}
template<typename RESULT, typename T>
RESULT callRemoteMethod(QDataStream &stream, const QString &name, const T &param1)
{
stream.device()->readAll();
stream << name;
stream << param1;
stream.device()->waitForBytesWritten(-1);
if (!stream.device()->bytesAvailable())
stream.device()->waitForReadyRead(-1);
quint32 test;
stream >> test;
RESULT result;
stream >> result;
stream.device()->readAll();
return result;
}
template<typename RESULT, typename T1, typename T2>
RESULT callRemoteMethod(QDataStream &stream, const QString &name, const T1 & param1, const T2 &param2)
{
stream.device()->readAll();
stream << name;
stream << param1;
stream << param2;
stream.device()->waitForBytesWritten(-1);
if (!stream.device()->bytesAvailable())
stream.device()->waitForReadyRead(-1);
quint32 test;
stream >> test;
RESULT result;
stream >> result;
stream.device()->readAll();
return result;
}
template<typename RESULT, typename T1, typename T2, typename T3>
RESULT callRemoteMethod(QDataStream &stream, const QString &name, const T1 &param1, const T2 &param2,
const T3 &param3)
{
stream.device()->readAll();
stream << name;
stream << param1;
stream << param2;
stream << param3;
stream.device()->waitForBytesWritten(-1);
if (!stream.device()->bytesAvailable())
stream.device()->waitForReadyRead(-1);
quint32 test;
stream >> test;
RESULT result;
stream >> result;
stream.device()->readAll();
return result;
}

View File

@ -47,7 +47,7 @@
#include <binaryformat.h>
#include <errors.h>
#include <fileutils.h>
#include <fsengineserver.h>
#include <remoteserver.h>
#include <init.h>
#include <lib7z_facade.h>
#include <operationrunner.h>
@ -163,10 +163,12 @@ int main(int argc, char *argv[])
// this is the FSEngineServer as an admin rights process upon request:
if (args.count() >= 3 && args[1] == QLatin1String("--startserver")) {
SDKApp<QCoreApplication> app(argc, argv);
FSEngineServer* const server = new FSEngineServer(args[2].toInt());
RemoteServer *const server = new RemoteServer();
QObject::connect(server, SIGNAL(destroyed()), &app, SLOT(quit()));
server->init(args[2].toInt(), QHostAddress::LocalHost, RemoteServer::Release);
if (args.count() >= 4)
server->setAuthorizationKey(args[3]);
QObject::connect(server, SIGNAL(destroyed()), &app, SLOT(quit()));
server->start();
return app.exec();
}

View File

@ -0,0 +1,6 @@
include(../../qttest.pri)
QT += network
QT -= gui
SOURCES += tst_clientserver.cpp

View File

@ -0,0 +1,328 @@
/**************************************************************************
**
** 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 <qprocesswrapper.h>
#include <qsettingswrapper.h>
#include <remoteclient.h>
#include <remotefileengine.h>
#include <remoteserver.h>
#include <QHostAddress>
#include <QSettings>
#include <QTcpSocket>
#include <QTemporaryFile>
#include <QTest>
#include <QSignalSpy>
using namespace QInstaller;
class tst_ClientServer : public QObject
{
Q_OBJECT
private slots:
void testServerConnection()
{
RemoteServer server;
server.init(39999, QHostAddress::LocalHost, RemoteServer::Debug);
server.start();
QTcpSocket socket;
socket.connectToHost(QHostAddress::LocalHost, 39999);
QVERIFY2(socket.waitForConnected(), "Could not connect to server.");
}
void testClientConnection()
{
RemoteServer server;
server.init(39999, QHostAddress::LocalHost, RemoteServer::Debug);
server.start();
RemoteClient::instance().init(39999, QHostAddress::LocalHost, RemoteClient::Debug);
QScopedPointer<QTcpSocket> socket(QInstaller::RemoteClient::instance().connect());
QVERIFY2(!socket.isNull(), "Socket is NULL, could not connect to server.");
}
void testQSettingsWrapper()
{
RemoteServer server;
server.init(39999, QHostAddress::LocalHost, RemoteServer::Debug);
server.start();
QSettingsWrapper wrapper("digia", "clientserver");
QCOMPARE(wrapper.isConnectedToServer(), false);
wrapper.clear();
QCOMPARE(wrapper.isConnectedToServer(), true);
wrapper.sync();
QSettings settings("digia", "clientserver");
QCOMPARE(settings.fileName(), wrapper.fileName());
QCOMPARE(int(settings.format()), int(wrapper.format()));
QCOMPARE(int(settings.scope()), int(wrapper.scope()));
QCOMPARE(settings.organizationName(), wrapper.organizationName());
QCOMPARE(settings.applicationName(), wrapper.applicationName());
QCOMPARE(settings.fallbacksEnabled(), wrapper.fallbacksEnabled());
wrapper.setValue("key", "value");
wrapper.setValue("contains", "value");
wrapper.sync();
QCOMPARE(wrapper.value("key").toString(), QLatin1String("value"));
QCOMPARE(settings.value("key").toString(), QLatin1String("value"));
QCOMPARE(wrapper.contains("contains"), true);
QCOMPARE(settings.contains("contains"), true);
wrapper.remove("contains");
wrapper.sync();
QCOMPARE(wrapper.contains("contains"), false);
QCOMPARE(settings.contains("contains"), false);
wrapper.clear();
wrapper.sync();
QCOMPARE(wrapper.contains("key"), false);
QCOMPARE(settings.contains("key"), false);
wrapper.beginGroup("group");
wrapper.setValue("key", "value");
wrapper.endGroup();
wrapper.sync();
wrapper.beginGroup("group");
settings.beginGroup("group");
QCOMPARE(wrapper.value("key").toString(), QLatin1String("value"));
QCOMPARE(settings.value("key").toString(), QLatin1String("value"));
QCOMPARE(wrapper.group(), QLatin1String("group"));
QCOMPARE(settings.group(), QLatin1String("group"));
settings.endGroup();
wrapper.endGroup();
wrapper.beginWriteArray("array");
wrapper.setArrayIndex(0);
wrapper.setValue("key", "value");
wrapper.endArray();
wrapper.sync();
wrapper.beginReadArray("array");
settings.beginReadArray("array");
wrapper.setArrayIndex(0);
settings.setArrayIndex(0);
QCOMPARE(wrapper.value("key").toString(), QLatin1String("value"));
QCOMPARE(settings.value("key").toString(), QLatin1String("value"));
settings.endArray();
wrapper.endArray();
wrapper.setValue("fridge/color", 3);
wrapper.setValue("fridge/size", QSize(32, 96));
wrapper.setValue("sofa", true);
wrapper.setValue("tv", false);
wrapper.remove("group");
wrapper.remove("array");
wrapper.sync();
QStringList keys = wrapper.allKeys();
QCOMPARE(keys.count(), 4);
QCOMPARE(keys.contains("fridge/color"), true);
QCOMPARE(keys.contains("fridge/size"), true);
QCOMPARE(keys.contains("sofa"), true);
QCOMPARE(keys.contains("tv"), true);
wrapper.beginGroup("fridge");
keys = wrapper.allKeys();
QCOMPARE(keys.count(), 2);
QCOMPARE(keys.contains("color"), true);
QCOMPARE(keys.contains("size"), true);
wrapper.endGroup();
keys = wrapper.childKeys();
QCOMPARE(keys.count(), 2);
QCOMPARE(keys.contains("sofa"), true);
QCOMPARE(keys.contains("tv"), true);
wrapper.beginGroup("fridge");
keys = wrapper.childKeys();
QCOMPARE(keys.count(), 2);
QCOMPARE(keys.contains("color"), true);
QCOMPARE(keys.contains("size"), true);
wrapper.endGroup();
QStringList groups = wrapper.childGroups();
QCOMPARE(groups.count(), 1);
QCOMPARE(groups.contains("fridge"), true);
wrapper.beginGroup("fridge");
groups = wrapper.childGroups();
QCOMPARE(groups.count(), 0);
wrapper.endGroup();
}
void testQProcessWrapper()
{
RemoteServer server;
server.init(39999, QHostAddress::LocalHost, RemoteServer::Debug);
server.start();
{
QProcess process;
QProcessWrapper wrapper;
QCOMPARE(wrapper.isConnectedToServer(), false);
QCOMPARE(int(wrapper.state()), int(QProcessWrapper::NotRunning));
QCOMPARE(wrapper.isConnectedToServer(), true);
QCOMPARE(process.workingDirectory(), wrapper.workingDirectory());
process.setWorkingDirectory(QDir::tempPath());
wrapper.setWorkingDirectory(QDir::tempPath());
QCOMPARE(process.workingDirectory(), wrapper.workingDirectory());
QCOMPARE(process.environment(), wrapper.environment());
process.setEnvironment(QProcess::systemEnvironment());
wrapper.setEnvironment(QProcess::systemEnvironment());
QCOMPARE(process.environment(), wrapper.environment());
QCOMPARE(int(process.readChannel()), int(wrapper.readChannel()));
process.setReadChannel(QProcess::StandardError);
wrapper.setReadChannel(QProcessWrapper::StandardError);
QCOMPARE(int(process.readChannel()), int(wrapper.readChannel()));
QCOMPARE(int(process.processChannelMode()), int(wrapper.processChannelMode()));
process.setProcessChannelMode(QProcess::ForwardedChannels);
wrapper.setProcessChannelMode(QProcessWrapper::ForwardedChannels);
QCOMPARE(int(process.processChannelMode()), int(wrapper.processChannelMode()));
}
{
QProcessWrapper wrapper;
QCOMPARE(wrapper.isConnectedToServer(), false);
QCOMPARE(int(wrapper.exitCode()), 0);
QCOMPARE(wrapper.isConnectedToServer(), true);
QCOMPARE(int(wrapper.state()), int(QProcessWrapper::NotRunning));
QCOMPARE(int(wrapper.exitStatus()), int(QProcessWrapper::NormalExit));
QString fileName;
{
QTemporaryFile file(QDir::tempPath() +
#ifdef Q_OS_WIN
QLatin1String("/XXXXXX.bat")
#else
QLatin1String("/XXXXXX.sh")
#endif
);
file.setAutoRemove(false);
QCOMPARE(file.open(), true);
#ifdef Q_OS_WIN
file.write("@echo off\necho Mega test output!");
#else
file.write("#!/bin/bash\necho Mega test output!");
#endif
file.setPermissions(file.permissions() | QFile::ExeOther | QFile::ExeGroup
| QFile::ExeUser);
fileName = file.fileName();
}
QSignalSpy spy(&wrapper, SIGNAL(started()));
QSignalSpy spy2(&wrapper, SIGNAL(finished(int)));
QSignalSpy spy3(&wrapper, SIGNAL(finished(int, QProcess::ExitStatus)));
#ifdef Q_OS_WIN
wrapper.start(fileName);
#else
wrapper.start("sh", QStringList() << fileName);
#endif
QCOMPARE(wrapper.waitForStarted(), true);
QCOMPARE(int(wrapper.state()), int(QProcessWrapper::Running));
QCOMPARE(wrapper.waitForFinished(), true);
QCOMPARE(int(wrapper.state()), int(QProcessWrapper::NotRunning));
QCOMPARE(wrapper.readAll().trimmed(), QByteArray("Mega test output!"));
QTest::qWait(500);
QCOMPARE(spy.count(), 1);
QCOMPARE(spy2.count(), 1);
QList<QVariant> arguments = spy2.takeFirst();
QCOMPARE(arguments.first().toInt(), 0);
QCOMPARE(spy3.count(), 1);
arguments = spy3.takeFirst();
QCOMPARE(arguments.first().toInt(), 0);
QCOMPARE(arguments.last().toInt(), int(QProcessWrapper::NormalExit));
QFile::remove(fileName);
}
}
void testRemoteFileEngine()
{
RemoteServer server;
server.init(39999, QHostAddress::LocalHost, RemoteServer::Debug);
server.start();
QString filename;
{
QTemporaryFile file;
file.setAutoRemove(false);
QCOMPARE(file.open(), true);
file.write(QProcess::systemEnvironment().join(QLatin1String("\n")).toLocal8Bit());
filename = file.fileName();
}
RemoteFileEngineHandler handler;
QFile file;
file.setFileName(filename);
file.open(QIODevice::ReadWrite);
const QByteArray ba = file.readLine();
file.seek(0);
QByteArray ba2(32 * 1024 * 1024, '\0');
file.readLine(ba2.data(), ba2.size());
file.resize(0);
file.write(QProcess::systemEnvironment().join(QLatin1String("\n")).toLocal8Bit());
}
};
QTEST_MAIN(tst_ClientServer)
#include "tst_clientserver.moc"

View File

@ -16,4 +16,5 @@ SUBDIRS += \
binaryformat \
packagemanagercore \
settingsoperation \
task
task \
clientserver

View File

@ -1,194 +0,0 @@
/**************************************************************************
**
** Copyright (C) 2012 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 <fsengineclient.h>
#include <QProcess>
#include <QCoreApplication>
#include <QThread>
#include <QDebug>
class OutputHandler : public QObject
{
Q_OBJECT
public:
OutputHandler(QProcess* processWrapper, QObject *parent = 0)
: QObject (parent)
{
m_process = processWrapper;
QObject::connect(m_process, SIGNAL(readyRead()),
this, SLOT(readProcessOutput()), Qt::DirectConnection);
}
void clearSavedOutPut() { m_savedOutPut.clear(); }
QByteArray savedOutPut() { return m_savedOutPut; }
public slots:
void readProcessOutput()
{
Q_ASSERT(m_process);
Q_ASSERT(QThread::currentThread() == m_process->thread());
if (QThread::currentThread() != m_process->thread()) {
qDebug() << Q_FUNC_INFO << QLatin1String("can only be called from the same thread as the "
"process is.");
}
const QByteArray output = m_process->readAll();
if (!output.isEmpty()) {
m_savedOutPut.append(output);
qDebug() << output;
}
}
private:
QProcess* m_process;
QByteArray m_savedOutPut;
};
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
QString fileName(QLatin1String("give_me_some_output.bat"));
QFile file(fileName);
if (file.exists() && !file.remove()) {
qFatal(qPrintable(QString::fromLatin1("something is wrong, can not delete: %1").arg(file.fileName())));
return -1;
}
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
{
qFatal(qPrintable(QString::fromLatin1("something is wrong, can not open for writing to: %1")
.arg(file.fileName())));
return -2;
}
QTextStream out(&file);
out << QLatin1String("echo mega test output");
if (!file.flush())
{
qFatal(qPrintable(QString::fromLatin1("something is wrong, can not write to: %1").arg(file.fileName())));
return -3;
}
file.close();
//first run as a normal QProcess
QByteArray firstOutPut;
{
QProcess process;
OutputHandler outputer(&process);
process.start(fileName);
qDebug() << "1";
{
const QByteArray output = process.readAll();
if (!output.isEmpty()) {
qDebug() << output;
}
}
process.waitForStarted();
qDebug() << "2";
{
const QByteArray output = process.readAll();
if (!output.isEmpty()) {
qDebug() << output;
}
}
process.waitForFinished();
qDebug() << "3";
{
const QByteArray output = process.readAll();
if (!output.isEmpty()) {
qDebug() << output;
}
}
firstOutPut = outputer.savedOutPut();
}
//first run as a normal QProcess
QByteArray secondOutPut;
{
FSEngineClientHandler::instance().enableTestMode();
FSEngineClientHandler::instance().init(39999);
FSEngineClientHandler::instance().setActive(true);
QProcess process;
OutputHandler outputer(&process);
process.start(fileName);
qDebug() << "1";
{
const QByteArray output = process.readAll();
if (!output.isEmpty()) {
qDebug() << output;
}
}
process.waitForStarted();
qDebug() << "2";
{
const QByteArray output = process.readAll();
if (!output.isEmpty()) {
qDebug() << output;
}
}
process.waitForFinished();
qDebug() << "3";
{
const QByteArray output = process.readAll();
if (!output.isEmpty()) {
qDebug() << output;
}
}
secondOutPut = outputer.savedOutPut();
}
if (firstOutPut != secondOutPut) {
qFatal(qPrintable(QString::fromLatin1("Test failed: output is different between a normal QProcess "
"and QProcessWrapper: %1").arg(file.fileName())));
return -2;
} else {
qDebug() << QLatin1String("Test OK: QProcess works as expected.");
}
return app.exec();
}
#include "fileengineclient.moc"

View File

@ -1,15 +0,0 @@
TEMPLATE = app
INCLUDEPATH += . ..
TARGET = fileengineclient
include(../../installerfw.pri)
QT -= gui
QT += network
CONFIG += console
DESTDIR = $$IFW_APP_PATH
SOURCES += fileengineclient.cpp
macx:include(../../no_app_bundle.pri)

View File

@ -1,52 +0,0 @@
/**************************************************************************
**
** Copyright (C) 2012 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 <fsengineserver.h>
#include <QCoreApplication>
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
FSEngineServer server(39999);
server.enableTestMode();
return app.exec();
}

View File

@ -1,14 +0,0 @@
TEMPLATE = app
INCLUDEPATH += . ..
TARGET = fileengineserver
include(../../installerfw.pri)
QT -= gui
CONFIG += console
DESTDIR = $$IFW_APP_PATH
SOURCES += fileengineserver.cpp
macx:include(../../no_app_bundle.pri)

View File

@ -4,10 +4,7 @@ TEMPLATE = subdirs
EXTRASUBDIRS = \
auto \
downloadspeed \
environmentvariable \
fileengineclient \
fileengineserver
environmentvariable
include(../installerfw.pri)