1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00
qTox/src/profile.cpp

246 lines
5.9 KiB
C++
Raw Normal View History

2015-06-04 05:20:47 +08:00
#include "profile.h"
#include "profilelocker.h"
2015-06-04 05:20:47 +08:00
#include "src/misc/settings.h"
#include "src/core/core.h"
2015-06-04 05:20:47 +08:00
#include <cassert>
#include <QDir>
#include <QFileInfo>
2015-06-04 16:56:48 +08:00
#include <QSaveFile>
#include <QThread>
#include <QObject>
#include <QDebug>
2015-06-04 05:20:47 +08:00
QVector<QString> Profile::profiles;
Profile::Profile(QString name, QString password, bool isNewProfile)
2015-06-04 08:43:07 +08:00
: name{name}, password{password}, newProfile{isNewProfile}
2015-06-04 05:20:47 +08:00
{
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())
{
qCritical() << "Tried to load profile "<<name<<", but another profile is already locked!";
return nullptr;
}
if (!ProfileLocker::lock(name))
{
qWarning() << "Failed to lock profile "<<name;
return nullptr;
}
return new Profile(name, password, false);
}
Profile* Profile::createProfile(QString name, QString password)
{
if (ProfileLocker::hasLock())
{
qCritical() << "Tried to create profile "<<name<<", but another profile is already locked!";
return nullptr;
}
if (profileExists(name))
{
qCritical() << "Tried to create profile "<<name<<", but it already exists!";
return nullptr;
}
2015-06-04 05:20:47 +08:00
if (!ProfileLocker::lock(name))
{
qWarning() << "Failed to lock profile "<<name;
return nullptr;
}
Settings::getInstance().createPersonal(name);
return new Profile(name, password, true);
2015-06-04 05:20:47 +08:00
}
Profile::~Profile()
{
delete core;
delete coreThread;
2015-06-04 17:56:19 +08:00
ProfileLocker::assertLock();
assert(ProfileLocker::getCurLockName() == name);
ProfileLocker::unlock();
2015-06-04 05:20:47 +08:00
}
QVector<QString> Profile::getFilesByExt(QString extension)
{
QDir dir(Settings::getInstance().getSettingsDirPath());
QVector<QString> out;
dir.setFilter(QDir::Files | QDir::NoDotAndDotDot);
dir.setNameFilters(QStringList("*."+extension));
QFileInfoList list = dir.entryInfoList();
out.reserve(list.size());
for (QFileInfo file : list)
out += file.completeBaseName();
return out;
}
void Profile::scanProfiles()
{
profiles.clear();
QVector<QString> toxfiles = getFilesByExt("tox"), inifiles = getFilesByExt("ini");
for (QString toxfile : toxfiles)
{
if (!inifiles.contains(toxfile))
importProfile(toxfile);
profiles.append(toxfile);
}
}
void Profile::importProfile(QString name)
{
assert(!profileExists(name));
Settings::getInstance().createPersonal(name);
2015-06-04 05:20:47 +08:00
}
QVector<QString> Profile::getProfiles()
{
return profiles;
}
Core* Profile::getCore()
{
return core;
}
2015-06-04 08:43:07 +08:00
QString Profile::getName()
{
return name;
}
void Profile::startCore()
{
coreThread->start();
}
2015-06-04 08:43:07 +08:00
bool Profile::isNewProfile()
{
return newProfile;
}
QByteArray Profile::loadToxSave()
{
2015-06-04 08:43:07 +08:00
/// TODO: Cache the data, invalidate it only when we save
QByteArray data;
QString path = Settings::getSettingsDirPath() + QDir::separator() + name + ".tox";
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!";
2015-06-04 08:43:07 +08:00
data.clear();
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;
}
void Profile::saveToxSave()
{
saveToxSave(core->getToxSaveData());
}
2015-06-04 16:56:48 +08:00
void Profile::saveToxSave(QByteArray data)
{
ProfileLocker::assertLock();
assert(ProfileLocker::getCurLockName() == name);
QString path = Settings::getSettingsDirPath() + QDir::separator() + name + ".tox";
2015-06-04 17:42:49 +08:00
qDebug() << "Saving tox save to "<<path;
2015-06-04 16:56:48 +08:00
QSaveFile saveFile(path);
if (!saveFile.open(QIODevice::WriteOnly))
{
qCritical() << "Tox save file " << path << " couldn't be opened";
return;
}
if (!password.isEmpty())
{
core->setPassword(password, Core::ptMain);
data = core->encryptData(data, Core::ptMain);
if (data.isEmpty())
{
qCritical() << "Failed to encrypt, can't save!";
saveFile.cancelWriting();
return;
}
}
saveFile.write(data);
saveFile.commit();
newProfile = false;
}
bool Profile::profileExists(QString name)
{
QString path = Settings::getSettingsDirPath() + QDir::separator() + name;
return QFile::exists(path+".tox") && QFile::exists(path+".ini");
}
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);
}