Browse Source

Cleanly create new profiles

pull/1793/head
tux3 10 years ago
parent
commit
840fd7dc40
  1. 97
      src/core/core.cpp
  2. 6
      src/core/core.h
  3. 63
      src/core/coreencryption.cpp
  4. 20
      src/profile.cpp
  5. 7
      src/profile.h
  6. 7
      src/widget/loginscreen.cpp

97
src/core/core.cpp

@ -126,7 +126,7 @@ Core* Core::getInstance() @@ -126,7 +126,7 @@ Core* Core::getInstance()
return Nexus::getCore();
}
void Core::make_tox(QByteArray savedata)
void Core::makeTox(QByteArray savedata)
{
// IPv6 needed for LAN discovery, but can crash some weird routers. On by default, can be disabled in options.
bool enableIPv6 = Settings::getInstance().getEnableIPv6();
@ -236,19 +236,25 @@ void Core::make_tox(QByteArray savedata) @@ -236,19 +236,25 @@ void Core::make_tox(QByteArray savedata)
void Core::start()
{
qDebug() << "Starting up";
QByteArray savedata = profile.loadToxSave();
make_tox(savedata);
// Do we need to create a new save & profile?
if (savedata.isNull())
bool isNewProfile = profile.isNewProfile();
if (isNewProfile)
{
qDebug() << "Save file not found, creating a new profile";
qDebug() << "Creating a new profile";
makeTox(QByteArray());
Settings::getInstance().load();
setStatusMessage(tr("Toxing on qTox"));
setUsername(tr("qTox User"));
setUsername(profile.getName());
}
else
{
qDebug() << "Loading user profile";
QByteArray savedata = profile.loadToxSave();
if (savedata.isEmpty())
{
emit failedToStart();
return;
}
makeTox(savedata);
}
qsrand(time(nullptr));
@ -323,7 +329,7 @@ void Core::start() @@ -323,7 +329,7 @@ void Core::start()
}
else
{
qDebug() << "Error loading self avatar";
qDebug() << "Self avatar not found";
}
ready = true;
@ -331,7 +337,7 @@ void Core::start() @@ -331,7 +337,7 @@ void Core::start()
// If we created a new profile earlier,
// now that we're ready save it and ONLY THEN broadcast the new ID.
// This is useful for e.g. the profileForm that searches for saves.
if (savedata.isNull())
if (isNewProfile)
{
saveConfiguration();
emit idSet(getSelfId().toString());
@ -884,71 +890,6 @@ QString Core::sanitize(QString name) @@ -884,71 +890,6 @@ QString Core::sanitize(QString name)
return name;
}
QByteArray Core::loadToxSave(QString path)
{
QByteArray data;
//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
while (!ProfileLocker::lock(QFileInfo(path).baseName()))
{
qWarning() << "Profile "<<QFileInfo(path).baseName()<<" is already in use, pick another";
GUI::showWarning(tr("Profile already in use"),
tr("This profile is already used by another qTox instance\n"
"Please select another profile"));
QString tmppath = Settings::getInstance().askProfiles();
if (tmppath.isEmpty())
continue;
Settings::getInstance().switchProfile(tmppath);
path = QDir(Settings::getSettingsDirPath()).filePath(tmppath + TOX_EXT);
HistoryKeeper::resetInstance();
}
QFile configurationFile(path);
qDebug() << "loadConfiguration: reading from " << path;
if (!configurationFile.exists())
{
qWarning() << "The Tox configuration file "<<path<<" was not found";
return data;
}
if (!configurationFile.open(QIODevice::ReadOnly))
{
qCritical() << "File " << path << " cannot be opened";
return data;
}
qint64 fileSize = configurationFile.size();
if (fileSize > 0)
{
data = configurationFile.readAll();
if (tox_is_data_encrypted((uint8_t*)data.data()))
{
if (!loadEncryptedSave(data))
{
configurationFile.close();
QString profile;
do {
profile = Settings::getInstance().askProfiles();
} while (profile.isEmpty());
if (!profile.isEmpty())
{
Settings::getInstance().switchProfile(profile);
HistoryKeeper::resetInstance();
return loadToxSave(QDir(Settings::getSettingsDirPath()).filePath(profile + TOX_EXT));
}
return QByteArray();
}
}
}
configurationFile.close();
return data;
}
void Core::saveConfiguration()
{
if (QThread::currentThread() != coreThread)

6
src/core/core.h

@ -147,7 +147,7 @@ public slots: @@ -147,7 +147,7 @@ public slots:
static bool isGroupCallMicEnabled(int groupId);
static bool isGroupCallVolEnabled(int groupId);
void setPassword(QString& password, PasswordType passtype, uint8_t* salt = nullptr);
void setPassword(const QString &password, PasswordType passtype, uint8_t* salt = nullptr);
void useOtherPassword(PasswordType type);
void clearPassword(PasswordType passtype);
QByteArray encryptData(const QByteArray& data, PasswordType passtype);
@ -279,10 +279,8 @@ private: @@ -279,10 +279,8 @@ private:
bool checkConnection();
QByteArray loadToxSave(QString path);
bool loadEncryptedSave(QByteArray& data);
void checkEncryptedHistory();
void make_tox(QByteArray savedata);
void makeTox(QByteArray savedata);
void loadFriends();
void checkLastOnline(uint32_t friendId);

63
src/core/coreencryption.cpp

@ -31,7 +31,7 @@ @@ -31,7 +31,7 @@
#include <algorithm>
#include <cassert>
void Core::setPassword(QString& password, PasswordType passtype, uint8_t* salt)
void Core::setPassword(const QString& password, PasswordType passtype, uint8_t* salt)
{
clearPassword(passtype);
if (password.isEmpty())
@ -44,8 +44,6 @@ void Core::setPassword(QString& password, PasswordType passtype, uint8_t* salt) @@ -44,8 +44,6 @@ void Core::setPassword(QString& password, PasswordType passtype, uint8_t* salt)
tox_derive_key_with_salt(str.data(), str.size(), salt, pwsaltedkeys[passtype], nullptr);
else
tox_derive_key_from_pass(str.data(), str.size(), pwsaltedkeys[passtype], nullptr);
password.clear();
}
void Core::useOtherPassword(PasswordType type)
@ -163,65 +161,6 @@ QByteArray Core::getSaltFromFile(QString filename) @@ -163,65 +161,6 @@ QByteArray Core::getSaltFromFile(QString filename)
return res;
}
bool Core::loadEncryptedSave(QByteArray& data)
{
if (!Settings::getInstance().getEncryptTox())
GUI::showWarning(tr("Encryption error"), tr("The .tox file is encrypted, but encryption was not checked, continuing regardless."));
size_t fileSize = data.size();
int error = -1;
QString a(tr("Please enter the password for the %1 profile.", "used in load() when no pw is already set").arg(Settings::getInstance().getCurrentProfile()));
QString b(tr("The previous password is incorrect; please try again:", "used on retries in load()"));
QString dialogtxt;
if (pwsaltedkeys[ptMain]) // password set, try it
{
QByteArray newData(fileSize-TOX_PASS_ENCRYPTION_EXTRA_LENGTH, 0);
if (tox_pass_key_decrypt((uint8_t*)data.data(), fileSize, pwsaltedkeys[ptMain],
(uint8_t*)newData.data(), nullptr))
{
data = newData;
Settings::getInstance().setEncryptTox(true);
return true;
}
dialogtxt = tr("The profile password failed. Please try another?", "used only when pw set before load() doesn't work");
}
else
{
dialogtxt = a;
}
uint8_t salt[TOX_PASS_SALT_LENGTH];
tox_get_salt(reinterpret_cast<uint8_t *>(data.data()), salt);
do
{
QString pw = GUI::passwordDialog(tr("Change profile"), dialogtxt);
if (pw.isEmpty())
{
clearPassword(ptMain);
return false;
}
else
{
setPassword(pw, ptMain, salt);
}
QByteArray newData(fileSize-TOX_PASS_ENCRYPTION_EXTRA_LENGTH, 0);
error = !tox_pass_key_decrypt((uint8_t*)data.data(), data.size(), pwsaltedkeys[ptMain],
(uint8_t*)newData.data(), nullptr);
if (!error)
data = newData;
dialogtxt = a + "\n" + b;
} while (error != 0);
Settings::getInstance().setEncryptTox(true);
return true;
}
void Core::checkEncryptedHistory()
{
QString path = HistoryKeeper::getHistoryPath();

20
src/profile.cpp

@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
QVector<QString> Profile::profiles;
Profile::Profile(QString name, QString password, bool isNewProfile)
: name{name}, password{password}, isNewProfile{isNewProfile}
: name{name}, password{password}, newProfile{isNewProfile}
{
coreThread = new QThread();
coreThread->setObjectName("qTox Core");
@ -111,21 +111,26 @@ Core* Profile::getCore() @@ -111,21 +111,26 @@ Core* Profile::getCore()
return core;
}
QString Profile::getName()
{
return name;
}
void Profile::startCore()
{
coreThread->start();
}
bool Profile::isNewProfile()
{
return newProfile;
}
QByteArray Profile::loadToxSave()
{
/// TODO: Cache the data, invalidate it only when we save
QByteArray data;
if (isNewProfile)
{
qDebug() << "Loading empty data for new profile";
return data;
}
QString path = Settings::getSettingsDirPath() + QDir::separator() + name + ".tox";
QFile saveFile(path);
qint64 fileSize;
@ -156,6 +161,7 @@ QByteArray Profile::loadToxSave() @@ -156,6 +161,7 @@ QByteArray Profile::loadToxSave()
if (password.isEmpty())
{
qCritical() << "The tox save file is encrypted, but we don't have a password!";
data.clear();
goto fail;
}

7
src/profile.h

@ -22,7 +22,10 @@ public: @@ -22,7 +22,10 @@ public:
~Profile();
Core* getCore();
QString getName();
void startCore(); ///< Starts the Core thread
bool isNewProfile();
QByteArray loadToxSave(); ///< Loads the profile's .tox save from file, unencrypted
/// Scan for profile, automatically importing them if needed
@ -34,7 +37,7 @@ public: @@ -34,7 +37,7 @@ public:
static bool isProfileEncrypted(QString name); ///< Returns false on error.
private:
Profile(QString name, QString password, bool isNewProfile);
Profile(QString name, QString password, bool newProfile);
/// Lists all the files in the config dir with a given extension
/// Pass the raw extension, e.g. "jpeg" not ".jpeg".
static QVector<QString> getFilesByExt(QString extension);
@ -47,7 +50,7 @@ private: @@ -47,7 +50,7 @@ private:
QThread* coreThread;
QString name, password;
static QVector<QString> profiles;
bool isNewProfile;
bool newProfile; ///< True if this is a newly created profile, with no .tox save file yet.
/// 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;

7
src/widget/loginscreen.cpp

@ -126,6 +126,13 @@ void LoginScreen::onLogin() @@ -126,6 +126,13 @@ void LoginScreen::onLogin()
QMessageBox::critical(this, tr("Couldn't load this profile"), tr("Couldn't load this profile."));
return;
}
if (profile->loadToxSave().isEmpty())
{
// Unknown error
QMessageBox::critical(this, tr("Couldn't load this profile"), tr("Wrong password."));
delete profile;
return;
}
Nexus& nexus = Nexus::getInstance();

Loading…
Cancel
Save