@ -43,56 +43,46 @@
|
||||
#include <QString>
|
||||
#include <memory>
|
||||
|
||||
|
||||
class QLocalServer;
|
||||
class LockedFile;
|
||||
|
||||
class ApplicationId
|
||||
{
|
||||
public: /* methods */
|
||||
class ApplicationId {
|
||||
public: /* methods */
|
||||
// traditional app = installed system wide and used in a multi-user environment
|
||||
static ApplicationId fromTraditionalApp();
|
||||
// ID based on a path with all the application data (no two instances with the same data path should run)
|
||||
static ApplicationId fromPathAndVersion(const QString & dataPath, const QString & version);
|
||||
static ApplicationId fromPathAndVersion(const QString& dataPath, const QString& version);
|
||||
// custom ID
|
||||
static ApplicationId fromCustomId(const QString & id);
|
||||
static ApplicationId fromCustomId(const QString& id);
|
||||
// custom ID, based on a raw string previously acquired from 'toString'
|
||||
static ApplicationId fromRawString(const QString & id);
|
||||
static ApplicationId fromRawString(const QString& id);
|
||||
|
||||
QString toString() { return m_id; }
|
||||
|
||||
QString toString()
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
private: /* methods */
|
||||
ApplicationId(const QString& value) { m_id = value; }
|
||||
|
||||
private: /* methods */
|
||||
ApplicationId(const QString & value)
|
||||
{
|
||||
m_id = value;
|
||||
}
|
||||
|
||||
private: /* data */
|
||||
private: /* data */
|
||||
QString m_id;
|
||||
};
|
||||
|
||||
class LocalPeer : public QObject
|
||||
{
|
||||
class LocalPeer : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LocalPeer(QObject *parent, const ApplicationId &appId);
|
||||
public:
|
||||
LocalPeer(QObject* parent, const ApplicationId& appId);
|
||||
~LocalPeer();
|
||||
bool isClient();
|
||||
bool sendMessage(const QByteArray &message, int timeout);
|
||||
bool sendMessage(const QByteArray& message, int timeout);
|
||||
ApplicationId applicationId() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void messageReceived(const QByteArray &message);
|
||||
Q_SIGNALS:
|
||||
void messageReceived(const QByteArray& message);
|
||||
|
||||
protected Q_SLOTS:
|
||||
protected Q_SLOTS:
|
||||
void receiveConnection();
|
||||
|
||||
protected:
|
||||
protected:
|
||||
ApplicationId id;
|
||||
QString socketName;
|
||||
std::unique_ptr<QLocalServer> server;
|
||||
|
@ -38,21 +38,20 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include "LocalPeer.h"
|
||||
#include <QCoreApplication>
|
||||
#include <QDataStream>
|
||||
#include <QTime>
|
||||
#include <QDir>
|
||||
#include <QLocalServer>
|
||||
#include <QLocalSocket>
|
||||
#include <QDir>
|
||||
#include <QRegularExpression>
|
||||
#include <QTime>
|
||||
#include "LockedFile.h"
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#include <QLibrary>
|
||||
#include <qt_windows.h>
|
||||
typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*);
|
||||
#include <QLibrary>
|
||||
typedef BOOL(WINAPI* PProcessIdToSessionId)(DWORD, DWORD*);
|
||||
static PProcessIdToSessionId pProcessIdToSessionId = 0;
|
||||
#endif
|
||||
#if defined(Q_OS_UNIX)
|
||||
@ -60,9 +59,9 @@ static PProcessIdToSessionId pProcessIdToSessionId = 0;
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <QCryptographicHash>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <QCryptographicHash>
|
||||
|
||||
static const char* ack = "ack";
|
||||
|
||||
@ -79,13 +78,11 @@ ApplicationId ApplicationId::fromTraditionalApp()
|
||||
quint16 idNum = qChecksum(idc.constData(), idc.size());
|
||||
auto socketName = QLatin1String("qtsingleapp-") + prefix + QLatin1Char('-') + QString::number(idNum, 16);
|
||||
#if defined(Q_OS_WIN)
|
||||
if (!pProcessIdToSessionId)
|
||||
{
|
||||
if (!pProcessIdToSessionId) {
|
||||
QLibrary lib("kernel32");
|
||||
pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId");
|
||||
}
|
||||
if (pProcessIdToSessionId)
|
||||
{
|
||||
if (pProcessIdToSessionId) {
|
||||
DWORD sessionId = 0;
|
||||
pProcessIdToSessionId(GetCurrentProcessId(), &sessionId);
|
||||
socketName += QLatin1Char('-') + QString::number(sessionId, 16);
|
||||
@ -114,8 +111,7 @@ ApplicationId ApplicationId::fromRawString(const QString& id)
|
||||
return ApplicationId(id);
|
||||
}
|
||||
|
||||
LocalPeer::LocalPeer(QObject * parent, const ApplicationId &appId)
|
||||
: QObject(parent), id(appId)
|
||||
LocalPeer::LocalPeer(QObject* parent, const ApplicationId& appId) : QObject(parent), id(appId)
|
||||
{
|
||||
socketName = id.toString();
|
||||
server.reset(new QLocalServer());
|
||||
@ -124,9 +120,7 @@ LocalPeer::LocalPeer(QObject * parent, const ApplicationId &appId)
|
||||
lockFile->open(QIODevice::ReadWrite);
|
||||
}
|
||||
|
||||
LocalPeer::~LocalPeer()
|
||||
{
|
||||
}
|
||||
LocalPeer::~LocalPeer() {}
|
||||
|
||||
ApplicationId LocalPeer::applicationId() const
|
||||
{
|
||||
@ -145,7 +139,7 @@ bool LocalPeer::isClient()
|
||||
#if defined(Q_OS_UNIX)
|
||||
// ### Workaround
|
||||
if (!res && server->serverError() == QAbstractSocket::AddressInUseError) {
|
||||
QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName);
|
||||
QFile::remove(QDir::cleanPath(QDir::tempPath()) + QLatin1Char('/') + socketName);
|
||||
res = server->listen(socketName);
|
||||
}
|
||||
#endif
|
||||
@ -155,8 +149,7 @@ bool LocalPeer::isClient()
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool LocalPeer::sendMessage(const QByteArray &message, int timeout)
|
||||
bool LocalPeer::sendMessage(const QByteArray& message, int timeout)
|
||||
{
|
||||
if (!isClient())
|
||||
return false;
|
||||
@ -164,17 +157,15 @@ bool LocalPeer::sendMessage(const QByteArray &message, int timeout)
|
||||
QLocalSocket socket;
|
||||
bool connOk = false;
|
||||
int tries = 2;
|
||||
for(int i = 0; i < tries; i++) {
|
||||
for (int i = 0; i < tries; i++) {
|
||||
// Try twice, in case the other instance is just starting up
|
||||
socket.connectToServer(socketName);
|
||||
connOk = socket.waitForConnected(timeout/2);
|
||||
if (!connOk && i < (tries - 1))
|
||||
{
|
||||
connOk = socket.waitForConnected(timeout / 2);
|
||||
if (!connOk && i < (tries - 1)) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(250));
|
||||
}
|
||||
}
|
||||
if (!connOk)
|
||||
{
|
||||
if (!connOk) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -182,36 +173,30 @@ bool LocalPeer::sendMessage(const QByteArray &message, int timeout)
|
||||
QDataStream ds(&socket);
|
||||
|
||||
ds.writeBytes(uMsg.constData(), uMsg.size());
|
||||
if(!socket.waitForBytesWritten(timeout))
|
||||
{
|
||||
if (!socket.waitForBytesWritten(timeout)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// wait for 'ack'
|
||||
if(!socket.waitForReadyRead(timeout))
|
||||
{
|
||||
if (!socket.waitForReadyRead(timeout)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// make sure we got 'ack'
|
||||
if(!(socket.read(qstrlen(ack)) == ack))
|
||||
{
|
||||
if (!(socket.read(qstrlen(ack)) == ack)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void LocalPeer::receiveConnection()
|
||||
{
|
||||
QLocalSocket* socket = server->nextPendingConnection();
|
||||
if (!socket)
|
||||
{
|
||||
if (!socket) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (socket->bytesAvailable() < static_cast<int>(sizeof(quint32)))
|
||||
{
|
||||
while (socket->bytesAvailable() < static_cast<int>(sizeof(quint32))) {
|
||||
socket->waitForReadyRead();
|
||||
}
|
||||
QDataStream ds(socket);
|
||||
@ -221,21 +206,19 @@ void LocalPeer::receiveConnection()
|
||||
uMsg.resize(remaining);
|
||||
int got = 0;
|
||||
char* uMsgBuf = uMsg.data();
|
||||
do
|
||||
{
|
||||
do {
|
||||
got = ds.readRawData(uMsgBuf, remaining);
|
||||
remaining -= got;
|
||||
uMsgBuf += got;
|
||||
} while (remaining && got >= 0 && socket->waitForReadyRead(2000));
|
||||
if (got < 0)
|
||||
{
|
||||
if (got < 0) {
|
||||
qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData());
|
||||
delete socket;
|
||||
return;
|
||||
}
|
||||
socket->write(ack, qstrlen(ack));
|
||||
socket->waitForBytesWritten(1000);
|
||||
socket->waitForDisconnected(1000); // make sure client reads ack
|
||||
socket->waitForDisconnected(1000); // make sure client reads ack
|
||||
delete socket;
|
||||
emit messageReceived(uMsg); //### (might take a long time to return)
|
||||
emit messageReceived(uMsg); //### (might take a long time to return)
|
||||
}
|
||||
|
@ -80,8 +80,7 @@
|
||||
|
||||
\sa QFile::QFile()
|
||||
*/
|
||||
LockedFile::LockedFile()
|
||||
: QFile()
|
||||
LockedFile::LockedFile() : QFile()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
wmutex = 0;
|
||||
@ -97,8 +96,7 @@ LockedFile::LockedFile()
|
||||
|
||||
\sa QFile::QFile()
|
||||
*/
|
||||
LockedFile::LockedFile(const QString &name)
|
||||
: QFile(name)
|
||||
LockedFile::LockedFile(const QString& name) : QFile(name)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
wmutex = 0;
|
||||
|
@ -45,13 +45,12 @@
|
||||
#include <QVector>
|
||||
#endif
|
||||
|
||||
class LockedFile : public QFile
|
||||
{
|
||||
public:
|
||||
class LockedFile : public QFile {
|
||||
public:
|
||||
enum LockMode { NoLock = 0, ReadLock, WriteLock };
|
||||
|
||||
LockedFile();
|
||||
LockedFile(const QString &name);
|
||||
LockedFile(const QString& name);
|
||||
~LockedFile();
|
||||
|
||||
bool open(OpenMode mode);
|
||||
@ -61,8 +60,7 @@ public:
|
||||
bool isLocked() const;
|
||||
LockMode lockMode() const;
|
||||
|
||||
private:
|
||||
|
||||
private:
|
||||
#ifdef Q_OS_WIN
|
||||
Qt::HANDLE wmutex;
|
||||
Qt::HANDLE rmutex;
|
||||
|
@ -38,10 +38,10 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "LockedFile.h"
|
||||
|
||||
@ -75,12 +75,10 @@ bool LockedFile::lock(LockMode mode, bool block)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
m_lock_mode = mode;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool LockedFile::unlock()
|
||||
{
|
||||
if (!isOpen()) {
|
||||
|
@ -38,9 +38,9 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "LockedFile.h"
|
||||
#include <qt_windows.h>
|
||||
#include <QFileInfo>
|
||||
#include "LockedFile.h"
|
||||
|
||||
#define MUTEX_PREFIX "QtLockedFile mutex "
|
||||
// Maximum number of concurrent read locks. Must not be greater than MAXIMUM_WAIT_OBJECTS
|
||||
@ -50,8 +50,7 @@ Qt::HANDLE LockedFile::getMutexHandle(int idx, bool doCreate)
|
||||
{
|
||||
if (mutexname.isEmpty()) {
|
||||
QFileInfo fi(*this);
|
||||
mutexname = QString::fromLatin1(MUTEX_PREFIX)
|
||||
+ fi.absoluteFilePath().toLower();
|
||||
mutexname = QString::fromLatin1(MUTEX_PREFIX) + fi.absoluteFilePath().toLower();
|
||||
}
|
||||
QString mname(mutexname);
|
||||
if (idx >= 0)
|
||||
@ -64,8 +63,7 @@ Qt::HANDLE LockedFile::getMutexHandle(int idx, bool doCreate)
|
||||
qErrnoWarning("QtLockedFile::lock(): CreateMutex failed");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (LPCWSTR)mname.utf16());
|
||||
if (!mutex) {
|
||||
if (GetLastError() != ERROR_FILE_NOT_FOUND)
|
||||
@ -81,20 +79,18 @@ bool LockedFile::waitMutex(Qt::HANDLE mutex, bool doBlock)
|
||||
Q_ASSERT(mutex);
|
||||
DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0);
|
||||
switch (res) {
|
||||
case WAIT_OBJECT_0:
|
||||
case WAIT_ABANDONED:
|
||||
return true;
|
||||
break;
|
||||
case WAIT_TIMEOUT:
|
||||
break;
|
||||
default:
|
||||
qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed");
|
||||
case WAIT_OBJECT_0:
|
||||
case WAIT_ABANDONED:
|
||||
return true;
|
||||
break;
|
||||
case WAIT_TIMEOUT:
|
||||
break;
|
||||
default:
|
||||
qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool LockedFile::lock(LockMode mode, bool block)
|
||||
{
|
||||
if (!isOpen()) {
|
||||
@ -130,8 +126,7 @@ bool LockedFile::lock(LockMode mode, bool block)
|
||||
qWarning("QtLockedFile::lock(): too many readers");
|
||||
rmutex = 0;
|
||||
ok = false;
|
||||
}
|
||||
else if (!rmutex) {
|
||||
} else if (!rmutex) {
|
||||
rmutex = getMutexHandle(idx, true);
|
||||
if (!rmutex || !waitMutex(rmutex, false))
|
||||
ok = false;
|
||||
@ -143,8 +138,7 @@ bool LockedFile::lock(LockMode mode, bool block)
|
||||
ReleaseMutex(wmutex);
|
||||
if (!ok)
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Q_ASSERT(rmutexes.isEmpty());
|
||||
for (int i = 0; i < MAX_READERS; i++) {
|
||||
Qt::HANDLE mutex = getMutexHandle(i, false);
|
||||
@ -152,8 +146,7 @@ bool LockedFile::lock(LockMode mode, bool block)
|
||||
rmutexes.append(mutex);
|
||||
}
|
||||
if (rmutexes.size()) {
|
||||
DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(),
|
||||
TRUE, block ? INFINITE : 0);
|
||||
DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(), TRUE, block ? INFINITE : 0);
|
||||
if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) {
|
||||
if (res != WAIT_TIMEOUT)
|
||||
qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed");
|
||||
@ -182,9 +175,8 @@ bool LockedFile::unlock()
|
||||
ReleaseMutex(rmutex);
|
||||
CloseHandle(rmutex);
|
||||
rmutex = 0;
|
||||
}
|
||||
else {
|
||||
foreach(Qt::HANDLE mutex, rmutexes) {
|
||||
} else {
|
||||
foreach (Qt::HANDLE mutex, rmutexes) {
|
||||
ReleaseMutex(mutex);
|
||||
CloseHandle(mutex);
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ static volatile int internal_libgamemode_loaded = 1;
|
||||
|
||||
/* Typedefs for the functions to load */
|
||||
typedef int (*api_call_return_int)(void);
|
||||
typedef const char *(*api_call_return_cstring)(void);
|
||||
typedef const char* (*api_call_return_cstring)(void);
|
||||
typedef int (*api_call_pid_return_int)(pid_t);
|
||||
|
||||
/* Storage for functors */
|
||||
@ -111,26 +111,26 @@ static api_call_pid_return_int REAL_internal_gamemode_query_status_for = NULL;
|
||||
*
|
||||
* Returns 0 on success and -1 on failure
|
||||
*/
|
||||
__attribute__((always_inline)) static inline int internal_bind_libgamemode_symbol(
|
||||
void *handle, const char *name, void **out_func, size_t func_size, bool required)
|
||||
__attribute__((always_inline)) static inline int internal_bind_libgamemode_symbol(void* handle,
|
||||
const char* name,
|
||||
void** out_func,
|
||||
size_t func_size,
|
||||
bool required)
|
||||
{
|
||||
void *symbol_lookup = NULL;
|
||||
char *dl_error = NULL;
|
||||
void* symbol_lookup = NULL;
|
||||
char* dl_error = NULL;
|
||||
|
||||
/* Safely look up the symbol */
|
||||
symbol_lookup = dlsym(handle, name);
|
||||
dl_error = dlerror();
|
||||
if (required && (dl_error || !symbol_lookup)) {
|
||||
snprintf(internal_gamemode_client_error_string,
|
||||
sizeof(internal_gamemode_client_error_string),
|
||||
"dlsym failed - %s",
|
||||
dl_error);
|
||||
return -1;
|
||||
}
|
||||
/* Safely look up the symbol */
|
||||
symbol_lookup = dlsym(handle, name);
|
||||
dl_error = dlerror();
|
||||
if (required && (dl_error || !symbol_lookup)) {
|
||||
snprintf(internal_gamemode_client_error_string, sizeof(internal_gamemode_client_error_string), "dlsym failed - %s", dl_error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Have the symbol correctly, copy it to make it usable */
|
||||
memcpy(out_func, &symbol_lookup, func_size);
|
||||
return 0;
|
||||
/* Have the symbol correctly, copy it to make it usable */
|
||||
memcpy(out_func, &symbol_lookup, func_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -140,98 +140,74 @@ __attribute__((always_inline)) static inline int internal_bind_libgamemode_symbo
|
||||
*/
|
||||
__attribute__((always_inline)) static inline int internal_load_libgamemode(void)
|
||||
{
|
||||
/* We start at 1, 0 is a success and -1 is a fail */
|
||||
if (internal_libgamemode_loaded != 1) {
|
||||
return internal_libgamemode_loaded;
|
||||
}
|
||||
/* We start at 1, 0 is a success and -1 is a fail */
|
||||
if (internal_libgamemode_loaded != 1) {
|
||||
return internal_libgamemode_loaded;
|
||||
}
|
||||
|
||||
/* Anonymous struct type to define our bindings */
|
||||
struct binding {
|
||||
const char *name;
|
||||
void **functor;
|
||||
size_t func_size;
|
||||
bool required;
|
||||
} bindings[] = {
|
||||
{ "real_gamemode_request_start",
|
||||
(void **)&REAL_internal_gamemode_request_start,
|
||||
sizeof(REAL_internal_gamemode_request_start),
|
||||
true },
|
||||
{ "real_gamemode_request_end",
|
||||
(void **)&REAL_internal_gamemode_request_end,
|
||||
sizeof(REAL_internal_gamemode_request_end),
|
||||
true },
|
||||
{ "real_gamemode_query_status",
|
||||
(void **)&REAL_internal_gamemode_query_status,
|
||||
sizeof(REAL_internal_gamemode_query_status),
|
||||
false },
|
||||
{ "real_gamemode_error_string",
|
||||
(void **)&REAL_internal_gamemode_error_string,
|
||||
sizeof(REAL_internal_gamemode_error_string),
|
||||
true },
|
||||
{ "real_gamemode_request_start_for",
|
||||
(void **)&REAL_internal_gamemode_request_start_for,
|
||||
sizeof(REAL_internal_gamemode_request_start_for),
|
||||
false },
|
||||
{ "real_gamemode_request_end_for",
|
||||
(void **)&REAL_internal_gamemode_request_end_for,
|
||||
sizeof(REAL_internal_gamemode_request_end_for),
|
||||
false },
|
||||
{ "real_gamemode_query_status_for",
|
||||
(void **)&REAL_internal_gamemode_query_status_for,
|
||||
sizeof(REAL_internal_gamemode_query_status_for),
|
||||
false },
|
||||
};
|
||||
/* Anonymous struct type to define our bindings */
|
||||
struct binding {
|
||||
const char* name;
|
||||
void** functor;
|
||||
size_t func_size;
|
||||
bool required;
|
||||
} bindings[] = {
|
||||
{ "real_gamemode_request_start", (void**)&REAL_internal_gamemode_request_start, sizeof(REAL_internal_gamemode_request_start),
|
||||
true },
|
||||
{ "real_gamemode_request_end", (void**)&REAL_internal_gamemode_request_end, sizeof(REAL_internal_gamemode_request_end), true },
|
||||
{ "real_gamemode_query_status", (void**)&REAL_internal_gamemode_query_status, sizeof(REAL_internal_gamemode_query_status), false },
|
||||
{ "real_gamemode_error_string", (void**)&REAL_internal_gamemode_error_string, sizeof(REAL_internal_gamemode_error_string), true },
|
||||
{ "real_gamemode_request_start_for", (void**)&REAL_internal_gamemode_request_start_for,
|
||||
sizeof(REAL_internal_gamemode_request_start_for), false },
|
||||
{ "real_gamemode_request_end_for", (void**)&REAL_internal_gamemode_request_end_for, sizeof(REAL_internal_gamemode_request_end_for),
|
||||
false },
|
||||
{ "real_gamemode_query_status_for", (void**)&REAL_internal_gamemode_query_status_for,
|
||||
sizeof(REAL_internal_gamemode_query_status_for), false },
|
||||
};
|
||||
|
||||
void *libgamemode = NULL;
|
||||
void* libgamemode = NULL;
|
||||
|
||||
/* Try and load libgamemode */
|
||||
libgamemode = dlopen("libgamemode.so.0", RTLD_NOW);
|
||||
if (!libgamemode) {
|
||||
/* Attempt to load unversioned library for compatibility with older
|
||||
* versions (as of writing, there are no ABI changes between the two -
|
||||
* this may need to change if ever ABI-breaking changes are made) */
|
||||
libgamemode = dlopen("libgamemode.so", RTLD_NOW);
|
||||
if (!libgamemode) {
|
||||
snprintf(internal_gamemode_client_error_string,
|
||||
sizeof(internal_gamemode_client_error_string),
|
||||
"dlopen failed - %s",
|
||||
dlerror());
|
||||
internal_libgamemode_loaded = -1;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/* Try and load libgamemode */
|
||||
libgamemode = dlopen("libgamemode.so.0", RTLD_NOW);
|
||||
if (!libgamemode) {
|
||||
/* Attempt to load unversioned library for compatibility with older
|
||||
* versions (as of writing, there are no ABI changes between the two -
|
||||
* this may need to change if ever ABI-breaking changes are made) */
|
||||
libgamemode = dlopen("libgamemode.so", RTLD_NOW);
|
||||
if (!libgamemode) {
|
||||
snprintf(internal_gamemode_client_error_string, sizeof(internal_gamemode_client_error_string), "dlopen failed - %s", dlerror());
|
||||
internal_libgamemode_loaded = -1;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Attempt to bind all symbols */
|
||||
for (size_t i = 0; i < sizeof(bindings) / sizeof(bindings[0]); i++) {
|
||||
struct binding *binder = &bindings[i];
|
||||
/* Attempt to bind all symbols */
|
||||
for (size_t i = 0; i < sizeof(bindings) / sizeof(bindings[0]); i++) {
|
||||
struct binding* binder = &bindings[i];
|
||||
|
||||
if (internal_bind_libgamemode_symbol(libgamemode,
|
||||
binder->name,
|
||||
binder->functor,
|
||||
binder->func_size,
|
||||
binder->required)) {
|
||||
internal_libgamemode_loaded = -1;
|
||||
return -1;
|
||||
};
|
||||
}
|
||||
if (internal_bind_libgamemode_symbol(libgamemode, binder->name, binder->functor, binder->func_size, binder->required)) {
|
||||
internal_libgamemode_loaded = -1;
|
||||
return -1;
|
||||
};
|
||||
}
|
||||
|
||||
/* Success */
|
||||
internal_libgamemode_loaded = 0;
|
||||
return 0;
|
||||
/* Success */
|
||||
internal_libgamemode_loaded = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect to the real libgamemode
|
||||
*/
|
||||
__attribute__((always_inline)) static inline const char *gamemode_error_string(void)
|
||||
__attribute__((always_inline)) static inline const char* gamemode_error_string(void)
|
||||
{
|
||||
/* If we fail to load the system gamemode, or we have an error string already, return our error
|
||||
* string instead of diverting to the system version */
|
||||
if (internal_load_libgamemode() < 0 || internal_gamemode_client_error_string[0] != '\0') {
|
||||
return internal_gamemode_client_error_string;
|
||||
}
|
||||
/* If we fail to load the system gamemode, or we have an error string already, return our error
|
||||
* string instead of diverting to the system version */
|
||||
if (internal_load_libgamemode() < 0 || internal_gamemode_client_error_string[0] != '\0') {
|
||||
return internal_gamemode_client_error_string;
|
||||
}
|
||||
|
||||
return REAL_internal_gamemode_error_string();
|
||||
return REAL_internal_gamemode_error_string();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -246,22 +222,22 @@ __attribute__((always_inline)) static inline
|
||||
#endif
|
||||
int gamemode_request_start(void)
|
||||
{
|
||||
/* Need to load gamemode */
|
||||
if (internal_load_libgamemode() < 0) {
|
||||
/* Need to load gamemode */
|
||||
if (internal_load_libgamemode() < 0) {
|
||||
#ifdef GAMEMODE_AUTO
|
||||
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
|
||||
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (REAL_internal_gamemode_request_start() < 0) {
|
||||
if (REAL_internal_gamemode_request_start() < 0) {
|
||||
#ifdef GAMEMODE_AUTO
|
||||
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
|
||||
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Redirect to the real libgamemode */
|
||||
@ -272,94 +248,90 @@ __attribute__((always_inline)) static inline
|
||||
#endif
|
||||
int gamemode_request_end(void)
|
||||
{
|
||||
/* Need to load gamemode */
|
||||
if (internal_load_libgamemode() < 0) {
|
||||
/* Need to load gamemode */
|
||||
if (internal_load_libgamemode() < 0) {
|
||||
#ifdef GAMEMODE_AUTO
|
||||
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
|
||||
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (REAL_internal_gamemode_request_end() < 0) {
|
||||
if (REAL_internal_gamemode_request_end() < 0) {
|
||||
#ifdef GAMEMODE_AUTO
|
||||
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
|
||||
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Redirect to the real libgamemode */
|
||||
__attribute__((always_inline)) static inline int gamemode_query_status(void)
|
||||
{
|
||||
/* Need to load gamemode */
|
||||
if (internal_load_libgamemode() < 0) {
|
||||
return -1;
|
||||
}
|
||||
/* Need to load gamemode */
|
||||
if (internal_load_libgamemode() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (REAL_internal_gamemode_query_status == NULL) {
|
||||
snprintf(internal_gamemode_client_error_string,
|
||||
sizeof(internal_gamemode_client_error_string),
|
||||
"gamemode_query_status missing (older host?)");
|
||||
return -1;
|
||||
}
|
||||
if (REAL_internal_gamemode_query_status == NULL) {
|
||||
snprintf(internal_gamemode_client_error_string, sizeof(internal_gamemode_client_error_string),
|
||||
"gamemode_query_status missing (older host?)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return REAL_internal_gamemode_query_status();
|
||||
return REAL_internal_gamemode_query_status();
|
||||
}
|
||||
|
||||
/* Redirect to the real libgamemode */
|
||||
__attribute__((always_inline)) static inline int gamemode_request_start_for(pid_t pid)
|
||||
{
|
||||
/* Need to load gamemode */
|
||||
if (internal_load_libgamemode() < 0) {
|
||||
return -1;
|
||||
}
|
||||
/* Need to load gamemode */
|
||||
if (internal_load_libgamemode() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (REAL_internal_gamemode_request_start_for == NULL) {
|
||||
snprintf(internal_gamemode_client_error_string,
|
||||
sizeof(internal_gamemode_client_error_string),
|
||||
"gamemode_request_start_for missing (older host?)");
|
||||
return -1;
|
||||
}
|
||||
if (REAL_internal_gamemode_request_start_for == NULL) {
|
||||
snprintf(internal_gamemode_client_error_string, sizeof(internal_gamemode_client_error_string),
|
||||
"gamemode_request_start_for missing (older host?)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return REAL_internal_gamemode_request_start_for(pid);
|
||||
return REAL_internal_gamemode_request_start_for(pid);
|
||||
}
|
||||
|
||||
/* Redirect to the real libgamemode */
|
||||
__attribute__((always_inline)) static inline int gamemode_request_end_for(pid_t pid)
|
||||
{
|
||||
/* Need to load gamemode */
|
||||
if (internal_load_libgamemode() < 0) {
|
||||
return -1;
|
||||
}
|
||||
/* Need to load gamemode */
|
||||
if (internal_load_libgamemode() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (REAL_internal_gamemode_request_end_for == NULL) {
|
||||
snprintf(internal_gamemode_client_error_string,
|
||||
sizeof(internal_gamemode_client_error_string),
|
||||
"gamemode_request_end_for missing (older host?)");
|
||||
return -1;
|
||||
}
|
||||
if (REAL_internal_gamemode_request_end_for == NULL) {
|
||||
snprintf(internal_gamemode_client_error_string, sizeof(internal_gamemode_client_error_string),
|
||||
"gamemode_request_end_for missing (older host?)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return REAL_internal_gamemode_request_end_for(pid);
|
||||
return REAL_internal_gamemode_request_end_for(pid);
|
||||
}
|
||||
|
||||
/* Redirect to the real libgamemode */
|
||||
__attribute__((always_inline)) static inline int gamemode_query_status_for(pid_t pid)
|
||||
{
|
||||
/* Need to load gamemode */
|
||||
if (internal_load_libgamemode() < 0) {
|
||||
return -1;
|
||||
}
|
||||
/* Need to load gamemode */
|
||||
if (internal_load_libgamemode() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (REAL_internal_gamemode_query_status_for == NULL) {
|
||||
snprintf(internal_gamemode_client_error_string,
|
||||
sizeof(internal_gamemode_client_error_string),
|
||||
"gamemode_query_status_for missing (older host?)");
|
||||
return -1;
|
||||
}
|
||||
if (REAL_internal_gamemode_query_status_for == NULL) {
|
||||
snprintf(internal_gamemode_client_error_string, sizeof(internal_gamemode_client_error_string),
|
||||
"gamemode_query_status_for missing (older host?)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return REAL_internal_gamemode_query_status_for(pid);
|
||||
return REAL_internal_gamemode_query_status_for(pid);
|
||||
}
|
||||
|
||||
#endif // CLIENT_GAMEMODE_H
|
||||
#endif // CLIENT_GAMEMODE_H
|
||||
|
@ -1,10 +1,5 @@
|
||||
public final class JavaCheck {
|
||||
|
||||
private static final String[] CHECKED_PROPERTIES = new String[] {
|
||||
"os.arch",
|
||||
"java.version",
|
||||
"java.vendor"
|
||||
};
|
||||
private static final String[] CHECKED_PROPERTIES = new String[] {"os.arch", "java.version", "java.vendor"};
|
||||
|
||||
public static void main(String[] args) {
|
||||
int returnCode = 0;
|
||||
@ -21,5 +16,4 @@ public final class JavaCheck {
|
||||
|
||||
System.exit(returnCode);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <QDateTime>
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
#include <QVariantMap>
|
||||
|
||||
namespace Katabasis {
|
||||
@ -11,17 +11,13 @@ enum class Activity {
|
||||
LoggingIn,
|
||||
LoggingOut,
|
||||
Refreshing,
|
||||
FailedSoft, //!< soft failure. this generally means the user auth details haven't been invalidated
|
||||
FailedHard, //!< hard failure. auth is invalid
|
||||
FailedGone, //!< hard failure. auth is invalid, and the account no longer exists
|
||||
FailedSoft, //!< soft failure. this generally means the user auth details haven't been invalidated
|
||||
FailedHard, //!< hard failure. auth is invalid
|
||||
FailedGone, //!< hard failure. auth is invalid, and the account no longer exists
|
||||
Succeeded
|
||||
};
|
||||
|
||||
enum class Validity {
|
||||
None,
|
||||
Assumed,
|
||||
Certain
|
||||
};
|
||||
enum class Validity { None, Assumed, Certain };
|
||||
|
||||
struct Token {
|
||||
QDateTime issueInstant;
|
||||
@ -34,4 +30,4 @@ struct Token {
|
||||
bool persistent = true;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace Katabasis
|
||||
|
@ -2,13 +2,13 @@
|
||||
|
||||
#include <QLoggingCategory>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <QPair>
|
||||
|
||||
#include "Bits.h"
|
||||
#include "Reply.h"
|
||||
#include "RequestParameter.h"
|
||||
#include "Bits.h"
|
||||
|
||||
namespace Katabasis {
|
||||
|
||||
@ -16,14 +16,12 @@ class ReplyServer;
|
||||
class PollServer;
|
||||
|
||||
/// Simple OAuth2 Device Flow authenticator.
|
||||
class DeviceFlow: public QObject
|
||||
{
|
||||
class DeviceFlow : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
public:
|
||||
Q_ENUMS(GrantFlow)
|
||||
|
||||
public:
|
||||
|
||||
public:
|
||||
struct Options {
|
||||
QString userAgent = QStringLiteral("Katabasis/1.0");
|
||||
QString responseType = QStringLiteral("code");
|
||||
@ -34,7 +32,7 @@ public:
|
||||
QUrl accessTokenUrl;
|
||||
};
|
||||
|
||||
public:
|
||||
public:
|
||||
/// Are we authenticated?
|
||||
bool linked();
|
||||
|
||||
@ -44,21 +42,21 @@ public:
|
||||
/// Provider-specific extra tokens, available after a successful authentication
|
||||
QVariantMap extraTokens();
|
||||
|
||||
public:
|
||||
public:
|
||||
// TODO: put in `Options`
|
||||
/// User-defined extra parameters to append to request URL
|
||||
QVariantMap extraRequestParams();
|
||||
void setExtraRequestParams(const QVariantMap &value);
|
||||
void setExtraRequestParams(const QVariantMap& value);
|
||||
|
||||
// TODO: split up the class into multiple, each implementing one OAuth2 flow
|
||||
/// Grant type (if non-standard)
|
||||
QString grantType();
|
||||
void setGrantType(const QString &value);
|
||||
void setGrantType(const QString& value);
|
||||
|
||||
public:
|
||||
public:
|
||||
/// Constructor.
|
||||
/// @param parent Parent object.
|
||||
explicit DeviceFlow(Options & opts, Token & token, QObject *parent = 0, QNetworkAccessManager *manager = 0);
|
||||
explicit DeviceFlow(Options& opts, Token& token, QObject* parent = 0, QNetworkAccessManager* manager = 0);
|
||||
|
||||
/// Get refresh token.
|
||||
QString refreshToken();
|
||||
@ -66,7 +64,7 @@ public:
|
||||
/// Get token expiration time
|
||||
QDateTime expires();
|
||||
|
||||
public slots:
|
||||
public slots:
|
||||
/// Authenticate.
|
||||
void login();
|
||||
|
||||
@ -79,24 +77,24 @@ public slots:
|
||||
/// Handle situation where reply server has opted to close its connection
|
||||
void serverHasClosed(bool paramsfound = false);
|
||||
|
||||
signals:
|
||||
signals:
|
||||
/// Emitted when client needs to open a web browser window, with the given URL.
|
||||
void openBrowser(const QUrl &url);
|
||||
void openBrowser(const QUrl& url);
|
||||
|
||||
/// Emitted when client can close the browser window.
|
||||
void closeBrowser();
|
||||
|
||||
/// Emitted when client needs to show a verification uri and user code
|
||||
void showVerificationUriAndCode(const QUrl &uri, const QString &code, int expiresIn);
|
||||
void showVerificationUriAndCode(const QUrl& uri, const QString& code, int expiresIn);
|
||||
|
||||
/// Emitted when the internal state changes
|
||||
void activityChanged(Activity activity);
|
||||
|
||||
public slots:
|
||||
public slots:
|
||||
/// Handle verification response.
|
||||
void onVerificationReceived(QMap<QString, QString>);
|
||||
|
||||
protected slots:
|
||||
protected slots:
|
||||
/// Handle completion of a Device Authorization Request
|
||||
void onDeviceAuthReplyFinished();
|
||||
|
||||
@ -104,20 +102,20 @@ protected slots:
|
||||
void onRefreshFinished();
|
||||
|
||||
/// Handle failure of a refresh request.
|
||||
void onRefreshError(QNetworkReply::NetworkError error, QNetworkReply *reply);
|
||||
void onRefreshError(QNetworkReply::NetworkError error, QNetworkReply* reply);
|
||||
|
||||
protected:
|
||||
protected:
|
||||
/// Set refresh token.
|
||||
void setRefreshToken(const QString &v);
|
||||
void setRefreshToken(const QString& v);
|
||||
|
||||
/// Set token expiration time.
|
||||
void setExpires(QDateTime v);
|
||||
|
||||
/// Start polling authorization server
|
||||
void startPollServer(const QVariantMap ¶ms, int expiresIn);
|
||||
void startPollServer(const QVariantMap& params, int expiresIn);
|
||||
|
||||
/// Set authentication token.
|
||||
void setToken(const QString &v);
|
||||
void setToken(const QString& v);
|
||||
|
||||
/// Set the linked state
|
||||
void setLinked(bool v);
|
||||
@ -126,26 +124,26 @@ protected:
|
||||
void setExtraTokens(QVariantMap extraTokens);
|
||||
|
||||
/// Set local poll server
|
||||
void setPollServer(PollServer *server);
|
||||
void setPollServer(PollServer* server);
|
||||
|
||||
PollServer * pollServer() const;
|
||||
PollServer* pollServer() const;
|
||||
|
||||
void updateActivity(Activity activity);
|
||||
|
||||
protected:
|
||||
protected:
|
||||
Options options_;
|
||||
|
||||
QVariantMap extraReqParams_;
|
||||
QNetworkAccessManager *manager_ = nullptr;
|
||||
QNetworkAccessManager* manager_ = nullptr;
|
||||
ReplyList timedReplies_;
|
||||
QString grantType_;
|
||||
|
||||
protected:
|
||||
Token &token_;
|
||||
protected:
|
||||
Token& token_;
|
||||
|
||||
private:
|
||||
PollServer *pollServer_ = nullptr;
|
||||
private:
|
||||
PollServer* pollServer_ = nullptr;
|
||||
Activity activity_ = Activity::Idle;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace Katabasis
|
||||
|
@ -45,7 +45,7 @@ const char OAUTH2_EXPIRES_IN[] = "expires_in";
|
||||
const char OAUTH2_DEVICE_CODE[] = "device_code";
|
||||
const char OAUTH2_USER_CODE[] = "user_code";
|
||||
const char OAUTH2_VERIFICATION_URI[] = "verification_uri";
|
||||
const char OAUTH2_VERIFICATION_URL[] = "verification_url"; // Google sign-in
|
||||
const char OAUTH2_VERIFICATION_URL[] = "verification_url"; // Google sign-in
|
||||
const char OAUTH2_VERIFICATION_URI_COMPLETE[] = "verification_uri_complete";
|
||||
const char OAUTH2_INTERVAL[] = "interval";
|
||||
|
||||
@ -56,4 +56,4 @@ const char AUTHORIZATION_CODE[] = "authorization_code";
|
||||
const char HTTP_HTTP_HEADER[] = "HTTP";
|
||||
const char HTTP_AUTHORIZATION_HEADER[] = "Authorization";
|
||||
|
||||
}
|
||||
} // namespace Katabasis
|
||||
|
@ -12,32 +12,35 @@ class QNetworkAccessManager;
|
||||
namespace Katabasis {
|
||||
|
||||
/// Poll an authorization server for token
|
||||
class PollServer : public QObject
|
||||
{
|
||||
class PollServer : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PollServer(QNetworkAccessManager * manager, const QNetworkRequest &request, const QByteArray & payload, int expiresIn, QObject *parent = 0);
|
||||
public:
|
||||
explicit PollServer(QNetworkAccessManager* manager,
|
||||
const QNetworkRequest& request,
|
||||
const QByteArray& payload,
|
||||
int expiresIn,
|
||||
QObject* parent = 0);
|
||||
|
||||
/// Seconds to wait between polling requests
|
||||
Q_PROPERTY(int interval READ interval WRITE setInterval)
|
||||
int interval() const;
|
||||
void setInterval(int interval);
|
||||
|
||||
signals:
|
||||
signals:
|
||||
void verificationReceived(QMap<QString, QString>);
|
||||
void serverClosed(bool); // whether it has found parameters
|
||||
void serverClosed(bool); // whether it has found parameters
|
||||
|
||||
public slots:
|
||||
public slots:
|
||||
void startPolling();
|
||||
|
||||
protected slots:
|
||||
protected slots:
|
||||
void onPollTimeout();
|
||||
void onExpiration();
|
||||
void onReplyFinished();
|
||||
|
||||
protected:
|
||||
QNetworkAccessManager *manager_;
|
||||
protected:
|
||||
QNetworkAccessManager* manager_;
|
||||
const QNetworkRequest request_;
|
||||
const QByteArray payload_;
|
||||
const int expiresIn_;
|
||||
@ -45,4 +48,4 @@ protected:
|
||||
QTimer pollTimer;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace Katabasis
|
||||
|
@ -1,38 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include <QList>
|
||||
#include <QTimer>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QByteArray>
|
||||
#include <QList>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <QTimer>
|
||||
|
||||
namespace Katabasis {
|
||||
|
||||
constexpr int defaultTimeout = 30 * 1000;
|
||||
|
||||
/// A network request/reply pair that can time out.
|
||||
class Reply: public QTimer {
|
||||
class Reply : public QTimer {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Reply(QNetworkReply *reply, int timeOut = defaultTimeout, QObject *parent = 0);
|
||||
public:
|
||||
Reply(QNetworkReply* reply, int timeOut = defaultTimeout, QObject* parent = 0);
|
||||
|
||||
signals:
|
||||
signals:
|
||||
void error(QNetworkReply::NetworkError);
|
||||
|
||||
public slots:
|
||||
public slots:
|
||||
/// When time out occurs, the QNetworkReply's error() signal is triggered.
|
||||
void onTimeOut();
|
||||
|
||||
public:
|
||||
QNetworkReply *reply;
|
||||
public:
|
||||
QNetworkReply* reply;
|
||||
bool timedOut = false;
|
||||
};
|
||||
|
||||
/// List of O2Replies.
|
||||
class ReplyList {
|
||||
public:
|
||||
public:
|
||||
ReplyList() { ignoreSslErrors_ = false; }
|
||||
|
||||
/// Destructor.
|
||||
@ -40,24 +40,24 @@ public:
|
||||
virtual ~ReplyList();
|
||||
|
||||
/// Create a new O2Reply from a QNetworkReply, and add it to this list.
|
||||
void add(QNetworkReply *reply, int timeOut = defaultTimeout);
|
||||
void add(QNetworkReply* reply, int timeOut = defaultTimeout);
|
||||
|
||||
/// Add an O2Reply to the list, while taking ownership of it.
|
||||
void add(Reply *reply);
|
||||
void add(Reply* reply);
|
||||
|
||||
/// Remove item from the list that corresponds to a QNetworkReply.
|
||||
void remove(QNetworkReply *reply);
|
||||
void remove(QNetworkReply* reply);
|
||||
|
||||
/// Find an O2Reply in the list, corresponding to a QNetworkReply.
|
||||
/// @return Matching O2Reply or NULL.
|
||||
Reply *find(QNetworkReply *reply);
|
||||
Reply* find(QNetworkReply* reply);
|
||||
|
||||
bool ignoreSslErrors();
|
||||
void setIgnoreSslErrors(bool ignoreSslErrors);
|
||||
|
||||
protected:
|
||||
QList<Reply *> replies_;
|
||||
protected:
|
||||
QList<Reply*> replies_;
|
||||
bool ignoreSslErrors_;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace Katabasis
|
||||
|
@ -4,12 +4,10 @@ namespace Katabasis {
|
||||
|
||||
/// Request parameter (name-value pair) participating in authentication.
|
||||
struct RequestParameter {
|
||||
RequestParameter(const QByteArray &n, const QByteArray &v): name(n), value(v) {}
|
||||
bool operator <(const RequestParameter &other) const {
|
||||
return (name == other.name)? (value < other.value): (name < other.name);
|
||||
}
|
||||
RequestParameter(const QByteArray& n, const QByteArray& v) : name(n), value(v) {}
|
||||
bool operator<(const RequestParameter& other) const { return (name == other.name) ? (value < other.value) : (name < other.name); }
|
||||
QByteArray name;
|
||||
QByteArray value;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace Katabasis
|
||||
|
@ -1,26 +1,26 @@
|
||||
#include <QList>
|
||||
#include <QPair>
|
||||
#include <QDebug>
|
||||
#include <QTcpServer>
|
||||
#include <QMap>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QDateTime>
|
||||
#include <QCryptographicHash>
|
||||
#include <QTimer>
|
||||
#include <QVariantMap>
|
||||
#include <QUuid>
|
||||
#include <QDataStream>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <QPair>
|
||||
#include <QTcpServer>
|
||||
#include <QTimer>
|
||||
#include <QUuid>
|
||||
#include <QVariantMap>
|
||||
|
||||
#include <QUrlQuery>
|
||||
|
||||
#include "katabasis/DeviceFlow.h"
|
||||
#include "katabasis/PollServer.h"
|
||||
#include "katabasis/Globals.h"
|
||||
#include "katabasis/PollServer.h"
|
||||
|
||||
#include "KatabasisLogging.h"
|
||||
#include "JsonResponse.h"
|
||||
#include "KatabasisLogging.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@ -43,10 +43,11 @@ bool hasMandatoryDeviceAuthParams(const QVariantMap& params)
|
||||
return true;
|
||||
}
|
||||
|
||||
QByteArray createQueryParameters(const QList<Katabasis::RequestParameter> ¶meters) {
|
||||
QByteArray createQueryParameters(const QList<Katabasis::RequestParameter>& parameters)
|
||||
{
|
||||
QByteArray ret;
|
||||
bool first = true;
|
||||
for( auto & h: parameters) {
|
||||
for (auto& h : parameters) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
@ -56,32 +57,35 @@ QByteArray createQueryParameters(const QList<Katabasis::RequestParameter> ¶m
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace Katabasis {
|
||||
|
||||
DeviceFlow::DeviceFlow(Options & opts, Token & token, QObject *parent, QNetworkAccessManager *manager) : QObject(parent), token_(token) {
|
||||
DeviceFlow::DeviceFlow(Options& opts, Token& token, QObject* parent, QNetworkAccessManager* manager) : QObject(parent), token_(token)
|
||||
{
|
||||
manager_ = manager ? manager : new QNetworkAccessManager(this);
|
||||
qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError");
|
||||
options_ = opts;
|
||||
}
|
||||
|
||||
bool DeviceFlow::linked() {
|
||||
bool DeviceFlow::linked()
|
||||
{
|
||||
return token_.validity != Validity::None;
|
||||
}
|
||||
void DeviceFlow::setLinked(bool v) {
|
||||
qDebug() << "DeviceFlow::setLinked:" << (v? "true": "false");
|
||||
void DeviceFlow::setLinked(bool v)
|
||||
{
|
||||
qDebug() << "DeviceFlow::setLinked:" << (v ? "true" : "false");
|
||||
token_.validity = v ? Validity::Certain : Validity::None;
|
||||
}
|
||||
|
||||
void DeviceFlow::updateActivity(Activity activity)
|
||||
{
|
||||
if(activity_ == activity) {
|
||||
if (activity_ == activity) {
|
||||
return;
|
||||
}
|
||||
|
||||
activity_ = activity;
|
||||
switch(activity) {
|
||||
switch (activity) {
|
||||
case Katabasis::Activity::Idle:
|
||||
case Katabasis::Activity::LoggingIn:
|
||||
case Katabasis::Activity::LoggingOut:
|
||||
@ -103,22 +107,26 @@ void DeviceFlow::updateActivity(Activity activity)
|
||||
emit activityChanged(activity_);
|
||||
}
|
||||
|
||||
QString DeviceFlow::token() {
|
||||
QString DeviceFlow::token()
|
||||
{
|
||||
return token_.token;
|
||||
}
|
||||
void DeviceFlow::setToken(const QString &v) {
|
||||
void DeviceFlow::setToken(const QString& v)
|
||||
{
|
||||
token_.token = v;
|
||||
}
|
||||
|
||||
QVariantMap DeviceFlow::extraTokens() {
|
||||
QVariantMap DeviceFlow::extraTokens()
|
||||
{
|
||||
return token_.extra;
|
||||
}
|
||||
|
||||
void DeviceFlow::setExtraTokens(QVariantMap extraTokens) {
|
||||
void DeviceFlow::setExtraTokens(QVariantMap extraTokens)
|
||||
{
|
||||
token_.extra = extraTokens;
|
||||
}
|
||||
|
||||
void DeviceFlow::setPollServer(PollServer *server)
|
||||
void DeviceFlow::setPollServer(PollServer* server)
|
||||
{
|
||||
if (pollServer_)
|
||||
pollServer_->deleteLater();
|
||||
@ -126,7 +134,7 @@ void DeviceFlow::setPollServer(PollServer *server)
|
||||
pollServer_ = server;
|
||||
}
|
||||
|
||||
PollServer *DeviceFlow::pollServer() const
|
||||
PollServer* DeviceFlow::pollServer() const
|
||||
{
|
||||
return pollServer_;
|
||||
}
|
||||
@ -136,7 +144,7 @@ QVariantMap DeviceFlow::extraRequestParams()
|
||||
return extraReqParams_;
|
||||
}
|
||||
|
||||
void DeviceFlow::setExtraRequestParams(const QVariantMap &value)
|
||||
void DeviceFlow::setExtraRequestParams(const QVariantMap& value)
|
||||
{
|
||||
extraReqParams_ = value;
|
||||
}
|
||||
@ -149,13 +157,14 @@ QString DeviceFlow::grantType()
|
||||
return OAUTH2_GRANT_TYPE_DEVICE;
|
||||
}
|
||||
|
||||
void DeviceFlow::setGrantType(const QString &value)
|
||||
void DeviceFlow::setGrantType(const QString& value)
|
||||
{
|
||||
grantType_ = value;
|
||||
}
|
||||
|
||||
// First get the URL and token to display to the user
|
||||
void DeviceFlow::login() {
|
||||
void DeviceFlow::login()
|
||||
{
|
||||
qDebug() << "DeviceFlow::link";
|
||||
|
||||
updateActivity(Activity::LoggingIn);
|
||||
@ -173,7 +182,7 @@ void DeviceFlow::login() {
|
||||
QUrl url(options_.authorizationUrl);
|
||||
QNetworkRequest deviceRequest(url);
|
||||
deviceRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||
QNetworkReply *tokenReply = manager_->post(deviceRequest, payload);
|
||||
QNetworkReply* tokenReply = manager_->post(deviceRequest, payload);
|
||||
|
||||
connect(tokenReply, &QNetworkReply::finished, this, &DeviceFlow::onDeviceAuthReplyFinished, Qt::QueuedConnection);
|
||||
}
|
||||
@ -182,19 +191,18 @@ void DeviceFlow::login() {
|
||||
void DeviceFlow::onDeviceAuthReplyFinished()
|
||||
{
|
||||
qDebug() << "DeviceFlow::onDeviceAuthReplyFinished";
|
||||
QNetworkReply *tokenReply = qobject_cast<QNetworkReply *>(sender());
|
||||
if (!tokenReply)
|
||||
{
|
||||
qDebug() << "DeviceFlow::onDeviceAuthReplyFinished: reply is null";
|
||||
return;
|
||||
QNetworkReply* tokenReply = qobject_cast<QNetworkReply*>(sender());
|
||||
if (!tokenReply) {
|
||||
qDebug() << "DeviceFlow::onDeviceAuthReplyFinished: reply is null";
|
||||
return;
|
||||
}
|
||||
if (tokenReply->error() == QNetworkReply::NoError) {
|
||||
QByteArray replyData = tokenReply->readAll();
|
||||
|
||||
// Dump replyData
|
||||
// SENSITIVE DATA in RelWithDebInfo or Debug builds
|
||||
//qDebug() << "DeviceFlow::onDeviceAuthReplyFinished: replyData\n";
|
||||
//qDebug() << QString( replyData );
|
||||
// qDebug() << "DeviceFlow::onDeviceAuthReplyFinished: replyData\n";
|
||||
// qDebug() << QString( replyData );
|
||||
|
||||
QVariantMap params = parseJsonResponse(replyData);
|
||||
|
||||
@ -202,7 +210,7 @@ void DeviceFlow::onDeviceAuthReplyFinished()
|
||||
qDebug() << "DeviceFlow::onDeviceAuthReplyFinished: Tokens returned:\n";
|
||||
foreach (QString key, params.keys()) {
|
||||
// SENSITIVE DATA in RelWithDebInfo or Debug builds, so it is truncated first
|
||||
qDebug() << key << ": "<< params.value( key ).toString();
|
||||
qDebug() << key << ": " << params.value(key).toString();
|
||||
}
|
||||
|
||||
// Check for mandatory parameters
|
||||
@ -237,7 +245,7 @@ void DeviceFlow::onDeviceAuthReplyFinished()
|
||||
}
|
||||
|
||||
// Spin up polling for the user completing the login flow out of band
|
||||
void DeviceFlow::startPollServer(const QVariantMap ¶ms, int expiresIn)
|
||||
void DeviceFlow::startPollServer(const QVariantMap& params, int expiresIn)
|
||||
{
|
||||
qDebug() << "DeviceFlow::startPollServer: device_ and user_code expires in" << expiresIn << "seconds";
|
||||
|
||||
@ -250,14 +258,14 @@ void DeviceFlow::startPollServer(const QVariantMap ¶ms, int expiresIn)
|
||||
|
||||
QList<RequestParameter> parameters;
|
||||
parameters.append(RequestParameter(OAUTH2_CLIENT_ID, options_.clientIdentifier.toUtf8()));
|
||||
if ( !options_.clientSecret.isEmpty() ) {
|
||||
if (!options_.clientSecret.isEmpty()) {
|
||||
parameters.append(RequestParameter(OAUTH2_CLIENT_SECRET, options_.clientSecret.toUtf8()));
|
||||
}
|
||||
parameters.append(RequestParameter(OAUTH2_CODE, deviceCode.toUtf8()));
|
||||
parameters.append(RequestParameter(OAUTH2_GRANT_TYPE, grantType.toUtf8()));
|
||||
QByteArray payload = createQueryParameters(parameters);
|
||||
|
||||
PollServer * pollServer = new PollServer(manager_, authRequest, payload, expiresIn, this);
|
||||
PollServer* pollServer = new PollServer(manager_, authRequest, payload, expiresIn, this);
|
||||
if (params.contains(OAUTH2_INTERVAL)) {
|
||||
bool ok = false;
|
||||
int interval = params[OAUTH2_INTERVAL].toInt(&ok);
|
||||
@ -272,7 +280,8 @@ void DeviceFlow::startPollServer(const QVariantMap ¶ms, int expiresIn)
|
||||
}
|
||||
|
||||
// Once the user completes the flow, update the internal state and report it to observers
|
||||
void DeviceFlow::onVerificationReceived(const QMap<QString, QString> response) {
|
||||
void DeviceFlow::onVerificationReceived(const QMap<QString, QString> response)
|
||||
{
|
||||
qDebug() << "DeviceFlow::onVerificationReceived: Emitting closeBrowser()";
|
||||
emit closeBrowser();
|
||||
|
||||
@ -307,7 +316,7 @@ void DeviceFlow::onVerificationReceived(const QMap<QString, QString> response) {
|
||||
// Or if the flow fails or the polling times out, update the internal state with error and report it to observers
|
||||
void DeviceFlow::serverHasClosed(bool paramsfound)
|
||||
{
|
||||
if ( !paramsfound ) {
|
||||
if (!paramsfound) {
|
||||
// server has probably timed out after receiving first response
|
||||
updateActivity(Activity::FailedHard);
|
||||
}
|
||||
@ -315,7 +324,8 @@ void DeviceFlow::serverHasClosed(bool paramsfound)
|
||||
setPollServer(NULL);
|
||||
}
|
||||
|
||||
void DeviceFlow::logout() {
|
||||
void DeviceFlow::logout()
|
||||
{
|
||||
qDebug() << "DeviceFlow::unlink";
|
||||
updateActivity(Activity::LoggingOut);
|
||||
// FIXME: implement logout flows... if they exist
|
||||
@ -323,24 +333,29 @@ void DeviceFlow::logout() {
|
||||
updateActivity(Activity::FailedHard);
|
||||
}
|
||||
|
||||
QDateTime DeviceFlow::expires() {
|
||||
QDateTime DeviceFlow::expires()
|
||||
{
|
||||
return token_.notAfter;
|
||||
}
|
||||
void DeviceFlow::setExpires(QDateTime v) {
|
||||
void DeviceFlow::setExpires(QDateTime v)
|
||||
{
|
||||
token_.notAfter = v;
|
||||
}
|
||||
|
||||
QString DeviceFlow::refreshToken() {
|
||||
QString DeviceFlow::refreshToken()
|
||||
{
|
||||
return token_.refresh_token;
|
||||
}
|
||||
|
||||
void DeviceFlow::setRefreshToken(const QString &v) {
|
||||
void DeviceFlow::setRefreshToken(const QString& v)
|
||||
{
|
||||
qCDebug(katabasisCredentials) << "new refresh token:" << v;
|
||||
token_.refresh_token = v;
|
||||
}
|
||||
|
||||
namespace {
|
||||
QByteArray buildRequestBody(const QMap<QString, QString> ¶meters) {
|
||||
QByteArray buildRequestBody(const QMap<QString, QString>& parameters)
|
||||
{
|
||||
QByteArray body;
|
||||
bool first = true;
|
||||
foreach (QString key, parameters.keys()) {
|
||||
@ -354,9 +369,10 @@ QByteArray buildRequestBody(const QMap<QString, QString> ¶meters) {
|
||||
}
|
||||
return body;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool DeviceFlow::refresh() {
|
||||
bool DeviceFlow::refresh()
|
||||
{
|
||||
qDebug() << "DeviceFlow::refresh: Token: ..." << refreshToken().right(7);
|
||||
|
||||
updateActivity(Activity::Refreshing);
|
||||
@ -376,21 +392,22 @@ bool DeviceFlow::refresh() {
|
||||
refreshRequest.setHeader(QNetworkRequest::ContentTypeHeader, MIME_TYPE_XFORM);
|
||||
QMap<QString, QString> parameters;
|
||||
parameters.insert(OAUTH2_CLIENT_ID, options_.clientIdentifier);
|
||||
if ( !options_.clientSecret.isEmpty() ) {
|
||||
if (!options_.clientSecret.isEmpty()) {
|
||||
parameters.insert(OAUTH2_CLIENT_SECRET, options_.clientSecret);
|
||||
}
|
||||
parameters.insert(OAUTH2_REFRESH_TOKEN, refreshToken());
|
||||
parameters.insert(OAUTH2_GRANT_TYPE, OAUTH2_REFRESH_TOKEN);
|
||||
|
||||
QByteArray data = buildRequestBody(parameters);
|
||||
QNetworkReply *refreshReply = manager_->post(refreshRequest, data);
|
||||
QNetworkReply* refreshReply = manager_->post(refreshRequest, data);
|
||||
timedReplies_.add(refreshReply);
|
||||
connect(refreshReply, &QNetworkReply::finished, this, &DeviceFlow::onRefreshFinished, Qt::QueuedConnection);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DeviceFlow::onRefreshFinished() {
|
||||
QNetworkReply *refreshReply = qobject_cast<QNetworkReply *>(sender());
|
||||
void DeviceFlow::onRefreshFinished()
|
||||
{
|
||||
QNetworkReply* refreshReply = qobject_cast<QNetworkReply*>(sender());
|
||||
|
||||
auto networkError = refreshReply->error();
|
||||
if (networkError == QNetworkReply::NoError) {
|
||||
@ -399,10 +416,9 @@ void DeviceFlow::onRefreshFinished() {
|
||||
setToken(tokens.value(OAUTH2_ACCESS_TOKEN).toString());
|
||||
setExpires(QDateTime::currentDateTimeUtc().addSecs(tokens.value(OAUTH2_EXPIRES_IN).toInt()));
|
||||
QString refreshToken = tokens.value(OAUTH2_REFRESH_TOKEN).toString();
|
||||
if(!refreshToken.isEmpty()) {
|
||||
if (!refreshToken.isEmpty()) {
|
||||
setRefreshToken(refreshToken);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
qDebug() << "No new refresh token. Keep the old one.";
|
||||
}
|
||||
timedReplies_.remove(refreshReply);
|
||||
@ -415,37 +431,37 @@ void DeviceFlow::onRefreshFinished() {
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceFlow::onRefreshError(QNetworkReply::NetworkError error, QNetworkReply *refreshReply) {
|
||||
void DeviceFlow::onRefreshError(QNetworkReply::NetworkError error, QNetworkReply* refreshReply)
|
||||
{
|
||||
QString errorString = "No Reply";
|
||||
if(refreshReply) {
|
||||
if (refreshReply) {
|
||||
timedReplies_.remove(refreshReply);
|
||||
errorString = refreshReply->errorString();
|
||||
}
|
||||
|
||||
switch (error)
|
||||
{
|
||||
// used for invalid credentials and similar errors. Fall through.
|
||||
case QNetworkReply::AuthenticationRequiredError:
|
||||
case QNetworkReply::ContentAccessDenied:
|
||||
case QNetworkReply::ContentOperationNotPermittedError:
|
||||
case QNetworkReply::ProtocolInvalidOperationError:
|
||||
updateActivity(Activity::FailedHard);
|
||||
break;
|
||||
case QNetworkReply::ContentGoneError: {
|
||||
updateActivity(Activity::FailedGone);
|
||||
break;
|
||||
switch (error) {
|
||||
// used for invalid credentials and similar errors. Fall through.
|
||||
case QNetworkReply::AuthenticationRequiredError:
|
||||
case QNetworkReply::ContentAccessDenied:
|
||||
case QNetworkReply::ContentOperationNotPermittedError:
|
||||
case QNetworkReply::ProtocolInvalidOperationError:
|
||||
updateActivity(Activity::FailedHard);
|
||||
break;
|
||||
case QNetworkReply::ContentGoneError: {
|
||||
updateActivity(Activity::FailedGone);
|
||||
break;
|
||||
}
|
||||
case QNetworkReply::TimeoutError:
|
||||
case QNetworkReply::OperationCanceledError:
|
||||
case QNetworkReply::SslHandshakeFailedError:
|
||||
default:
|
||||
updateActivity(Activity::FailedSoft);
|
||||
return;
|
||||
}
|
||||
case QNetworkReply::TimeoutError:
|
||||
case QNetworkReply::OperationCanceledError:
|
||||
case QNetworkReply::SslHandshakeFailedError:
|
||||
default:
|
||||
updateActivity(Activity::FailedSoft);
|
||||
return;
|
||||
}
|
||||
if(refreshReply) {
|
||||
if (refreshReply) {
|
||||
refreshReply->deleteLater();
|
||||
}
|
||||
qDebug() << "DeviceFlow::onRefreshFinished: Error" << static_cast<int>(error) << " - " << errorString;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Katabasis
|
||||
|
@ -7,7 +7,8 @@
|
||||
|
||||
namespace Katabasis {
|
||||
|
||||
QVariantMap parseJsonResponse(const QByteArray &data) {
|
||||
QVariantMap parseJsonResponse(const QByteArray& data)
|
||||
{
|
||||
QJsonParseError err;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(data, &err);
|
||||
if (err.error != QJsonParseError::NoError) {
|
||||
@ -23,4 +24,4 @@ QVariantMap parseJsonResponse(const QByteArray &data) {
|
||||
return doc.object().toVariantMap();
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Katabasis
|
||||
|
@ -6,7 +6,7 @@ class QByteArray;
|
||||
|
||||
namespace Katabasis {
|
||||
|
||||
/// Parse JSON data into a QVariantMap
|
||||
QVariantMap parseJsonResponse(const QByteArray &data);
|
||||
/// Parse JSON data into a QVariantMap
|
||||
QVariantMap parseJsonResponse(const QByteArray& data);
|
||||
|
||||
}
|
||||
} // namespace Katabasis
|
||||
|
@ -1,30 +1,28 @@
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
|
||||
#include "katabasis/PollServer.h"
|
||||
#include "JsonResponse.h"
|
||||
#include "katabasis/PollServer.h"
|
||||
|
||||
namespace {
|
||||
QMap<QString, QString> toVerificationParams(const QVariantMap &map)
|
||||
QMap<QString, QString> toVerificationParams(const QVariantMap& map)
|
||||
{
|
||||
QMap<QString, QString> params;
|
||||
for (QVariantMap::const_iterator i = map.constBegin();
|
||||
i != map.constEnd(); ++i)
|
||||
{
|
||||
for (QVariantMap::const_iterator i = map.constBegin(); i != map.constEnd(); ++i) {
|
||||
params[i.key()] = i.value().toString();
|
||||
}
|
||||
return params;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace Katabasis {
|
||||
|
||||
PollServer::PollServer(QNetworkAccessManager *manager, const QNetworkRequest &request, const QByteArray &payload, int expiresIn, QObject *parent)
|
||||
: QObject(parent)
|
||||
, manager_(manager)
|
||||
, request_(request)
|
||||
, payload_(payload)
|
||||
, expiresIn_(expiresIn)
|
||||
PollServer::PollServer(QNetworkAccessManager* manager,
|
||||
const QNetworkRequest& request,
|
||||
const QByteArray& payload,
|
||||
int expiresIn,
|
||||
QObject* parent)
|
||||
: QObject(parent), manager_(manager), request_(request), payload_(payload), expiresIn_(expiresIn)
|
||||
{
|
||||
expirationTimer.setTimerType(Qt::VeryCoarseTimer);
|
||||
expirationTimer.setInterval(expiresIn * 1000);
|
||||
@ -58,7 +56,7 @@ void PollServer::startPolling()
|
||||
void PollServer::onPollTimeout()
|
||||
{
|
||||
qDebug() << "PollServer::onPollTimeout: retrying";
|
||||
QNetworkReply * reply = manager_->post(request_, payload_);
|
||||
QNetworkReply* reply = manager_->post(request_, payload_);
|
||||
connect(reply, SIGNAL(finished()), this, SLOT(onReplyFinished()));
|
||||
}
|
||||
|
||||
@ -70,7 +68,7 @@ void PollServer::onExpiration()
|
||||
|
||||
void PollServer::onReplyFinished()
|
||||
{
|
||||
QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
|
||||
|
||||
if (!reply) {
|
||||
qDebug() << "PollServer::onReplyFinished: reply is null";
|
||||
@ -93,8 +91,7 @@ void PollServer::onReplyFinished()
|
||||
// polling interval on each such connection timeout, is RECOMMENDED."
|
||||
setInterval(interval() * 2);
|
||||
pollTimer.start();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
QString error = params.value("error");
|
||||
if (error == "slow_down") {
|
||||
// rfc8628#section-3.2
|
||||
@ -103,14 +100,12 @@ void PollServer::onReplyFinished()
|
||||
// be increased by 5 seconds for this and all subsequent requests."
|
||||
setInterval(interval() + 5);
|
||||
pollTimer.start();
|
||||
}
|
||||
else if (error == "authorization_pending") {
|
||||
} else if (error == "authorization_pending") {
|
||||
// keep trying - rfc8628#section-3.2
|
||||
// "The authorization request is still pending as the end user hasn't
|
||||
// yet completed the user-interaction steps (Section 3.3)."
|
||||
pollTimer.start();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
expirationTimer.stop();
|
||||
emit serverClosed(true);
|
||||
// let O2 handle the other cases
|
||||
@ -120,4 +115,4 @@ void PollServer::onReplyFinished()
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Katabasis
|
||||
|
@ -1,42 +1,48 @@
|
||||
#include <QTimer>
|
||||
#include <QNetworkReply>
|
||||
#include <QTimer>
|
||||
|
||||
#include "katabasis/Reply.h"
|
||||
|
||||
namespace Katabasis {
|
||||
|
||||
Reply::Reply(QNetworkReply *r, int timeOut, QObject *parent): QTimer(parent), reply(r) {
|
||||
Reply::Reply(QNetworkReply* r, int timeOut, QObject* parent) : QTimer(parent), reply(r)
|
||||
{
|
||||
setSingleShot(true);
|
||||
connect(this, &Reply::timeout, this, &Reply::onTimeOut, Qt::QueuedConnection);
|
||||
start(timeOut);
|
||||
}
|
||||
|
||||
void Reply::onTimeOut() {
|
||||
void Reply::onTimeOut()
|
||||
{
|
||||
timedOut = true;
|
||||
reply->abort();
|
||||
}
|
||||
|
||||
// ----------------------------
|
||||
|
||||
ReplyList::~ReplyList() {
|
||||
foreach (Reply *timedReply, replies_) {
|
||||
ReplyList::~ReplyList()
|
||||
{
|
||||
foreach (Reply* timedReply, replies_) {
|
||||
delete timedReply;
|
||||
}
|
||||
}
|
||||
|
||||
void ReplyList::add(QNetworkReply *reply, int timeOut) {
|
||||
void ReplyList::add(QNetworkReply* reply, int timeOut)
|
||||
{
|
||||
if (reply && ignoreSslErrors()) {
|
||||
reply->ignoreSslErrors();
|
||||
}
|
||||
add(new Reply(reply, timeOut));
|
||||
}
|
||||
|
||||
void ReplyList::add(Reply *reply) {
|
||||
void ReplyList::add(Reply* reply)
|
||||
{
|
||||
replies_.append(reply);
|
||||
}
|
||||
|
||||
void ReplyList::remove(QNetworkReply *reply) {
|
||||
Reply *o2Reply = find(reply);
|
||||
void ReplyList::remove(QNetworkReply* reply)
|
||||
{
|
||||
Reply* o2Reply = find(reply);
|
||||
if (o2Reply) {
|
||||
o2Reply->stop();
|
||||
(void)replies_.removeOne(o2Reply);
|
||||
@ -45,8 +51,9 @@ void ReplyList::remove(QNetworkReply *reply) {
|
||||
}
|
||||
}
|
||||
|
||||
Reply *ReplyList::find(QNetworkReply *reply) {
|
||||
foreach (Reply *timedReply, replies_) {
|
||||
Reply* ReplyList::find(QNetworkReply* reply)
|
||||
{
|
||||
foreach (Reply* timedReply, replies_) {
|
||||
if (timedReply->reply == reply) {
|
||||
return timedReply;
|
||||
}
|
||||
@ -64,4 +71,4 @@ void ReplyList::setIgnoreSslErrors(bool ignoreSslErrors)
|
||||
ignoreSslErrors_ = ignoreSslErrors;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Katabasis
|
||||
|
@ -71,7 +71,6 @@ import java.util.Map;
|
||||
* recommended.
|
||||
*/
|
||||
public final class Launcher extends Applet implements AppletStub {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final Map<String, String> params = new HashMap<>();
|
||||
@ -207,12 +206,10 @@ public final class Launcher extends Applet implements AppletStub {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics graphics) {
|
||||
}
|
||||
public void paint(Graphics graphics) {}
|
||||
|
||||
@Override
|
||||
public void update(Graphics graphics) {
|
||||
}
|
||||
public void update(Graphics graphics) {}
|
||||
|
||||
public void setParameter(String key, String value) {
|
||||
params.put(key, value);
|
||||
@ -221,5 +218,4 @@ public final class Launcher extends Applet implements AppletStub {
|
||||
public void setParameter(String key, boolean value) {
|
||||
setParameter(key, value ? "true" : "false");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -54,10 +54,6 @@
|
||||
|
||||
package org.prismlauncher;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.prismlauncher.exception.ParseException;
|
||||
import org.prismlauncher.launcher.Launcher;
|
||||
import org.prismlauncher.launcher.impl.StandardLauncher;
|
||||
@ -65,8 +61,11 @@ import org.prismlauncher.launcher.impl.legacy.LegacyLauncher;
|
||||
import org.prismlauncher.utils.Parameters;
|
||||
import org.prismlauncher.utils.logging.Log;
|
||||
|
||||
public final class EntryPoint {
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public final class EntryPoint {
|
||||
public static void main(String[] args) {
|
||||
ExitCode code = listen();
|
||||
|
||||
@ -160,19 +159,18 @@ public final class EntryPoint {
|
||||
return PreLaunchAction.PROCEED;
|
||||
}
|
||||
|
||||
private enum PreLaunchAction {
|
||||
PROCEED, LAUNCH, ABORT
|
||||
}
|
||||
private enum PreLaunchAction { PROCEED, LAUNCH, ABORT }
|
||||
|
||||
private enum ExitCode {
|
||||
NORMAL(0), ABORT(1), ERROR(2), ILLEGAL_ARGUMENT(65);
|
||||
NORMAL(0),
|
||||
ABORT(1),
|
||||
ERROR(2),
|
||||
ILLEGAL_ARGUMENT(65);
|
||||
|
||||
private final int numeric;
|
||||
|
||||
ExitCode(int numeric) {
|
||||
this.numeric = numeric;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -38,11 +38,9 @@
|
||||
package org.prismlauncher.exception;
|
||||
|
||||
public final class ParameterNotFoundException extends IllegalArgumentException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ParameterNotFoundException(String key) {
|
||||
super(String.format("Required parameter '%s' was not found", key));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -38,11 +38,9 @@
|
||||
package org.prismlauncher.exception;
|
||||
|
||||
public final class ParseException extends IllegalArgumentException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ParseException(String input, String format) {
|
||||
super(String.format("For input '%s' - should match '%s'", input, format));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -38,7 +38,5 @@
|
||||
package org.prismlauncher.launcher;
|
||||
|
||||
public interface Launcher {
|
||||
|
||||
void launch() throws Throwable;
|
||||
|
||||
}
|
||||
|
@ -54,15 +54,14 @@
|
||||
|
||||
package org.prismlauncher.launcher.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.prismlauncher.exception.ParseException;
|
||||
import org.prismlauncher.launcher.Launcher;
|
||||
import org.prismlauncher.utils.Parameters;
|
||||
|
||||
public abstract class AbstractLauncher implements Launcher {
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class AbstractLauncher implements Launcher {
|
||||
private static final int DEFAULT_WINDOW_WIDTH = 854, DEFAULT_WINDOW_HEIGHT = 480;
|
||||
|
||||
// parameters, separated from ParamBucket
|
||||
@ -106,5 +105,4 @@ public abstract class AbstractLauncher implements Launcher {
|
||||
throw new ParseException(windowParams, "[width]x[height]");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -54,13 +54,12 @@
|
||||
|
||||
package org.prismlauncher.launcher.impl;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
|
||||
import org.prismlauncher.utils.Parameters;
|
||||
import org.prismlauncher.utils.ReflectionUtils;
|
||||
|
||||
public final class StandardLauncher extends AbstractLauncher {
|
||||
import java.lang.invoke.MethodHandle;
|
||||
|
||||
public final class StandardLauncher extends AbstractLauncher {
|
||||
public StandardLauncher(Parameters params) {
|
||||
super(params);
|
||||
}
|
||||
@ -87,5 +86,4 @@ public final class StandardLauncher extends AbstractLauncher {
|
||||
MethodHandle method = ReflectionUtils.findMainMethod(mainClassName);
|
||||
method.invokeExact(gameArgs.toArray(new String[0]));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -54,6 +54,8 @@
|
||||
|
||||
package org.prismlauncher.launcher.impl.legacy;
|
||||
|
||||
import org.prismlauncher.utils.logging.Log;
|
||||
|
||||
import java.applet.Applet;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.WindowAdapter;
|
||||
@ -70,12 +72,9 @@ import java.util.List;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.JFrame;
|
||||
|
||||
import org.prismlauncher.utils.logging.Log;
|
||||
|
||||
import net.minecraft.Launcher;
|
||||
|
||||
public final class LegacyFrame extends JFrame {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final Launcher launcher;
|
||||
@ -96,8 +95,8 @@ public final class LegacyFrame extends JFrame {
|
||||
addWindowListener(new ForceExitHandler());
|
||||
}
|
||||
|
||||
public void start(String user, String session, int width, int height, boolean maximize, String serverAddress,
|
||||
String serverPort, boolean demo) {
|
||||
public void start(
|
||||
String user, String session, int width, int height, boolean maximize, String serverAddress, String serverPort, boolean demo) {
|
||||
// Implements support for launching in to multiplayer on classic servers using a
|
||||
// mpticket file generated by an external program and stored in the instance's
|
||||
// root folder.
|
||||
@ -157,7 +156,6 @@ public final class LegacyFrame extends JFrame {
|
||||
}
|
||||
|
||||
private final class ForceExitHandler extends WindowAdapter {
|
||||
|
||||
@Override
|
||||
public void windowClosing(WindowEvent event) {
|
||||
// FIXME better solution
|
||||
@ -184,7 +182,5 @@ public final class LegacyFrame extends JFrame {
|
||||
// old minecraft versions can hang without this >_<
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -55,22 +55,21 @@
|
||||
|
||||
package org.prismlauncher.launcher.impl.legacy;
|
||||
|
||||
import org.prismlauncher.launcher.impl.AbstractLauncher;
|
||||
import org.prismlauncher.utils.Parameters;
|
||||
import org.prismlauncher.utils.ReflectionUtils;
|
||||
import org.prismlauncher.utils.logging.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.prismlauncher.launcher.impl.AbstractLauncher;
|
||||
import org.prismlauncher.utils.Parameters;
|
||||
import org.prismlauncher.utils.ReflectionUtils;
|
||||
import org.prismlauncher.utils.logging.Log;
|
||||
|
||||
/**
|
||||
* Used to launch old versions that support applets.
|
||||
*/
|
||||
public final class LegacyLauncher extends AbstractLauncher {
|
||||
|
||||
private final String user, session;
|
||||
private final String title;
|
||||
private final String appletClass;
|
||||
@ -109,8 +108,7 @@ public final class LegacyLauncher extends AbstractLauncher {
|
||||
try {
|
||||
LegacyFrame window = new LegacyFrame(title, ReflectionUtils.createAppletClass(appletClass));
|
||||
|
||||
window.start(user, session, width, height, maximize, serverAddress, serverPort,
|
||||
gameArgs.contains("--demo"));
|
||||
window.start(user, session, width, height, maximize, serverAddress, serverPort, gameArgs.contains("--demo"));
|
||||
return;
|
||||
} catch (Throwable e) {
|
||||
Log.error("Running applet wrapper failed with exception; falling back to main class", e);
|
||||
@ -122,5 +120,4 @@ public final class LegacyLauncher extends AbstractLauncher {
|
||||
MethodHandle method = ReflectionUtils.findMainMethod(main);
|
||||
method.invokeExact(gameArgs.toArray(new String[0]));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -54,15 +54,14 @@
|
||||
|
||||
package org.prismlauncher.utils;
|
||||
|
||||
import org.prismlauncher.exception.ParameterNotFoundException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.prismlauncher.exception.ParameterNotFoundException;
|
||||
|
||||
public final class Parameters {
|
||||
|
||||
private final Map<String, List<String>> map = new HashMap<>();
|
||||
|
||||
public void add(String key, String value) {
|
||||
@ -112,5 +111,4 @@ public final class Parameters {
|
||||
|
||||
return params.get(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -54,6 +54,8 @@
|
||||
|
||||
package org.prismlauncher.utils;
|
||||
|
||||
import org.prismlauncher.utils.logging.Log;
|
||||
|
||||
import java.applet.Applet;
|
||||
import java.io.File;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
@ -62,10 +64,7 @@ import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import org.prismlauncher.utils.logging.Log;
|
||||
|
||||
public final class ReflectionUtils {
|
||||
|
||||
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
|
||||
private static final ClassLoader LOADER = ClassLoader.getSystemClassLoader();
|
||||
|
||||
@ -146,9 +145,7 @@ public final class ReflectionUtils {
|
||||
* @throws NoSuchMethodException
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
public static MethodHandle findMainMethod(String clazz)
|
||||
throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException {
|
||||
public static MethodHandle findMainMethod(String clazz) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException {
|
||||
return findMainMethod(LOADER.loadClass(clazz));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -55,5 +55,4 @@ public enum Level {
|
||||
this.name = name;
|
||||
this.stderr = stderr;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -43,9 +43,8 @@ import java.io.PrintStream;
|
||||
* messages.
|
||||
*/
|
||||
public final class Log {
|
||||
|
||||
// original before possibly overridden by MC
|
||||
private static final PrintStream OUT = new PrintStream(System.out), ERR = new PrintStream(System.err);
|
||||
private static final PrintStream OUT = new PrintStream(System.out), ERR = new PrintStream(System.err);
|
||||
private static final boolean DEBUG = Boolean.getBoolean("org.prismlauncher.debug");
|
||||
|
||||
public static void launcher(String message) {
|
||||
@ -100,5 +99,4 @@ public final class Log {
|
||||
else
|
||||
OUT.println(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -16,11 +16,11 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define KiB 1024
|
||||
#define MiB 1024*KiB
|
||||
#define MiB 1024 * KiB
|
||||
|
||||
uint32_t MurmurHash2(
|
||||
std::ifstream&& file_stream,
|
||||
std::size_t buffer_size = 4*MiB,
|
||||
std::size_t buffer_size = 4 * MiB,
|
||||
std::function<bool(char)> filter_out = [](char) { return false; });
|
||||
|
||||
struct IncrementalHashInfo {
|
||||
|
@ -29,8 +29,7 @@ class QColor;
|
||||
/**
|
||||
* A set of methods used to work with colors.
|
||||
*/
|
||||
namespace Rainbow
|
||||
{
|
||||
namespace Rainbow {
|
||||
/**
|
||||
* Calculate the luma of a color. Luma is weighted sum of gamma-adjusted
|
||||
* R'G'B' components of a color. The result is similar to qGray. The range
|
||||
@ -41,14 +40,13 @@ namespace Rainbow
|
||||
*
|
||||
* @see http://en.wikipedia.org/wiki/Luma_(video)
|
||||
*/
|
||||
qreal luma(const QColor &);
|
||||
qreal luma(const QColor&);
|
||||
|
||||
/**
|
||||
* Calculate hue, chroma and luma of a color in one call.
|
||||
* @since 5.0
|
||||
*/
|
||||
void getHcy(const QColor &, qreal *hue, qreal *chroma, qreal *luma,
|
||||
qreal *alpha = 0);
|
||||
void getHcy(const QColor&, qreal* hue, qreal* chroma, qreal* luma, qreal* alpha = 0);
|
||||
|
||||
/**
|
||||
* Calculate the contrast ratio between two colors, according to the
|
||||
@ -62,7 +60,7 @@ void getHcy(const QColor &, qreal *hue, qreal *chroma, qreal *luma,
|
||||
*
|
||||
* @see Rainbow::luma
|
||||
*/
|
||||
qreal contrastRatio(const QColor &, const QColor &);
|
||||
qreal contrastRatio(const QColor&, const QColor&);
|
||||
|
||||
/**
|
||||
* Adjust the luma of a color by changing its distance from white.
|
||||
@ -79,8 +77,7 @@ qreal contrastRatio(const QColor &, const QColor &);
|
||||
* component of the color; 1.0 means no change, 0.0 maximizes chroma
|
||||
* @see Rainbow::shade
|
||||
*/
|
||||
QColor
|
||||
lighten(const QColor &, qreal amount = 0.5, qreal chromaInverseGain = 1.0);
|
||||
QColor lighten(const QColor&, qreal amount = 0.5, qreal chromaInverseGain = 1.0);
|
||||
|
||||
/**
|
||||
* Adjust the luma of a color by changing its distance from black.
|
||||
@ -97,7 +94,7 @@ lighten(const QColor &, qreal amount = 0.5, qreal chromaInverseGain = 1.0);
|
||||
* component of the color; 1.0 means no change, 0.0 minimizes chroma
|
||||
* @see Rainbow::shade
|
||||
*/
|
||||
QColor darken(const QColor &, qreal amount = 0.5, qreal chromaGain = 1.0);
|
||||
QColor darken(const QColor&, qreal amount = 0.5, qreal chromaGain = 1.0);
|
||||
|
||||
/**
|
||||
* Adjust the luma and chroma components of a color. The amount is added
|
||||
@ -111,7 +108,7 @@ QColor darken(const QColor &, qreal amount = 0.5, qreal chromaGain = 1.0);
|
||||
* 1.0 maximizes chroma
|
||||
* @see Rainbow::luma
|
||||
*/
|
||||
QColor shade(const QColor &, qreal lumaAmount, qreal chromaAmount = 0.0);
|
||||
QColor shade(const QColor&, qreal lumaAmount, qreal chromaAmount = 0.0);
|
||||
|
||||
/**
|
||||
* Create a new color by tinting one color with another. This function is
|
||||
@ -125,7 +122,7 @@ QColor shade(const QColor &, qreal lumaAmount, qreal chromaAmount = 0.0);
|
||||
* @param amount how strongly to tint the base; 0.0 gives @p base,
|
||||
* 1.0 gives @p color
|
||||
*/
|
||||
QColor tint(const QColor &base, const QColor &color, qreal amount = 0.3);
|
||||
QColor tint(const QColor& base, const QColor& color, qreal amount = 0.3);
|
||||
|
||||
/**
|
||||
* Blend two colors into a new color by linear combination.
|
||||
@ -138,7 +135,7 @@ QColor tint(const QColor &base, const QColor &color, qreal amount = 0.3);
|
||||
* @p bias >= 1 gives @p c2. @p bias == 0.5 gives a 50% blend of @p c1
|
||||
* and @p c2.
|
||||
*/
|
||||
QColor mix(const QColor &c1, const QColor &c2, qreal bias = 0.5);
|
||||
QColor mix(const QColor& c1, const QColor& c2, qreal bias = 0.5);
|
||||
|
||||
/**
|
||||
* Blend two colors into a new color by painting the second color over the
|
||||
@ -152,7 +149,5 @@ QColor mix(const QColor &c1, const QColor &c2, qreal bias = 0.5);
|
||||
* @param paint the color to be overlayed onto the base color.
|
||||
* @param comp the CompositionMode used to do the blending.
|
||||
*/
|
||||
QColor
|
||||
overlayColors(const QColor &base, const QColor &paint,
|
||||
QPainter::CompositionMode comp = QPainter::CompositionMode_SourceOver);
|
||||
}
|
||||
QColor overlayColors(const QColor& base, const QColor& paint, QPainter::CompositionMode comp = QPainter::CompositionMode_SourceOver);
|
||||
} // namespace Rainbow
|
||||
|
@ -25,11 +25,11 @@
|
||||
|
||||
#include <QColor>
|
||||
#include <QImage>
|
||||
#include <QtNumeric> // qIsNaN
|
||||
#include <QtNumeric> // qIsNaN
|
||||
|
||||
#include <math.h>
|
||||
|
||||
//BEGIN internal helper functions
|
||||
// BEGIN internal helper functions
|
||||
|
||||
static inline qreal wrap(qreal a, qreal d = 1.0)
|
||||
{
|
||||
@ -44,23 +44,21 @@ static inline qreal normalize(qreal a)
|
||||
return (a < 1.0 ? (a > 0.0 ? a : 0.0) : 1.0);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// HCY color space
|
||||
|
||||
#define HCY_REC 709 // use 709 for now
|
||||
#define HCY_REC 709 // use 709 for now
|
||||
#if HCY_REC == 601
|
||||
static const qreal yc[3] = {0.299, 0.587, 0.114};
|
||||
static const qreal yc[3] = { 0.299, 0.587, 0.114 };
|
||||
#elif HCY_REC == 709
|
||||
static const qreal yc[3] = {0.2126, 0.7152, 0.0722};
|
||||
#else // use Qt values
|
||||
static const qreal yc[3] = {0.34375, 0.5, 0.15625};
|
||||
static const qreal yc[3] = { 0.2126, 0.7152, 0.0722 };
|
||||
#else // use Qt values
|
||||
static const qreal yc[3] = { 0.34375, 0.5, 0.15625 };
|
||||
#endif
|
||||
|
||||
class KHCY
|
||||
{
|
||||
public:
|
||||
explicit KHCY(const QColor &color)
|
||||
class KHCY {
|
||||
public:
|
||||
explicit KHCY(const QColor& color)
|
||||
{
|
||||
qreal r = gamma(color.redF());
|
||||
qreal g = gamma(color.greenF());
|
||||
@ -74,30 +72,20 @@ public:
|
||||
qreal p = qMax(qMax(r, g), b);
|
||||
qreal n = qMin(qMin(r, g), b);
|
||||
qreal d = 6.0 * (p - n);
|
||||
if (n == p)
|
||||
{
|
||||
if (n == p) {
|
||||
h = 0.0;
|
||||
}
|
||||
else if (r == p)
|
||||
{
|
||||
} else if (r == p) {
|
||||
h = ((g - b) / d);
|
||||
}
|
||||
else if (g == p)
|
||||
{
|
||||
} else if (g == p) {
|
||||
h = ((b - r) / d) + (1.0 / 3.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
h = ((r - g) / d) + (2.0 / 3.0);
|
||||
}
|
||||
|
||||
// chroma component
|
||||
if (r == g && g == b)
|
||||
{
|
||||
if (r == g && g == b) {
|
||||
c = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
c = qMax((y - n) / y, (p - y) / (1 - y));
|
||||
}
|
||||
}
|
||||
@ -118,145 +106,103 @@ public:
|
||||
|
||||
// calculate some needed variables
|
||||
qreal _hs = _h * 6.0, th, tm;
|
||||
if (_hs < 1.0)
|
||||
{
|
||||
if (_hs < 1.0) {
|
||||
th = _hs;
|
||||
tm = yc[0] + yc[1] * th;
|
||||
}
|
||||
else if (_hs < 2.0)
|
||||
{
|
||||
} else if (_hs < 2.0) {
|
||||
th = 2.0 - _hs;
|
||||
tm = yc[1] + yc[0] * th;
|
||||
}
|
||||
else if (_hs < 3.0)
|
||||
{
|
||||
} else if (_hs < 3.0) {
|
||||
th = _hs - 2.0;
|
||||
tm = yc[1] + yc[2] * th;
|
||||
}
|
||||
else if (_hs < 4.0)
|
||||
{
|
||||
} else if (_hs < 4.0) {
|
||||
th = 4.0 - _hs;
|
||||
tm = yc[2] + yc[1] * th;
|
||||
}
|
||||
else if (_hs < 5.0)
|
||||
{
|
||||
} else if (_hs < 5.0) {
|
||||
th = _hs - 4.0;
|
||||
tm = yc[2] + yc[0] * th;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
th = 6.0 - _hs;
|
||||
tm = yc[0] + yc[2] * th;
|
||||
}
|
||||
|
||||
// calculate RGB channels in sorted order
|
||||
qreal tn, to, tp;
|
||||
if (tm >= _y)
|
||||
{
|
||||
if (tm >= _y) {
|
||||
tp = _y + _y * _c * (1.0 - tm) / tm;
|
||||
to = _y + _y * _c * (th - tm) / tm;
|
||||
tn = _y - (_y * _c);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
tp = _y + (1.0 - _y) * _c;
|
||||
to = _y + (1.0 - _y) * _c * (th - tm) / (1.0 - tm);
|
||||
tn = _y - (1.0 - _y) * _c * tm / (1.0 - tm);
|
||||
}
|
||||
|
||||
// return RGB channels in appropriate order
|
||||
if (_hs < 1.0)
|
||||
{
|
||||
if (_hs < 1.0) {
|
||||
return QColor::fromRgbF(igamma(tp), igamma(to), igamma(tn), a);
|
||||
}
|
||||
else if (_hs < 2.0)
|
||||
{
|
||||
} else if (_hs < 2.0) {
|
||||
return QColor::fromRgbF(igamma(to), igamma(tp), igamma(tn), a);
|
||||
}
|
||||
else if (_hs < 3.0)
|
||||
{
|
||||
} else if (_hs < 3.0) {
|
||||
return QColor::fromRgbF(igamma(tn), igamma(tp), igamma(to), a);
|
||||
}
|
||||
else if (_hs < 4.0)
|
||||
{
|
||||
} else if (_hs < 4.0) {
|
||||
return QColor::fromRgbF(igamma(tn), igamma(to), igamma(tp), a);
|
||||
}
|
||||
else if (_hs < 5.0)
|
||||
{
|
||||
} else if (_hs < 5.0) {
|
||||
return QColor::fromRgbF(igamma(to), igamma(tn), igamma(tp), a);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
return QColor::fromRgbF(igamma(tp), igamma(tn), igamma(to), a);
|
||||
}
|
||||
}
|
||||
|
||||
qreal h, c, y, a;
|
||||
static qreal luma(const QColor &color)
|
||||
{
|
||||
return lumag(gamma(color.redF()), gamma(color.greenF()), gamma(color.blueF()));
|
||||
}
|
||||
static qreal luma(const QColor& color) { return lumag(gamma(color.redF()), gamma(color.greenF()), gamma(color.blueF())); }
|
||||
|
||||
private:
|
||||
static qreal gamma(qreal n)
|
||||
{
|
||||
return pow(normalize(n), 2.2);
|
||||
}
|
||||
static qreal igamma(qreal n)
|
||||
{
|
||||
return pow(normalize(n), 1.0 / 2.2);
|
||||
}
|
||||
static qreal lumag(qreal r, qreal g, qreal b)
|
||||
{
|
||||
return r * yc[0] + g * yc[1] + b * yc[2];
|
||||
}
|
||||
private:
|
||||
static qreal gamma(qreal n) { return pow(normalize(n), 2.2); }
|
||||
static qreal igamma(qreal n) { return pow(normalize(n), 1.0 / 2.2); }
|
||||
static qreal lumag(qreal r, qreal g, qreal b) { return r * yc[0] + g * yc[1] + b * yc[2]; }
|
||||
};
|
||||
|
||||
static inline qreal mixQreal(qreal a, qreal b, qreal bias)
|
||||
{
|
||||
return a + (b - a) * bias;
|
||||
}
|
||||
//END internal helper functions
|
||||
// END internal helper functions
|
||||
|
||||
qreal Rainbow::luma(const QColor &color)
|
||||
qreal Rainbow::luma(const QColor& color)
|
||||
{
|
||||
return KHCY::luma(color);
|
||||
}
|
||||
|
||||
void Rainbow::getHcy(const QColor &color, qreal *h, qreal *c, qreal *y, qreal *a)
|
||||
void Rainbow::getHcy(const QColor& color, qreal* h, qreal* c, qreal* y, qreal* a)
|
||||
{
|
||||
if (!c || !h || !y)
|
||||
{
|
||||
if (!c || !h || !y) {
|
||||
return;
|
||||
}
|
||||
KHCY khcy(color);
|
||||
*c = khcy.c;
|
||||
*h = khcy.h;
|
||||
*y = khcy.y;
|
||||
if (a)
|
||||
{
|
||||
if (a) {
|
||||
*a = khcy.a;
|
||||
}
|
||||
}
|
||||
|
||||
static qreal contrastRatioForLuma(qreal y1, qreal y2)
|
||||
{
|
||||
if (y1 > y2)
|
||||
{
|
||||
if (y1 > y2) {
|
||||
return (y1 + 0.05) / (y2 + 0.05);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
return (y2 + 0.05) / (y1 + 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
qreal Rainbow::contrastRatio(const QColor &c1, const QColor &c2)
|
||||
qreal Rainbow::contrastRatio(const QColor& c1, const QColor& c2)
|
||||
{
|
||||
return contrastRatioForLuma(luma(c1), luma(c2));
|
||||
}
|
||||
|
||||
QColor Rainbow::lighten(const QColor &color, qreal ky, qreal kc)
|
||||
QColor Rainbow::lighten(const QColor& color, qreal ky, qreal kc)
|
||||
{
|
||||
KHCY c(color);
|
||||
c.y = 1.0 - normalize((1.0 - c.y) * (1.0 - ky));
|
||||
@ -264,7 +210,7 @@ QColor Rainbow::lighten(const QColor &color, qreal ky, qreal kc)
|
||||
return c.qColor();
|
||||
}
|
||||
|
||||
QColor Rainbow::darken(const QColor &color, qreal ky, qreal kc)
|
||||
QColor Rainbow::darken(const QColor& color, qreal ky, qreal kc)
|
||||
{
|
||||
KHCY c(color);
|
||||
c.y = normalize(c.y * (1.0 - ky));
|
||||
@ -272,7 +218,7 @@ QColor Rainbow::darken(const QColor &color, qreal ky, qreal kc)
|
||||
return c.qColor();
|
||||
}
|
||||
|
||||
QColor Rainbow::shade(const QColor &color, qreal ky, qreal kc)
|
||||
QColor Rainbow::shade(const QColor& color, qreal ky, qreal kc)
|
||||
{
|
||||
KHCY c(color);
|
||||
c.y = normalize(c.y + ky);
|
||||
@ -280,7 +226,7 @@ QColor Rainbow::shade(const QColor &color, qreal ky, qreal kc)
|
||||
return c.qColor();
|
||||
}
|
||||
|
||||
static QColor tintHelper(const QColor &base, qreal baseLuma, const QColor &color, qreal amount)
|
||||
static QColor tintHelper(const QColor& base, qreal baseLuma, const QColor& color, qreal amount)
|
||||
{
|
||||
KHCY result(Rainbow::mix(base, color, pow(amount, 0.3)));
|
||||
result.y = mixQreal(baseLuma, result.y, amount);
|
||||
@ -288,55 +234,45 @@ static QColor tintHelper(const QColor &base, qreal baseLuma, const QColor &color
|
||||
return result.qColor();
|
||||
}
|
||||
|
||||
QColor Rainbow::tint(const QColor &base, const QColor &color, qreal amount)
|
||||
QColor Rainbow::tint(const QColor& base, const QColor& color, qreal amount)
|
||||
{
|
||||
if (amount <= 0.0)
|
||||
{
|
||||
if (amount <= 0.0) {
|
||||
return base;
|
||||
}
|
||||
if (amount >= 1.0)
|
||||
{
|
||||
if (amount >= 1.0) {
|
||||
return color;
|
||||
}
|
||||
if (qIsNaN(amount))
|
||||
{
|
||||
if (qIsNaN(amount)) {
|
||||
return base;
|
||||
}
|
||||
|
||||
qreal baseLuma = luma(base); // cache value because luma call is expensive
|
||||
qreal baseLuma = luma(base); // cache value because luma call is expensive
|
||||
double ri = contrastRatioForLuma(baseLuma, luma(color));
|
||||
double rg = 1.0 + ((ri + 1.0) * amount * amount * amount);
|
||||
double u = 1.0, l = 0.0;
|
||||
QColor result;
|
||||
for (int i = 12; i; --i)
|
||||
{
|
||||
for (int i = 12; i; --i) {
|
||||
double a = 0.5 * (l + u);
|
||||
result = tintHelper(base, baseLuma, color, a);
|
||||
double ra = contrastRatioForLuma(baseLuma, luma(result));
|
||||
if (ra > rg)
|
||||
{
|
||||
if (ra > rg) {
|
||||
u = a;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
l = a;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QColor Rainbow::mix(const QColor &c1, const QColor &c2, qreal bias)
|
||||
QColor Rainbow::mix(const QColor& c1, const QColor& c2, qreal bias)
|
||||
{
|
||||
if (bias <= 0.0)
|
||||
{
|
||||
if (bias <= 0.0) {
|
||||
return c1;
|
||||
}
|
||||
if (bias >= 1.0)
|
||||
{
|
||||
if (bias >= 1.0) {
|
||||
return c2;
|
||||
}
|
||||
if (qIsNaN(bias))
|
||||
{
|
||||
if (qIsNaN(bias)) {
|
||||
return c1;
|
||||
}
|
||||
|
||||
@ -348,15 +284,14 @@ QColor Rainbow::mix(const QColor &c1, const QColor &c2, qreal bias)
|
||||
return QColor::fromRgbF(r, g, b, a);
|
||||
}
|
||||
|
||||
QColor Rainbow::overlayColors(const QColor &base, const QColor &paint,
|
||||
QPainter::CompositionMode comp)
|
||||
QColor Rainbow::overlayColors(const QColor& base, const QColor& paint, QPainter::CompositionMode comp)
|
||||
{
|
||||
// This isn't the fastest way, but should be "fast enough".
|
||||
// It's also the only safe way to use QPainter::CompositionMode
|
||||
QImage img(1, 1, QImage::Format_ARGB32_Premultiplied);
|
||||
QPainter p(&img);
|
||||
QColor start = base;
|
||||
start.setAlpha(255); // opaque
|
||||
start.setAlpha(255); // opaque
|
||||
p.fillRect(0, 0, 1, 1, start);
|
||||
p.setCompositionMode(comp);
|
||||
p.fillRect(0, 0, 1, 1, paint);
|
||||
|
@ -1,23 +1,22 @@
|
||||
#include "sys.h"
|
||||
#include <QString>
|
||||
#include "sys.h"
|
||||
|
||||
namespace Sys {
|
||||
struct LsbInfo
|
||||
{
|
||||
struct LsbInfo {
|
||||
QString distributor;
|
||||
QString version;
|
||||
QString description;
|
||||
QString codename;
|
||||
};
|
||||
|
||||
bool main_lsb_info(LsbInfo & out);
|
||||
bool fallback_lsb_info(Sys::LsbInfo & out);
|
||||
void lsb_postprocess(Sys::LsbInfo & lsb, Sys::DistributionInfo & out);
|
||||
bool main_lsb_info(LsbInfo& out);
|
||||
bool fallback_lsb_info(Sys::LsbInfo& out);
|
||||
void lsb_postprocess(Sys::LsbInfo& lsb, Sys::DistributionInfo& out);
|
||||
Sys::DistributionInfo read_lsb_release();
|
||||
|
||||
QString _extract_distribution(const QString & x);
|
||||
QString _extract_version(const QString & x);
|
||||
QString _extract_distribution(const QString& x);
|
||||
QString _extract_version(const QString& x);
|
||||
Sys::DistributionInfo read_legacy_release();
|
||||
|
||||
Sys::DistributionInfo read_os_release();
|
||||
}
|
||||
} // namespace Sys
|
||||
|
@ -1,19 +1,12 @@
|
||||
#pragma once
|
||||
#include <QString>
|
||||
|
||||
namespace Sys
|
||||
{
|
||||
namespace Sys {
|
||||
const uint64_t mebibyte = 1024ull * 1024ull;
|
||||
|
||||
enum class KernelType {
|
||||
Undetermined,
|
||||
Windows,
|
||||
Darwin,
|
||||
Linux
|
||||
};
|
||||
enum class KernelType { Undetermined, Windows, Darwin, Linux };
|
||||
|
||||
struct KernelInfo
|
||||
{
|
||||
struct KernelInfo {
|
||||
QString kernelName;
|
||||
QString kernelVersion;
|
||||
|
||||
@ -26,25 +19,18 @@ struct KernelInfo
|
||||
|
||||
KernelInfo getKernelInfo();
|
||||
|
||||
struct DistributionInfo
|
||||
{
|
||||
struct DistributionInfo {
|
||||
DistributionInfo operator+(const DistributionInfo& rhs) const
|
||||
{
|
||||
DistributionInfo out;
|
||||
if(!distributionName.isEmpty())
|
||||
{
|
||||
if (!distributionName.isEmpty()) {
|
||||
out.distributionName = distributionName;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
out.distributionName = rhs.distributionName;
|
||||
}
|
||||
if(!distributionVersion.isEmpty())
|
||||
{
|
||||
if (!distributionVersion.isEmpty()) {
|
||||
out.distributionVersion = distributionVersion;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
out.distributionVersion = rhs.distributionVersion;
|
||||
}
|
||||
return out;
|
||||
@ -56,4 +42,4 @@ struct DistributionInfo
|
||||
DistributionInfo getDistributionInfo();
|
||||
|
||||
uint64_t getSystemRam();
|
||||
}
|
||||
} // namespace Sys
|
||||
|
@ -29,14 +29,14 @@ SOFTWARE.
|
||||
|
||||
#include "distroutils.h"
|
||||
|
||||
#include <QStringList>
|
||||
#include <QMap>
|
||||
#include <QSettings>
|
||||
#include <QFile>
|
||||
#include <QProcess>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QMap>
|
||||
#include <QProcess>
|
||||
#include <QRegularExpression>
|
||||
#include <QSettings>
|
||||
#include <QStringList>
|
||||
|
||||
#include <functional>
|
||||
|
||||
@ -46,38 +46,27 @@ Sys::DistributionInfo Sys::read_os_release()
|
||||
QStringList files = { "/etc/os-release", "/usr/lib/os-release" };
|
||||
QString name;
|
||||
QString version;
|
||||
for (auto &file: files)
|
||||
{
|
||||
if(!QFile::exists(file))
|
||||
{
|
||||
for (auto& file : files) {
|
||||
if (!QFile::exists(file)) {
|
||||
continue;
|
||||
}
|
||||
QSettings settings(file, QSettings::IniFormat);
|
||||
if(settings.contains("ID"))
|
||||
{
|
||||
if (settings.contains("ID")) {
|
||||
name = settings.value("ID").toString().toLower();
|
||||
}
|
||||
else if (settings.contains("NAME"))
|
||||
{
|
||||
} else if (settings.contains("NAME")) {
|
||||
name = settings.value("NAME").toString().toLower();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(settings.contains("VERSION_ID"))
|
||||
{
|
||||
if (settings.contains("VERSION_ID")) {
|
||||
version = settings.value("VERSION_ID").toString().toLower();
|
||||
}
|
||||
else if(settings.contains("VERSION"))
|
||||
{
|
||||
} else if (settings.contains("VERSION")) {
|
||||
version = settings.value("VERSION").toString().toLower();
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(name.isEmpty())
|
||||
{
|
||||
if (name.isEmpty()) {
|
||||
return out;
|
||||
}
|
||||
out.distributionName = name;
|
||||
@ -85,33 +74,31 @@ Sys::DistributionInfo Sys::read_os_release()
|
||||
return out;
|
||||
}
|
||||
|
||||
bool Sys::main_lsb_info(Sys::LsbInfo & out)
|
||||
bool Sys::main_lsb_info(Sys::LsbInfo& out)
|
||||
{
|
||||
int status=0;
|
||||
int status = 0;
|
||||
QProcess lsbProcess;
|
||||
QStringList arguments;
|
||||
arguments << "-a";
|
||||
lsbProcess.start("lsb_release", arguments);
|
||||
lsbProcess.start("lsb_release", arguments);
|
||||
lsbProcess.waitForFinished();
|
||||
status = lsbProcess.exitStatus();
|
||||
QString output = lsbProcess.readAllStandardOutput();
|
||||
qDebug() << output;
|
||||
lsbProcess.close();
|
||||
if(status == 0)
|
||||
{
|
||||
if (status == 0) {
|
||||
auto lines = output.split('\n');
|
||||
for(auto line:lines)
|
||||
{
|
||||
for (auto line : lines) {
|
||||
int index = line.indexOf(':');
|
||||
auto key = line.left(index).trimmed();
|
||||
auto value = line.mid(index + 1).toLower().trimmed();
|
||||
if(key == "Distributor ID")
|
||||
if (key == "Distributor ID")
|
||||
out.distributor = value;
|
||||
else if(key == "Release")
|
||||
else if (key == "Release")
|
||||
out.version = value;
|
||||
else if(key == "Description")
|
||||
else if (key == "Description")
|
||||
out.description = value;
|
||||
else if(key == "Codename")
|
||||
else if (key == "Codename")
|
||||
out.codename = value;
|
||||
}
|
||||
return !out.distributor.isEmpty();
|
||||
@ -119,7 +106,7 @@ bool Sys::main_lsb_info(Sys::LsbInfo & out)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Sys::fallback_lsb_info(Sys::LsbInfo & out)
|
||||
bool Sys::fallback_lsb_info(Sys::LsbInfo& out)
|
||||
{
|
||||
// running lsb_release failed, try to read the file instead
|
||||
// /etc/lsb-release format, if the file even exists, is non-standard.
|
||||
@ -127,15 +114,12 @@ bool Sys::fallback_lsb_info(Sys::LsbInfo & out)
|
||||
// distributions install an /etc/lsb-release as part of the base
|
||||
// distribution, but `lsb_release` remains optional.
|
||||
QString file = "/etc/lsb-release";
|
||||
if (QFile::exists(file))
|
||||
{
|
||||
if (QFile::exists(file)) {
|
||||
QSettings settings(file, QSettings::IniFormat);
|
||||
if(settings.contains("DISTRIB_ID"))
|
||||
{
|
||||
if (settings.contains("DISTRIB_ID")) {
|
||||
out.distributor = settings.value("DISTRIB_ID").toString().toLower();
|
||||
}
|
||||
if(settings.contains("DISTRIB_RELEASE"))
|
||||
{
|
||||
if (settings.contains("DISTRIB_RELEASE")) {
|
||||
out.version = settings.value("DISTRIB_RELEASE").toString().toLower();
|
||||
}
|
||||
return !out.distributor.isEmpty();
|
||||
@ -143,48 +127,34 @@ bool Sys::fallback_lsb_info(Sys::LsbInfo & out)
|
||||
return false;
|
||||
}
|
||||
|
||||
void Sys::lsb_postprocess(Sys::LsbInfo & lsb, Sys::DistributionInfo & out)
|
||||
void Sys::lsb_postprocess(Sys::LsbInfo& lsb, Sys::DistributionInfo& out)
|
||||
{
|
||||
QString dist = lsb.distributor;
|
||||
QString vers = lsb.version;
|
||||
if(dist.startsWith("redhatenterprise"))
|
||||
{
|
||||
if (dist.startsWith("redhatenterprise")) {
|
||||
dist = "rhel";
|
||||
}
|
||||
else if(dist == "archlinux")
|
||||
{
|
||||
} else if (dist == "archlinux") {
|
||||
dist = "arch";
|
||||
}
|
||||
else if (dist.startsWith("suse"))
|
||||
{
|
||||
if(lsb.description.startsWith("opensuse"))
|
||||
{
|
||||
} else if (dist.startsWith("suse")) {
|
||||
if (lsb.description.startsWith("opensuse")) {
|
||||
dist = "opensuse";
|
||||
}
|
||||
else if (lsb.description.startsWith("suse linux enterprise"))
|
||||
{
|
||||
} else if (lsb.description.startsWith("suse linux enterprise")) {
|
||||
dist = "sles";
|
||||
}
|
||||
}
|
||||
else if (dist == "debian" and vers == "testing")
|
||||
{
|
||||
} else if (dist == "debian" and vers == "testing") {
|
||||
vers = lsb.codename;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// ubuntu, debian, gentoo, scientific, slackware, ... ?
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||
auto parts = dist.split(QRegularExpression("\\s+"), Qt::SkipEmptyParts);
|
||||
#else
|
||||
auto parts = dist.split(QRegularExpression("\\s+"), QString::SkipEmptyParts);
|
||||
#endif
|
||||
if(parts.size())
|
||||
{
|
||||
if (parts.size()) {
|
||||
dist = parts[0];
|
||||
}
|
||||
}
|
||||
if(!dist.isEmpty())
|
||||
{
|
||||
if (!dist.isEmpty()) {
|
||||
out.distributionName = dist;
|
||||
out.distributionVersion = vers;
|
||||
}
|
||||
@ -193,10 +163,8 @@ void Sys::lsb_postprocess(Sys::LsbInfo & lsb, Sys::DistributionInfo & out)
|
||||
Sys::DistributionInfo Sys::read_lsb_release()
|
||||
{
|
||||
LsbInfo lsb;
|
||||
if(!main_lsb_info(lsb))
|
||||
{
|
||||
if(!fallback_lsb_info(lsb))
|
||||
{
|
||||
if (!main_lsb_info(lsb)) {
|
||||
if (!fallback_lsb_info(lsb)) {
|
||||
return Sys::DistributionInfo();
|
||||
}
|
||||
}
|
||||
@ -205,15 +173,13 @@ Sys::DistributionInfo Sys::read_lsb_release()
|
||||
return out;
|
||||
}
|
||||
|
||||
QString Sys::_extract_distribution(const QString & x)
|
||||
QString Sys::_extract_distribution(const QString& x)
|
||||
{
|
||||
QString release = x.toLower();
|
||||
if (release.startsWith("red hat enterprise"))
|
||||
{
|
||||
if (release.startsWith("red hat enterprise")) {
|
||||
return "rhel";
|
||||
}
|
||||
if (release.startsWith("suse linux enterprise"))
|
||||
{
|
||||
if (release.startsWith("suse linux enterprise")) {
|
||||
return "sles";
|
||||
}
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||
@ -221,14 +187,13 @@ QString Sys::_extract_distribution(const QString & x)
|
||||
#else
|
||||
QStringList list = release.split(QRegularExpression("\\s+"), QString::SkipEmptyParts);
|
||||
#endif
|
||||
if(list.size())
|
||||
{
|
||||
if (list.size()) {
|
||||
return list[0];
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString Sys::_extract_version(const QString & x)
|
||||
QString Sys::_extract_version(const QString& x)
|
||||
{
|
||||
QRegularExpression versionish_string(QRegularExpression::anchoredPattern("\\d+(?:\\.\\d+)*$"));
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||
@ -236,11 +201,9 @@ QString Sys::_extract_version(const QString & x)
|
||||
#else
|
||||
QStringList list = x.split(QRegularExpression("\\s+"), QString::SkipEmptyParts);
|
||||
#endif
|
||||
for(int i = list.size() - 1; i >= 0; --i)
|
||||
{
|
||||
for (int i = list.size() - 1; i >= 0; --i) {
|
||||
QString chunk = list[i];
|
||||
if(versionish_string.match(chunk).hasMatch())
|
||||
{
|
||||
if (versionish_string.match(chunk).hasMatch()) {
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
@ -249,43 +212,35 @@ QString Sys::_extract_version(const QString & x)
|
||||
|
||||
Sys::DistributionInfo Sys::read_legacy_release()
|
||||
{
|
||||
struct checkEntry
|
||||
{
|
||||
struct checkEntry {
|
||||
QString file;
|
||||
std::function<QString(const QString &)> extract_distro;
|
||||
std::function<QString(const QString &)> extract_version;
|
||||
std::function<QString(const QString&)> extract_distro;
|
||||
std::function<QString(const QString&)> extract_version;
|
||||
};
|
||||
QList<checkEntry> checks =
|
||||
{
|
||||
{"/etc/arch-release", [](const QString &){ return "arch";}, [](const QString &){ return "rolling";}},
|
||||
{"/etc/slackware-version", &Sys::_extract_distribution, &Sys::_extract_version},
|
||||
{QString(), &Sys::_extract_distribution, &Sys::_extract_version},
|
||||
{"/etc/debian_version", [](const QString &){ return "debian";}, [](const QString & x){ return x;}},
|
||||
QList<checkEntry> checks = {
|
||||
{ "/etc/arch-release", [](const QString&) { return "arch"; }, [](const QString&) { return "rolling"; } },
|
||||
{ "/etc/slackware-version", &Sys::_extract_distribution, &Sys::_extract_version },
|
||||
{ QString(), &Sys::_extract_distribution, &Sys::_extract_version },
|
||||
{ "/etc/debian_version", [](const QString&) { return "debian"; }, [](const QString& x) { return x; } },
|
||||
};
|
||||
for(auto & check: checks)
|
||||
{
|
||||
for (auto& check : checks) {
|
||||
QStringList files;
|
||||
if(check.file.isNull())
|
||||
{
|
||||
if (check.file.isNull()) {
|
||||
QDir etcDir("/etc");
|
||||
etcDir.setNameFilters({"*-release"});
|
||||
etcDir.setNameFilters({ "*-release" });
|
||||
etcDir.setFilter(QDir::Files | QDir::NoDot | QDir::NoDotDot | QDir::Readable | QDir::Hidden);
|
||||
files = etcDir.entryList();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
files.append(check.file);
|
||||
}
|
||||
for (auto file : files)
|
||||
{
|
||||
for (auto file : files) {
|
||||
QFile relfile(file);
|
||||
if(!relfile.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
if (!relfile.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
continue;
|
||||
QString contents = QString::fromUtf8(relfile.readLine()).trimmed();
|
||||
QString dist = check.extract_distro(contents);
|
||||
QString vers = check.extract_version(contents);
|
||||
if(!dist.isEmpty())
|
||||
{
|
||||
if (!dist.isEmpty()) {
|
||||
Sys::DistributionInfo out;
|
||||
out.distributionName = dist;
|
||||
out.distributionVersion = vers;
|
||||
@ -295,4 +250,3 @@ Sys::DistributionInfo Sys::read_legacy_release()
|
||||
}
|
||||
return Sys::DistributionInfo();
|
||||
}
|
||||
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QDebug>
|
||||
|
||||
Sys::KernelInfo Sys::getKernelInfo()
|
||||
{
|
||||
@ -22,18 +22,16 @@ Sys::KernelInfo Sys::getKernelInfo()
|
||||
out.kernelMinor = 0;
|
||||
out.kernelPatch = 0;
|
||||
auto sections = release.split('-');
|
||||
if(sections.size() >= 1) {
|
||||
if (sections.size() >= 1) {
|
||||
auto versionParts = sections[0].split('.');
|
||||
if(versionParts.size() >= 3) {
|
||||
if (versionParts.size() >= 3) {
|
||||
out.kernelMajor = versionParts[0].toInt();
|
||||
out.kernelMinor = versionParts[1].toInt();
|
||||
out.kernelPatch = versionParts[2].toInt();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
qWarning() << "Not enough version numbers in " << sections[0] << " found " << versionParts.size();
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
qWarning() << "Not enough '-' sections in " << release << " found " << sections.size();
|
||||
}
|
||||
return out;
|
||||
@ -45,12 +43,9 @@ uint64_t Sys::getSystemRam()
|
||||
{
|
||||
uint64_t memsize;
|
||||
size_t memsizesize = sizeof(memsize);
|
||||
if(!sysctlbyname("hw.memsize", &memsize, &memsizesize, NULL, 0))
|
||||
{
|
||||
if (!sysctlbyname("hw.memsize", &memsize, &memsizesize, NULL, 0)) {
|
||||
return memsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -2,11 +2,9 @@
|
||||
|
||||
#include <sys.h>
|
||||
|
||||
class SysTest : public QObject
|
||||
{
|
||||
class SysTest : public QObject {
|
||||
Q_OBJECT
|
||||
private
|
||||
slots:
|
||||
private slots:
|
||||
|
||||
void test_kernelNotNull()
|
||||
{
|
||||
@ -14,15 +12,15 @@ slots:
|
||||
QVERIFY(!kinfo.kernelName.isEmpty());
|
||||
QVERIFY(kinfo.kernelVersion != "0.0");
|
||||
}
|
||||
/*
|
||||
void test_systemDistroNotNull()
|
||||
{
|
||||
auto kinfo = Sys::getDistributionInfo();
|
||||
QVERIFY(!kinfo.distributionName.isEmpty());
|
||||
QVERIFY(!kinfo.distributionVersion.isEmpty());
|
||||
qDebug() << "Distro: " << kinfo.distributionName << "version" << kinfo.distributionVersion;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
void test_systemDistroNotNull()
|
||||
{
|
||||
auto kinfo = Sys::getDistributionInfo();
|
||||
QVERIFY(!kinfo.distributionName.isEmpty());
|
||||
QVERIFY(!kinfo.distributionVersion.isEmpty());
|
||||
qDebug() << "Distro: " << kinfo.distributionName << "version" << kinfo.distributionVersion;
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
QTEST_GUILESS_MAIN(SysTest)
|
||||
|
@ -6,9 +6,9 @@
|
||||
#include <fstream>
|
||||
#include <limits>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QDebug>
|
||||
|
||||
Sys::KernelInfo Sys::getKernelInfo()
|
||||
{
|
||||
@ -27,18 +27,16 @@ Sys::KernelInfo Sys::getKernelInfo()
|
||||
out.kernelMinor = 0;
|
||||
out.kernelPatch = 0;
|
||||
auto sections = release.split('-');
|
||||
if(sections.size() >= 1) {
|
||||
if (sections.size() >= 1) {
|
||||
auto versionParts = sections[0].split('.');
|
||||
if(versionParts.size() >= 3) {
|
||||
if (versionParts.size() >= 3) {
|
||||
out.kernelMajor = versionParts[0].toInt();
|
||||
out.kernelMinor = versionParts[1].toInt();
|
||||
out.kernelPatch = versionParts[2].toInt();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
qWarning() << "Not enough version numbers in " << sections[0] << " found " << versionParts.size();
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
qWarning() << "Not enough '-' sections in " << release << " found " << sections.size();
|
||||
}
|
||||
return out;
|
||||
@ -49,17 +47,12 @@ uint64_t Sys::getSystemRam()
|
||||
std::string token;
|
||||
#ifdef Q_OS_LINUX
|
||||
std::ifstream file("/proc/meminfo");
|
||||
while(file >> token)
|
||||
{
|
||||
if(token == "MemTotal:")
|
||||
{
|
||||
while (file >> token) {
|
||||
if (token == "MemTotal:") {
|
||||
uint64_t mem;
|
||||
if(file >> mem)
|
||||
{
|
||||
if (file >> mem) {
|
||||
return mem * 1024ull;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -68,18 +61,16 @@ uint64_t Sys::getSystemRam()
|
||||
}
|
||||
#elif defined(Q_OS_FREEBSD)
|
||||
char buff[512];
|
||||
FILE *fp = popen("sysctl hw.physmem", "r");
|
||||
if (fp != NULL)
|
||||
{
|
||||
while(fgets(buff, 512, fp) != NULL)
|
||||
{
|
||||
std::string str(buff);
|
||||
uint64_t mem = std::stoull(str.substr(12, std::string::npos));
|
||||
return mem * 1024ull;
|
||||
}
|
||||
FILE* fp = popen("sysctl hw.physmem", "r");
|
||||
if (fp != NULL) {
|
||||
while (fgets(buff, 512, fp) != NULL) {
|
||||
std::string str(buff);
|
||||
uint64_t mem = std::stoull(str.substr(12, std::string::npos));
|
||||
return mem * 1024ull;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0; // nothing found
|
||||
return 0; // nothing found
|
||||
}
|
||||
|
||||
Sys::DistributionInfo Sys::getDistributionInfo()
|
||||
@ -88,18 +79,13 @@ Sys::DistributionInfo Sys::getDistributionInfo()
|
||||
DistributionInfo lsb_info = read_lsb_release();
|
||||
DistributionInfo legacy_info = read_legacy_release();
|
||||
DistributionInfo result = systemd_info + lsb_info + legacy_info;
|
||||
if(result.distributionName.isNull())
|
||||
{
|
||||
if (result.distributionName.isNull()) {
|
||||
result.distributionName = "unknown";
|
||||
}
|
||||
if(result.distributionVersion.isNull())
|
||||
{
|
||||
if(result.distributionName == "arch")
|
||||
{
|
||||
if (result.distributionVersion.isNull()) {
|
||||
if (result.distributionName == "arch") {
|
||||
result.distributionVersion = "rolling";
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
result.distributionVersion = "unknown";
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ uint64_t Sys::getSystemRam()
|
||||
{
|
||||
MEMORYSTATUSEX status;
|
||||
status.dwLength = sizeof(status);
|
||||
GlobalMemoryStatusEx( &status );
|
||||
GlobalMemoryStatusEx(&status);
|
||||
// bytes
|
||||
return (uint64_t)status.ullTotalPhys;
|
||||
}
|
||||
|
Reference in New Issue
Block a user