mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
Make Nexus own and start the LoginScreen
And start implementing some of the required methods to make Core, LoginScreen and Nexus use Profile
This commit is contained in:
parent
7d6167d90c
commit
032c561e62
|
@ -24,6 +24,7 @@
|
||||||
#include "src/audio.h"
|
#include "src/audio.h"
|
||||||
#include "src/profilelocker.h"
|
#include "src/profilelocker.h"
|
||||||
#include "src/avatarbroadcaster.h"
|
#include "src/avatarbroadcaster.h"
|
||||||
|
#include "src/profile.h"
|
||||||
#include "corefile.h"
|
#include "corefile.h"
|
||||||
|
|
||||||
#include <tox/tox.h>
|
#include <tox/tox.h>
|
||||||
|
@ -52,11 +53,9 @@ QThread* Core::coreThread{nullptr};
|
||||||
|
|
||||||
#define MAX_GROUP_MESSAGE_LEN 1024
|
#define MAX_GROUP_MESSAGE_LEN 1024
|
||||||
|
|
||||||
Core::Core(QThread *CoreThread, QString loadPath) :
|
Core::Core(QThread *CoreThread, Profile& profile) :
|
||||||
tox(nullptr), toxav(nullptr), loadPath(loadPath), ready{false}
|
tox(nullptr), toxav(nullptr), profile(profile), ready{false}
|
||||||
{
|
{
|
||||||
qDebug() << "loading Tox from" << loadPath;
|
|
||||||
|
|
||||||
coreThread = CoreThread;
|
coreThread = CoreThread;
|
||||||
|
|
||||||
Audio::getInstance();
|
Audio::getInstance();
|
||||||
|
@ -239,7 +238,7 @@ void Core::start()
|
||||||
{
|
{
|
||||||
qDebug() << "Starting up";
|
qDebug() << "Starting up";
|
||||||
|
|
||||||
QByteArray savedata = loadToxSave(loadPath);
|
QByteArray savedata = profile.loadToxSave();
|
||||||
|
|
||||||
make_tox(savedata);
|
make_tox(savedata);
|
||||||
|
|
||||||
|
@ -888,7 +887,7 @@ QString Core::sanitize(QString name)
|
||||||
QByteArray Core::loadToxSave(QString path)
|
QByteArray Core::loadToxSave(QString path)
|
||||||
{
|
{
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
loadPath = ""; // if not empty upon return, then user forgot a password and is switching
|
//loadPath = ""; // if not empty upon return, then user forgot a password and is switching
|
||||||
|
|
||||||
// If we can't get a lock, then another instance is already using that profile
|
// If we can't get a lock, then another instance is already using that profile
|
||||||
while (!ProfileLocker::lock(QFileInfo(path).baseName()))
|
while (!ProfileLocker::lock(QFileInfo(path).baseName()))
|
||||||
|
@ -1019,10 +1018,10 @@ void Core::switchConfiguration(const QString& _profile)
|
||||||
emit selfAvatarChanged(QPixmap(":/img/contact_dark.svg"));
|
emit selfAvatarChanged(QPixmap(":/img/contact_dark.svg"));
|
||||||
emit blockingClearContacts(); // we need this to block, but signals are required for thread safety
|
emit blockingClearContacts(); // we need this to block, but signals are required for thread safety
|
||||||
|
|
||||||
if (profile.isEmpty())
|
//if (profile.isEmpty())
|
||||||
loadPath = "";
|
//loadPath = "";
|
||||||
else
|
//else
|
||||||
loadPath = QDir(Settings::getSettingsDirPath()).filePath(profile + TOX_EXT);
|
// loadPath = QDir(Settings::getSettingsDirPath()).filePath(profile + TOX_EXT);
|
||||||
|
|
||||||
Settings::getInstance().switchProfile(profile);
|
Settings::getInstance().switchProfile(profile);
|
||||||
HistoryKeeper::resetInstance();
|
HistoryKeeper::resetInstance();
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "coredefines.h"
|
#include "coredefines.h"
|
||||||
#include "toxid.h"
|
#include "toxid.h"
|
||||||
|
|
||||||
|
class Profile;
|
||||||
template <typename T> class QList;
|
template <typename T> class QList;
|
||||||
class QTimer;
|
class QTimer;
|
||||||
class QString;
|
class QString;
|
||||||
|
@ -45,7 +46,7 @@ class Core : public QObject
|
||||||
public:
|
public:
|
||||||
enum PasswordType {ptMain = 0, ptHistory, ptCounter};
|
enum PasswordType {ptMain = 0, ptHistory, ptCounter};
|
||||||
|
|
||||||
explicit Core(QThread* coreThread, QString initialLoadPath);
|
explicit Core(QThread* coreThread, Profile& profile);
|
||||||
static Core* getInstance(); ///< Returns the global widget's Core instance
|
static Core* getInstance(); ///< Returns the global widget's Core instance
|
||||||
~Core();
|
~Core();
|
||||||
|
|
||||||
|
@ -292,7 +293,7 @@ private:
|
||||||
Tox* tox;
|
Tox* tox;
|
||||||
ToxAv* toxav;
|
ToxAv* toxav;
|
||||||
QTimer *toxTimer, *fileTimer; //, *saveTimer;
|
QTimer *toxTimer, *fileTimer; //, *saveTimer;
|
||||||
QString loadPath; // meaningless after start() is called
|
Profile& profile;
|
||||||
int dhtServerId;
|
int dhtServerId;
|
||||||
static ToxCall calls[TOXAV_MAX_CALLS];
|
static ToxCall calls[TOXAV_MAX_CALLS];
|
||||||
#ifdef QTOX_FILTER_AUDIO
|
#ifdef QTOX_FILTER_AUDIO
|
||||||
|
|
|
@ -110,7 +110,7 @@ QByteArray Core::encryptData(const QByteArray& data, PasswordType passtype)
|
||||||
if (!tox_pass_key_encrypt(reinterpret_cast<const uint8_t*>(data.data()), data.size(),
|
if (!tox_pass_key_encrypt(reinterpret_cast<const uint8_t*>(data.data()), data.size(),
|
||||||
pwsaltedkeys[passtype], encrypted, nullptr))
|
pwsaltedkeys[passtype], encrypted, nullptr))
|
||||||
{
|
{
|
||||||
qWarning() << "encryptData: encryption failed";
|
qWarning() << "Encryption failed";
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
}
|
}
|
||||||
return QByteArray(reinterpret_cast<char*>(encrypted), data.size() + TOX_PASS_ENCRYPTION_EXTRA_LENGTH);
|
return QByteArray(reinterpret_cast<char*>(encrypted), data.size() + TOX_PASS_ENCRYPTION_EXTRA_LENGTH);
|
||||||
|
@ -126,7 +126,7 @@ QByteArray Core::decryptData(const QByteArray& data, PasswordType passtype)
|
||||||
if (!tox_pass_key_decrypt(reinterpret_cast<const uint8_t*>(data.data()), data.size(),
|
if (!tox_pass_key_decrypt(reinterpret_cast<const uint8_t*>(data.data()), data.size(),
|
||||||
pwsaltedkeys[passtype], decrypted, nullptr))
|
pwsaltedkeys[passtype], decrypted, nullptr))
|
||||||
{
|
{
|
||||||
qWarning() << "decryptData: decryption failed";
|
qWarning() << "Decryption failed";
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
}
|
}
|
||||||
return QByteArray(reinterpret_cast<char*>(decrypted), sz);
|
return QByteArray(reinterpret_cast<char*>(decrypted), sz);
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
See the COPYING file for more details.
|
See the COPYING file for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "toxme.h"
|
||||||
#include "widget/widget.h"
|
#include "widget/widget.h"
|
||||||
#include "misc/settings.h"
|
#include "misc/settings.h"
|
||||||
#include "src/nexus.h"
|
#include "src/nexus.h"
|
||||||
|
@ -20,6 +21,7 @@
|
||||||
#include "src/widget/toxsave.h"
|
#include "src/widget/toxsave.h"
|
||||||
#include "src/autoupdate.h"
|
#include "src/autoupdate.h"
|
||||||
#include "src/profilelocker.h"
|
#include "src/profilelocker.h"
|
||||||
|
#include "src/widget/loginscreen.h"
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QCommandLineParser>
|
#include <QCommandLineParser>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
@ -31,9 +33,6 @@
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
|
||||||
#include <sodium.h>
|
#include <sodium.h>
|
||||||
|
|
||||||
#include "toxme.h"
|
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#define EXIT_UPDATE_MACX 218 //We track our state using unique exit codes when debugging
|
#define EXIT_UPDATE_MACX 218 //We track our state using unique exit codes when debugging
|
||||||
|
@ -292,7 +291,6 @@ int main(int argc, char *argv[])
|
||||||
Nexus::getInstance().start();
|
Nexus::getInstance().start();
|
||||||
|
|
||||||
// Run
|
// Run
|
||||||
a.setQuitOnLastWindowClosed(false);
|
|
||||||
int errorcode = a.exec();
|
int errorcode = a.exec();
|
||||||
|
|
||||||
#ifdef LOG_TO_FILE
|
#ifdef LOG_TO_FILE
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
#include "nexus.h"
|
#include "nexus.h"
|
||||||
|
#include "profile.h"
|
||||||
#include "src/core/core.h"
|
#include "src/core/core.h"
|
||||||
#include "misc/settings.h"
|
#include "misc/settings.h"
|
||||||
#include "video/camerasource.h"
|
#include "video/camerasource.h"
|
||||||
#include "widget/gui.h"
|
#include "widget/gui.h"
|
||||||
|
#include "widget/loginscreen.h"
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QImageReader>
|
#include <QImageReader>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
#include <src/widget/androidgui.h>
|
#include <src/widget/androidgui.h>
|
||||||
|
@ -18,18 +22,14 @@ static Nexus* nexus{nullptr};
|
||||||
|
|
||||||
Nexus::Nexus(QObject *parent) :
|
Nexus::Nexus(QObject *parent) :
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
core{nullptr},
|
profile{nullptr},
|
||||||
coreThread{nullptr},
|
|
||||||
widget{nullptr},
|
widget{nullptr},
|
||||||
androidgui{nullptr},
|
androidgui{nullptr}
|
||||||
started{false}
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Nexus::~Nexus()
|
Nexus::~Nexus()
|
||||||
{
|
{
|
||||||
delete core;
|
|
||||||
delete coreThread;
|
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
delete androidgui;
|
delete androidgui;
|
||||||
#else
|
#else
|
||||||
|
@ -39,9 +39,6 @@ Nexus::~Nexus()
|
||||||
|
|
||||||
void Nexus::start()
|
void Nexus::start()
|
||||||
{
|
{
|
||||||
if (started)
|
|
||||||
return;
|
|
||||||
|
|
||||||
qDebug() << "Starting up";
|
qDebug() << "Starting up";
|
||||||
|
|
||||||
// Setup the environment
|
// Setup the environment
|
||||||
|
@ -59,19 +56,30 @@ void Nexus::start()
|
||||||
qRegisterMetaType<Core::PasswordType>("Core::PasswordType");
|
qRegisterMetaType<Core::PasswordType>("Core::PasswordType");
|
||||||
qRegisterMetaType<std::shared_ptr<VideoFrame>>("std::shared_ptr<VideoFrame>");
|
qRegisterMetaType<std::shared_ptr<VideoFrame>>("std::shared_ptr<VideoFrame>");
|
||||||
|
|
||||||
|
// Create and show login screen
|
||||||
|
loginScreen = new LoginScreen();
|
||||||
|
showLogin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nexus::showLogin()
|
||||||
|
{
|
||||||
|
((QApplication*)qApp)->setQuitOnLastWindowClosed(true);
|
||||||
|
loginScreen->reset();
|
||||||
|
loginScreen->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nexus::showMainGUI()
|
||||||
|
{
|
||||||
|
assert(profile);
|
||||||
|
|
||||||
|
((QApplication*)qApp)->setQuitOnLastWindowClosed(false);
|
||||||
|
loginScreen->close();
|
||||||
|
|
||||||
// Create GUI
|
// Create GUI
|
||||||
#ifndef Q_OS_ANDROID
|
#ifndef Q_OS_ANDROID
|
||||||
widget = Widget::getInstance();
|
widget = Widget::getInstance();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Create Core
|
|
||||||
QString profilePath = Settings::getInstance().detectProfile();
|
|
||||||
coreThread = new QThread(this);
|
|
||||||
coreThread->setObjectName("qTox Core");
|
|
||||||
core = new Core(coreThread, profilePath);
|
|
||||||
core->moveToThread(coreThread);
|
|
||||||
connect(coreThread, &QThread::started, core, &Core::start);
|
|
||||||
|
|
||||||
// Start GUI
|
// Start GUI
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
androidgui = new AndroidGUI;
|
androidgui = new AndroidGUI;
|
||||||
|
@ -88,6 +96,7 @@ void Nexus::start()
|
||||||
GUI::setEnabled(false);
|
GUI::setEnabled(false);
|
||||||
|
|
||||||
// Connections
|
// Connections
|
||||||
|
Core* core = profile->getCore();
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
connect(core, &Core::connected, androidgui, &AndroidGUI::onConnected);
|
connect(core, &Core::connected, androidgui, &AndroidGUI::onConnected);
|
||||||
connect(core, &Core::disconnected, androidgui, &AndroidGUI::onDisconnected);
|
connect(core, &Core::disconnected, androidgui, &AndroidGUI::onDisconnected);
|
||||||
|
@ -138,10 +147,7 @@ void Nexus::start()
|
||||||
connect(widget, &Widget::changeProfile, core, &Core::switchConfiguration);
|
connect(widget, &Widget::changeProfile, core, &Core::switchConfiguration);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Start Core
|
profile->startCore();
|
||||||
coreThread->start();
|
|
||||||
|
|
||||||
started = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Nexus& Nexus::getInstance()
|
Nexus& Nexus::getInstance()
|
||||||
|
@ -160,7 +166,20 @@ void Nexus::destroyInstance()
|
||||||
|
|
||||||
Core* Nexus::getCore()
|
Core* Nexus::getCore()
|
||||||
{
|
{
|
||||||
return getInstance().core;
|
Nexus& nexus = getInstance();
|
||||||
|
if (!nexus.profile)
|
||||||
|
return nullptr;
|
||||||
|
return nexus.profile->getCore();
|
||||||
|
}
|
||||||
|
|
||||||
|
Profile* Nexus::getProfile()
|
||||||
|
{
|
||||||
|
return getInstance().profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nexus::setProfile(Profile* profile)
|
||||||
|
{
|
||||||
|
getInstance().profile = profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
AndroidGUI* Nexus::getAndroidGUI()
|
AndroidGUI* Nexus::getAndroidGUI()
|
||||||
|
|
18
src/nexus.h
18
src/nexus.h
|
@ -3,10 +3,11 @@
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
class QThread;
|
|
||||||
class Core;
|
|
||||||
class Widget;
|
class Widget;
|
||||||
class AndroidGUI;
|
class AndroidGUI;
|
||||||
|
class Profile;
|
||||||
|
class LoginScreen;
|
||||||
|
class Core;
|
||||||
|
|
||||||
/// This class is in charge of connecting various systems together
|
/// This class is in charge of connecting various systems together
|
||||||
/// and forwarding signals appropriately to the right objects
|
/// and forwarding signals appropriately to the right objects
|
||||||
|
@ -15,11 +16,17 @@ class Nexus : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
void start(); ///< Will initialise the systems (GUI, Core, ...)
|
void start(); ///< Sets up invariants and calls showLogin
|
||||||
|
void showLogin(); ///< Shows the login screen
|
||||||
|
/// Hides the login screen and shows the GUI for the given profile.
|
||||||
|
/// Will delete the current GUI, if it exists.
|
||||||
|
void showMainGUI();
|
||||||
|
|
||||||
static Nexus& getInstance();
|
static Nexus& getInstance();
|
||||||
static void destroyInstance();
|
static void destroyInstance();
|
||||||
static Core* getCore(); ///< Will return 0 if not started
|
static Core* getCore(); ///< Will return 0 if not started
|
||||||
|
static Profile* getProfile(); ///< Will return 0 if not started
|
||||||
|
static void setProfile(Profile* profile); ///< Delete the current profile, if any, and replaces it
|
||||||
static AndroidGUI* getAndroidGUI(); ///< Will return 0 if not started
|
static AndroidGUI* getAndroidGUI(); ///< Will return 0 if not started
|
||||||
static Widget* getDesktopGUI(); ///< Will return 0 if not started
|
static Widget* getDesktopGUI(); ///< Will return 0 if not started
|
||||||
static QString getSupportedImageFilter();
|
static QString getSupportedImageFilter();
|
||||||
|
@ -30,11 +37,10 @@ private:
|
||||||
~Nexus();
|
~Nexus();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Core* core;
|
Profile* profile;
|
||||||
QThread* coreThread;
|
|
||||||
Widget* widget;
|
Widget* widget;
|
||||||
AndroidGUI* androidgui;
|
AndroidGUI* androidgui;
|
||||||
bool started;
|
LoginScreen* loginScreen;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // NEXUS_H
|
#endif // NEXUS_H
|
||||||
|
|
116
src/profile.cpp
116
src/profile.cpp
|
@ -1,19 +1,48 @@
|
||||||
#include "profile.h"
|
#include "profile.h"
|
||||||
|
#include "profilelocker.h"
|
||||||
#include "src/misc/settings.h"
|
#include "src/misc/settings.h"
|
||||||
|
#include "src/core/core.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
#include <QThread>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
QVector<QString> Profile::profiles;
|
QVector<QString> Profile::profiles;
|
||||||
|
|
||||||
Profile::Profile()
|
Profile::Profile(QString name, QString password)
|
||||||
|
: name{name}, password{password}
|
||||||
{
|
{
|
||||||
|
coreThread = new QThread();
|
||||||
|
coreThread->setObjectName("qTox Core");
|
||||||
|
core = new Core(coreThread, *this);
|
||||||
|
core->moveToThread(coreThread);
|
||||||
|
QObject::connect(coreThread, &QThread::started, core, &Core::start);
|
||||||
|
}
|
||||||
|
|
||||||
|
Profile* Profile::loadProfile(QString name, QString password)
|
||||||
|
{
|
||||||
|
if (ProfileLocker::hasLock())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ProfileLocker::lock(name))
|
||||||
|
{
|
||||||
|
qWarning() << "Failed to lock profile "<<name;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Profile(name, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
Profile::~Profile()
|
Profile::~Profile()
|
||||||
{
|
{
|
||||||
|
delete core;
|
||||||
|
delete coreThread;
|
||||||
|
assert(ProfileLocker::getCurLockName() == name);
|
||||||
|
ProfileLocker::unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<QString> Profile::getFilesByExt(QString extension)
|
QVector<QString> Profile::getFilesByExt(QString extension)
|
||||||
|
@ -52,3 +81,86 @@ QVector<QString> Profile::getProfiles()
|
||||||
{
|
{
|
||||||
return profiles;
|
return profiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Core* Profile::getCore()
|
||||||
|
{
|
||||||
|
return core;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Profile::startCore()
|
||||||
|
{
|
||||||
|
coreThread->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray Profile::loadToxSave()
|
||||||
|
{
|
||||||
|
QByteArray data;
|
||||||
|
QString path = Settings::getSettingsDirPath() + QDir::separator() + name;
|
||||||
|
|
||||||
|
QFile saveFile(path);
|
||||||
|
qint64 fileSize;
|
||||||
|
qDebug() << "Loading tox save "<<path;
|
||||||
|
|
||||||
|
if (!saveFile.exists())
|
||||||
|
{
|
||||||
|
qWarning() << "The tox save file "<<path<<" was not found";
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!saveFile.open(QIODevice::ReadOnly))
|
||||||
|
{
|
||||||
|
qCritical() << "The tox save file " << path << " couldn't' be opened";
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
fileSize = saveFile.size();
|
||||||
|
if (fileSize <= 0)
|
||||||
|
{
|
||||||
|
qWarning() << "The tox save file"<<path<<" is empty!";
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = saveFile.readAll();
|
||||||
|
if (tox_is_data_encrypted((uint8_t*)data.data()))
|
||||||
|
{
|
||||||
|
if (password.isEmpty())
|
||||||
|
{
|
||||||
|
qCritical() << "The tox save file is encrypted, but we don't have a password!";
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t salt[TOX_PASS_SALT_LENGTH];
|
||||||
|
tox_get_salt(reinterpret_cast<uint8_t *>(data.data()), salt);
|
||||||
|
core->setPassword(password, Core::ptMain, salt);
|
||||||
|
|
||||||
|
data = core->decryptData(data, Core::ptMain);
|
||||||
|
if (data.isEmpty())
|
||||||
|
qCritical() << "Failed to decrypt the tox save file";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!password.isEmpty())
|
||||||
|
qWarning() << "We have a password, but the tox save file is not encrypted";
|
||||||
|
}
|
||||||
|
|
||||||
|
fail:
|
||||||
|
saveFile.close();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Profile::isProfileEncrypted(QString name)
|
||||||
|
{
|
||||||
|
uint8_t data[encryptHeaderSize] = {0};
|
||||||
|
QString path = Settings::getSettingsDirPath() + QDir::separator() + name + ".tox";
|
||||||
|
QFile saveFile(path);
|
||||||
|
if (!saveFile.open(QIODevice::ReadOnly))
|
||||||
|
{
|
||||||
|
qWarning() << "Couldn't open tox save "<<path;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
saveFile.read((char*)data, encryptHeaderSize);
|
||||||
|
saveFile.close();
|
||||||
|
|
||||||
|
return tox_is_data_encrypted(data);
|
||||||
|
}
|
||||||
|
|
|
@ -3,20 +3,34 @@
|
||||||
|
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QByteArray>
|
||||||
|
|
||||||
|
class Core;
|
||||||
|
class QThread;
|
||||||
|
|
||||||
/// Manages user profiles
|
/// Manages user profiles
|
||||||
class Profile
|
class Profile
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Profile();
|
/// Locks and loads an existing profile and create the associate Core* instance
|
||||||
|
/// Returns a nullptr on error, for example if the profile is already in use
|
||||||
|
Profile* loadProfile(QString name, QString password);
|
||||||
~Profile();
|
~Profile();
|
||||||
|
|
||||||
|
Core* getCore();
|
||||||
|
void startCore(); ///< Starts the Core thread
|
||||||
|
QByteArray loadToxSave(); ///< Loads the profile's .tox save from file, unencrypted
|
||||||
|
|
||||||
/// Scan for profile, automatically importing them if needed
|
/// Scan for profile, automatically importing them if needed
|
||||||
/// NOT thread-safe
|
/// NOT thread-safe
|
||||||
static void scanProfiles();
|
static void scanProfiles();
|
||||||
static QVector<QString> getProfiles();
|
static QVector<QString> getProfiles();
|
||||||
|
|
||||||
|
/// Checks whether a profile is encrypted. Return false on error.
|
||||||
|
static bool isProfileEncrypted(QString name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Profile(QString name, QString password);
|
||||||
/// Lists all the files in the config dir with a given extension
|
/// Lists all the files in the config dir with a given extension
|
||||||
/// Pass the raw extension, e.g. "jpeg" not ".jpeg".
|
/// Pass the raw extension, e.g. "jpeg" not ".jpeg".
|
||||||
static QVector<QString> getFilesByExt(QString extension);
|
static QVector<QString> getFilesByExt(QString extension);
|
||||||
|
@ -25,7 +39,13 @@ private:
|
||||||
static void importProfile(QString name);
|
static void importProfile(QString name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Core* core;
|
||||||
|
QThread* coreThread;
|
||||||
|
QString name, password;
|
||||||
static QVector<QString> profiles;
|
static QVector<QString> profiles;
|
||||||
|
/// How much data we need to read to check if the file is encrypted
|
||||||
|
/// Must be >= TOX_ENC_SAVE_MAGIC_LENGTH (8), which isn't publicly defined
|
||||||
|
static constexpr int encryptHeaderSize = 8;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PROFILE_H
|
#endif // PROFILE_H
|
||||||
|
|
|
@ -97,3 +97,16 @@ void ProfileLocker::deathByBrokenLock()
|
||||||
qCritical() << "Lock is *BROKEN*, exiting immediately";
|
qCritical() << "Lock is *BROKEN*, exiting immediately";
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ProfileLocker::hasLock()
|
||||||
|
{
|
||||||
|
return lockfile.operator bool();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ProfileLocker::getCurLockName()
|
||||||
|
{
|
||||||
|
if (lockfile)
|
||||||
|
return curLockName;
|
||||||
|
else
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
|
@ -24,6 +24,10 @@ public:
|
||||||
static bool lock(QString profile);
|
static bool lock(QString profile);
|
||||||
/// Releases the lock on the current profile
|
/// Releases the lock on the current profile
|
||||||
static void unlock();
|
static void unlock();
|
||||||
|
/// Returns true if we're currently holding a lock
|
||||||
|
static bool hasLock();
|
||||||
|
/// Return the name of the currently loaded profile, a null string if there is none
|
||||||
|
static QString getCurLockName();
|
||||||
/// Releases all locks on all profiles
|
/// Releases all locks on all profiles
|
||||||
/// DO NOT call unless all we're the only qTox instance
|
/// DO NOT call unless all we're the only qTox instance
|
||||||
/// and we don't hold any lock yet.
|
/// and we don't hold any lock yet.
|
||||||
|
|
|
@ -12,7 +12,24 @@ LoginScreen::LoginScreen(QWidget *parent) :
|
||||||
connect(ui->loginPgbtn, &QPushButton::clicked, this, &LoginScreen::onLoginPageClicked);
|
connect(ui->loginPgbtn, &QPushButton::clicked, this, &LoginScreen::onLoginPageClicked);
|
||||||
connect(ui->createAccountButton, &QPushButton::clicked, this, &LoginScreen::onCreateNewProfile);
|
connect(ui->createAccountButton, &QPushButton::clicked, this, &LoginScreen::onCreateNewProfile);
|
||||||
connect(ui->loginButton, &QPushButton::clicked, this, &LoginScreen::onLogin);
|
connect(ui->loginButton, &QPushButton::clicked, this, &LoginScreen::onLogin);
|
||||||
|
connect(ui->loginUsernames, &QComboBox::currentTextChanged, this, &LoginScreen::onLoginUsernameSelected);
|
||||||
|
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
LoginScreen::~LoginScreen()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoginScreen::reset()
|
||||||
|
{
|
||||||
|
ui->newUsername->clear();
|
||||||
|
ui->newPass->clear();
|
||||||
|
ui->loginPassword->clear();
|
||||||
|
|
||||||
|
ui->loginUsernames->clear();
|
||||||
|
Profile::scanProfiles();
|
||||||
QVector<QString> profiles = Profile::getProfiles();
|
QVector<QString> profiles = Profile::getProfiles();
|
||||||
for (QString profile : profiles)
|
for (QString profile : profiles)
|
||||||
ui->loginUsernames->addItem(profile);
|
ui->loginUsernames->addItem(profile);
|
||||||
|
@ -23,11 +40,6 @@ LoginScreen::LoginScreen(QWidget *parent) :
|
||||||
ui->stackedWidget->setCurrentIndex(1);
|
ui->stackedWidget->setCurrentIndex(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
LoginScreen::~LoginScreen()
|
|
||||||
{
|
|
||||||
delete ui;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoginScreen::onNewProfilePageClicked()
|
void LoginScreen::onNewProfilePageClicked()
|
||||||
{
|
{
|
||||||
ui->stackedWidget->setCurrentIndex(0);
|
ui->stackedWidget->setCurrentIndex(0);
|
||||||
|
@ -43,6 +55,23 @@ void LoginScreen::onCreateNewProfile()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LoginScreen::onLoginUsernameSelected(const QString &name)
|
||||||
|
{
|
||||||
|
if (name.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Profile::isProfileEncrypted(name))
|
||||||
|
{
|
||||||
|
ui->loginPasswordLabel->show();
|
||||||
|
ui->loginPassword->show();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ui->loginPasswordLabel->hide();
|
||||||
|
ui->loginPassword->hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LoginScreen::onLogin()
|
void LoginScreen::onLogin()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,10 @@ class LoginScreen : public QWidget
|
||||||
public:
|
public:
|
||||||
explicit LoginScreen(QWidget *parent = 0);
|
explicit LoginScreen(QWidget *parent = 0);
|
||||||
~LoginScreen();
|
~LoginScreen();
|
||||||
|
void reset(); ///< Resets the UI, clears all fields
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
void onLoginUsernameSelected(const QString& name);
|
||||||
// Buttons to change page
|
// Buttons to change page
|
||||||
void onNewProfilePageClicked();
|
void onNewProfilePageClicked();
|
||||||
void onLoginPageClicked();
|
void onLoginPageClicked();
|
||||||
|
|
|
@ -709,7 +709,7 @@ margin-bottom:5px;</string>
|
||||||
<widget class="QComboBox" name="loginUsernames"/>
|
<widget class="QComboBox" name="loginUsernames"/>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_4">
|
<widget class="QLabel" name="loginPasswordLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Password:</string>
|
<string>Password:</string>
|
||||||
</property>
|
</property>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user