mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
Use profile password for all encryption
This commit is contained in:
parent
4e2983817f
commit
5f94f33117
|
@ -62,9 +62,7 @@ Core::Core(QThread *CoreThread, Profile& profile) :
|
||||||
Audio::getInstance();
|
Audio::getInstance();
|
||||||
|
|
||||||
videobuf = nullptr;
|
videobuf = nullptr;
|
||||||
|
encryptionKey = nullptr;
|
||||||
for (int i = 0; i < ptCounter; i++)
|
|
||||||
pwsaltedkeys[i] = nullptr;
|
|
||||||
|
|
||||||
toxTimer = new QTimer(this);
|
toxTimer = new QTimer(this);
|
||||||
toxTimer->setSingleShot(true);
|
toxTimer->setSingleShot(true);
|
||||||
|
@ -109,7 +107,7 @@ Core::~Core()
|
||||||
if (QThread::currentThread() == coreThread)
|
if (QThread::currentThread() == coreThread)
|
||||||
killTimers();
|
killTimers();
|
||||||
else
|
else
|
||||||
QMetaObject::invokeMethod(this, "stopTimers", Qt::BlockingQueuedConnection);
|
QMetaObject::invokeMethod(this, "killTimers", Qt::BlockingQueuedConnection);
|
||||||
}
|
}
|
||||||
coreThread->exit(0);
|
coreThread->exit(0);
|
||||||
while (coreThread->isRunning())
|
while (coreThread->isRunning())
|
||||||
|
@ -286,7 +284,7 @@ void Core::start()
|
||||||
emit idSet(id);
|
emit idSet(id);
|
||||||
|
|
||||||
// tox core is already decrypted
|
// tox core is already decrypted
|
||||||
if (Settings::getInstance().getEnableLogging() && Settings::getInstance().getEncryptLogs())
|
if (Settings::getInstance().getEnableLogging() && Nexus::getProfile()->isEncrypted())
|
||||||
checkEncryptedHistory();
|
checkEncryptedHistory();
|
||||||
|
|
||||||
loadFriends();
|
loadFriends();
|
||||||
|
|
|
@ -44,8 +44,6 @@ class Core : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
enum PasswordType {ptMain = 0, ptHistory, ptCounter};
|
|
||||||
|
|
||||||
explicit Core(QThread* coreThread, Profile& profile);
|
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();
|
||||||
|
@ -82,7 +80,7 @@ public:
|
||||||
VideoSource* getVideoSourceFromCall(int callNumber); ///< Get a call's video source
|
VideoSource* getVideoSourceFromCall(int callNumber); ///< Get a call's video source
|
||||||
|
|
||||||
static bool anyActiveCalls(); ///< true is any calls are currently active (note: a call about to start is not yet active)
|
static bool anyActiveCalls(); ///< true is any calls are currently active (note: a call about to start is not yet active)
|
||||||
bool isPasswordSet(PasswordType passtype);
|
bool isPasswordSet();
|
||||||
bool isReady(); ///< Most of the API shouldn't be used until Core is ready, call start() first
|
bool isReady(); ///< Most of the API shouldn't be used until Core is ready, call start() first
|
||||||
|
|
||||||
void resetCallSources(); ///< Forces to regenerate each call's audio sources
|
void resetCallSources(); ///< Forces to regenerate each call's audio sources
|
||||||
|
@ -145,11 +143,10 @@ public slots:
|
||||||
static bool isGroupCallMicEnabled(int groupId);
|
static bool isGroupCallMicEnabled(int groupId);
|
||||||
static bool isGroupCallVolEnabled(int groupId);
|
static bool isGroupCallVolEnabled(int groupId);
|
||||||
|
|
||||||
void setPassword(const QString &password, PasswordType passtype, uint8_t* salt = nullptr);
|
void setPassword(const QString &password, uint8_t* salt = nullptr);
|
||||||
void useOtherPassword(PasswordType type);
|
void clearPassword();
|
||||||
void clearPassword(PasswordType passtype);
|
QByteArray encryptData(const QByteArray& data);
|
||||||
QByteArray encryptData(const QByteArray& data, PasswordType passtype);
|
QByteArray decryptData(const QByteArray& data);
|
||||||
QByteArray decryptData(const QByteArray& data, PasswordType passtype);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void connected();
|
void connected();
|
||||||
|
@ -301,7 +298,7 @@ private:
|
||||||
QMutex messageSendMutex;
|
QMutex messageSendMutex;
|
||||||
bool ready;
|
bool ready;
|
||||||
|
|
||||||
TOX_PASS_KEY* pwsaltedkeys[PasswordType::ptCounter] = {nullptr}; // use the pw's hash as the "pw"
|
TOX_PASS_KEY* encryptionKey = nullptr; // use the pw's hash as the "pw"
|
||||||
|
|
||||||
static const int videobufsize;
|
static const int videobufsize;
|
||||||
static uint8_t* videobuf;
|
static uint8_t* videobuf;
|
||||||
|
|
|
@ -33,45 +33,38 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
void Core::setPassword(const QString& password, PasswordType passtype, uint8_t* salt)
|
void Core::setPassword(const QString& password, uint8_t* salt)
|
||||||
{
|
{
|
||||||
clearPassword(passtype);
|
clearPassword();
|
||||||
if (password.isEmpty())
|
if (password.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pwsaltedkeys[passtype] = new TOX_PASS_KEY;
|
encryptionKey = new TOX_PASS_KEY;
|
||||||
|
|
||||||
CString str(password);
|
CString str(password);
|
||||||
if (salt)
|
if (salt)
|
||||||
tox_derive_key_with_salt(str.data(), str.size(), salt, pwsaltedkeys[passtype], nullptr);
|
tox_derive_key_with_salt(str.data(), str.size(), salt, encryptionKey, nullptr);
|
||||||
else
|
else
|
||||||
tox_derive_key_from_pass(str.data(), str.size(), pwsaltedkeys[passtype], nullptr);
|
tox_derive_key_from_pass(str.data(), str.size(), encryptionKey, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::useOtherPassword(PasswordType type)
|
void Core::clearPassword()
|
||||||
{
|
{
|
||||||
clearPassword(type);
|
delete encryptionKey;
|
||||||
pwsaltedkeys[type] = new TOX_PASS_KEY;
|
encryptionKey = nullptr;
|
||||||
|
|
||||||
PasswordType other = (type == ptMain) ? ptHistory : ptMain;
|
|
||||||
|
|
||||||
std::copy(pwsaltedkeys[other], pwsaltedkeys[other]+1, pwsaltedkeys[type]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::clearPassword(PasswordType passtype)
|
QByteArray Core::encryptData(const QByteArray& data)
|
||||||
{
|
{
|
||||||
delete pwsaltedkeys[passtype];
|
if (!encryptionKey)
|
||||||
pwsaltedkeys[passtype] = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray Core::encryptData(const QByteArray& data, PasswordType passtype)
|
|
||||||
{
|
{
|
||||||
if (!pwsaltedkeys[passtype])
|
qWarning() << "No encryption key set";
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t encrypted[data.size() + TOX_PASS_ENCRYPTION_EXTRA_LENGTH];
|
uint8_t encrypted[data.size() + TOX_PASS_ENCRYPTION_EXTRA_LENGTH];
|
||||||
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))
|
encryptionKey, encrypted, nullptr))
|
||||||
{
|
{
|
||||||
qWarning() << "Encryption failed";
|
qWarning() << "Encryption failed";
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
|
@ -79,15 +72,18 @@ QByteArray Core::encryptData(const QByteArray& data, PasswordType passtype)
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Core::decryptData(const QByteArray& data, PasswordType passtype)
|
QByteArray Core::decryptData(const QByteArray& data)
|
||||||
{
|
{
|
||||||
if (!pwsaltedkeys[passtype])
|
if (!encryptionKey)
|
||||||
|
{
|
||||||
|
qWarning() << "No encryption key set";
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
int sz = data.size() - TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
|
int sz = data.size() - TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
|
||||||
uint8_t decrypted[sz];
|
uint8_t decrypted[sz];
|
||||||
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))
|
encryptionKey, decrypted, nullptr))
|
||||||
{
|
{
|
||||||
qWarning() << "Decryption failed";
|
qWarning() << "Decryption failed";
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
|
@ -95,12 +91,9 @@ QByteArray Core::decryptData(const QByteArray& data, PasswordType passtype)
|
||||||
return QByteArray(reinterpret_cast<char*>(decrypted), sz);
|
return QByteArray(reinterpret_cast<char*>(decrypted), sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Core::isPasswordSet(PasswordType passtype)
|
bool Core::isPasswordSet()
|
||||||
{
|
{
|
||||||
if (pwsaltedkeys[passtype])
|
return static_cast<bool>(encryptionKey);
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Core::getSaltFromFile(QString filename)
|
QByteArray Core::getSaltFromFile(QString filename)
|
||||||
|
@ -135,42 +128,24 @@ void Core::checkEncryptedHistory()
|
||||||
if (exists && salt.size() == 0)
|
if (exists && salt.size() == 0)
|
||||||
{ // maybe we should handle this better
|
{ // maybe we should handle this better
|
||||||
GUI::showWarning(tr("Encrypted chat history"), tr("No encrypted chat history file found, or it was corrupted.\nHistory will be disabled!"));
|
GUI::showWarning(tr("Encrypted chat history"), tr("No encrypted chat history file found, or it was corrupted.\nHistory will be disabled!"));
|
||||||
Settings::getInstance().setEncryptLogs(false);
|
|
||||||
Settings::getInstance().setEnableLogging(false);
|
|
||||||
HistoryKeeper::resetInstance();
|
HistoryKeeper::resetInstance();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setPassword(Nexus::getProfile()->getPassword(), reinterpret_cast<uint8_t*>(salt.data()));
|
||||||
|
|
||||||
QString a(tr("Please enter the password for the chat history for the profile \"%1\".", "used in load() when no hist pw set").arg(Nexus::getProfile()->getName()));
|
QString a(tr("Please enter the password for the chat history for the profile \"%1\".", "used in load() when no hist pw set").arg(Nexus::getProfile()->getName()));
|
||||||
QString b(tr("The previous password is incorrect; please try again:", "used on retries in load()"));
|
QString b(tr("The previous password is incorrect; please try again:", "used on retries in load()"));
|
||||||
QString c(tr("\nDisabling chat history now will leave the encrypted history intact (but not usable); if you later remember the password, you may re-enable encryption from the Privacy tab with the correct password to use the history.", "part of history password dialog"));
|
QString c(tr("\nDisabling chat history now will leave the encrypted history intact (but not usable); if you later remember the password, you may re-enable encryption from the Privacy tab with the correct password to use the history.", "part of history password dialog"));
|
||||||
QString dialogtxt;
|
QString dialogtxt;
|
||||||
|
|
||||||
if (pwsaltedkeys[ptHistory])
|
|
||||||
{
|
|
||||||
if (!exists || HistoryKeeper::checkPassword())
|
if (!exists || HistoryKeeper::checkPassword())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dialogtxt = tr("The chat history password failed. Please try another?", "used only when pw set before load() doesn't work");
|
dialogtxt = tr("The chat history password failed. Please try another?", "used only when pw set before load() doesn't work");
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dialogtxt = a;
|
|
||||||
}
|
|
||||||
|
|
||||||
dialogtxt += "\n" + c;
|
dialogtxt += "\n" + c;
|
||||||
|
|
||||||
if (pwsaltedkeys[ptMain])
|
|
||||||
{
|
|
||||||
useOtherPassword(ptHistory);
|
|
||||||
if (!exists || HistoryKeeper::checkPassword())
|
|
||||||
{
|
|
||||||
qDebug() << "using main password for chat history";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
clearPassword(ptHistory);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool error = true;
|
bool error = true;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -178,15 +153,14 @@ void Core::checkEncryptedHistory()
|
||||||
|
|
||||||
if (pw.isEmpty())
|
if (pw.isEmpty())
|
||||||
{
|
{
|
||||||
clearPassword(ptHistory);
|
clearPassword();
|
||||||
Settings::getInstance().setEncryptLogs(false);
|
|
||||||
Settings::getInstance().setEnableLogging(false);
|
Settings::getInstance().setEnableLogging(false);
|
||||||
HistoryKeeper::resetInstance();
|
HistoryKeeper::resetInstance();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
setPassword(pw, ptHistory, reinterpret_cast<uint8_t*>(salt.data()));
|
setPassword(pw, reinterpret_cast<uint8_t*>(salt.data()));
|
||||||
}
|
}
|
||||||
|
|
||||||
error = exists && !HistoryKeeper::checkPassword();
|
error = exists && !HistoryKeeper::checkPassword();
|
||||||
|
|
|
@ -47,9 +47,7 @@ HistoryKeeper *HistoryKeeper::getInstance()
|
||||||
|
|
||||||
if (Settings::getInstance().getEnableLogging())
|
if (Settings::getInstance().getEnableLogging())
|
||||||
{
|
{
|
||||||
bool encrypted = Settings::getInstance().getEncryptLogs();
|
if (Nexus::getProfile()->isEncrypted())
|
||||||
|
|
||||||
if (encrypted)
|
|
||||||
{
|
{
|
||||||
path = getHistoryPath();
|
path = getHistoryPath();
|
||||||
dbIntf = new EncryptedDb(path, initLst);
|
dbIntf = new EncryptedDb(path, initLst);
|
||||||
|
@ -75,7 +73,7 @@ bool HistoryKeeper::checkPassword(int encrypted)
|
||||||
if (!Settings::getInstance().getEnableLogging() && (encrypted == -1))
|
if (!Settings::getInstance().getEnableLogging() && (encrypted == -1))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if ((encrypted == 1) || (encrypted == -1 && Settings::getInstance().getEncryptLogs()))
|
if ((encrypted == 1) || (encrypted == -1 && Nexus::getProfile()->isEncrypted()))
|
||||||
return EncryptedDb::check(getHistoryPath(Nexus::getProfile()->getName(), encrypted));
|
return EncryptedDb::check(getHistoryPath(Nexus::getProfile()->getName(), encrypted));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -365,7 +363,7 @@ QString HistoryKeeper::getHistoryPath(QString currentProfile, int encrypted)
|
||||||
if (currentProfile.isEmpty())
|
if (currentProfile.isEmpty())
|
||||||
currentProfile = Settings::getInstance().getCurrentProfile();
|
currentProfile = Settings::getInstance().getCurrentProfile();
|
||||||
|
|
||||||
if (encrypted == 1 || (encrypted == -1 && Settings::getInstance().getEncryptLogs()))
|
if (encrypted == 1 || (encrypted == -1 && Nexus::getProfile()->isEncrypted()))
|
||||||
return baseDir.filePath(currentProfile + ".qtox_history.encrypted");
|
return baseDir.filePath(currentProfile + ".qtox_history.encrypted");
|
||||||
else
|
else
|
||||||
return baseDir.filePath(currentProfile + ".qtox_history");
|
return baseDir.filePath(currentProfile + ".qtox_history");
|
||||||
|
|
|
@ -118,7 +118,7 @@ int main(int argc, char *argv[])
|
||||||
if (QDir(Settings::getSettingsDirPath()).exists(profileName + ".tox"))
|
if (QDir(Settings::getSettingsDirPath()).exists(profileName + ".tox"))
|
||||||
{
|
{
|
||||||
qDebug() << "Setting profile to" << profileName;
|
qDebug() << "Setting profile to" << profileName;
|
||||||
if (Profile::isProfileEncrypted(profileName))
|
if (Profile::isEncrypted(profileName))
|
||||||
{
|
{
|
||||||
Settings::getInstance().setCurrentProfile(profileName);
|
Settings::getInstance().setCurrentProfile(profileName);
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@ bool EncryptedDb::pullFileContent(const QString &fname, QByteArray &buf)
|
||||||
while (!dbFile.atEnd())
|
while (!dbFile.atEnd())
|
||||||
{
|
{
|
||||||
QByteArray encrChunk = dbFile.read(encryptedChunkSize);
|
QByteArray encrChunk = dbFile.read(encryptedChunkSize);
|
||||||
buf = Core::getInstance()->decryptData(encrChunk, Core::ptHistory);
|
buf = Core::getInstance()->decryptData(encrChunk);
|
||||||
if (buf.size() > 0)
|
if (buf.size() > 0)
|
||||||
{
|
{
|
||||||
fileContent += buf;
|
fileContent += buf;
|
||||||
|
@ -130,7 +130,7 @@ void EncryptedDb::appendToEncrypted(const QString &sql)
|
||||||
{
|
{
|
||||||
QByteArray filledChunk = buffer.left(plainChunkSize);
|
QByteArray filledChunk = buffer.left(plainChunkSize);
|
||||||
encrFile.seek(chunkPosition * encryptedChunkSize);
|
encrFile.seek(chunkPosition * encryptedChunkSize);
|
||||||
QByteArray encr = Core::getInstance()->encryptData(filledChunk, Core::ptHistory);
|
QByteArray encr = Core::getInstance()->encryptData(filledChunk);
|
||||||
if (encr.size() > 0)
|
if (encr.size() > 0)
|
||||||
{
|
{
|
||||||
encrFile.write(encr);
|
encrFile.write(encr);
|
||||||
|
@ -142,7 +142,7 @@ void EncryptedDb::appendToEncrypted(const QString &sql)
|
||||||
}
|
}
|
||||||
encrFile.seek(chunkPosition * encryptedChunkSize);
|
encrFile.seek(chunkPosition * encryptedChunkSize);
|
||||||
|
|
||||||
QByteArray encr = Core::getInstance()->encryptData(buffer, Core::ptHistory);
|
QByteArray encr = Core::getInstance()->encryptData(buffer);
|
||||||
if (encr.size() > 0)
|
if (encr.size() > 0)
|
||||||
encrFile.write(encr);
|
encrFile.write(encr);
|
||||||
|
|
||||||
|
@ -158,7 +158,7 @@ bool EncryptedDb::check(const QString &fname)
|
||||||
if (file.size() > 0)
|
if (file.size() > 0)
|
||||||
{
|
{
|
||||||
QByteArray encrChunk = file.read(encryptedChunkSize);
|
QByteArray encrChunk = file.read(encryptedChunkSize);
|
||||||
QByteArray buf = Core::getInstance()->decryptData(encrChunk, Core::ptHistory);
|
QByteArray buf = Core::getInstance()->decryptData(encrChunk);
|
||||||
if (buf.size() == 0)
|
if (buf.size() == 0)
|
||||||
state = false;
|
state = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -249,8 +249,6 @@ void Settings::load()
|
||||||
ps.beginGroup("Privacy");
|
ps.beginGroup("Privacy");
|
||||||
typingNotification = ps.value("typingNotification", false).toBool();
|
typingNotification = ps.value("typingNotification", false).toBool();
|
||||||
enableLogging = ps.value("enableLogging", false).toBool();
|
enableLogging = ps.value("enableLogging", false).toBool();
|
||||||
encryptLogs = ps.value("encryptLogs", false).toBool();
|
|
||||||
encryptTox = ps.value("encryptTox", false).toBool();
|
|
||||||
ps.endGroup();
|
ps.endGroup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -396,8 +394,6 @@ void Settings::savePersonal(QString path)
|
||||||
ps.beginGroup("Privacy");
|
ps.beginGroup("Privacy");
|
||||||
ps.setValue("typingNotification", typingNotification);
|
ps.setValue("typingNotification", typingNotification);
|
||||||
ps.setValue("enableLogging", enableLogging);
|
ps.setValue("enableLogging", enableLogging);
|
||||||
ps.setValue("encryptLogs", encryptLogs);
|
|
||||||
ps.setValue("encryptTox", encryptTox);
|
|
||||||
ps.endGroup();
|
ps.endGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -731,26 +727,6 @@ void Settings::setEnableLogging(bool newValue)
|
||||||
enableLogging = newValue;
|
enableLogging = newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Settings::getEncryptLogs() const
|
|
||||||
{
|
|
||||||
return encryptLogs;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Settings::setEncryptLogs(bool newValue)
|
|
||||||
{
|
|
||||||
encryptLogs = newValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Settings::getEncryptTox() const
|
|
||||||
{
|
|
||||||
return encryptTox;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Settings::setEncryptTox(bool newValue)
|
|
||||||
{
|
|
||||||
encryptTox = newValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Db::syncType Settings::getDbSyncType() const
|
Db::syncType Settings::getDbSyncType() const
|
||||||
{
|
{
|
||||||
return dbSyncType;
|
return dbSyncType;
|
||||||
|
|
|
@ -104,12 +104,6 @@ public:
|
||||||
bool getEnableLogging() const;
|
bool getEnableLogging() const;
|
||||||
void setEnableLogging(bool newValue);
|
void setEnableLogging(bool newValue);
|
||||||
|
|
||||||
bool getEncryptLogs() const;
|
|
||||||
void setEncryptLogs(bool newValue);
|
|
||||||
|
|
||||||
bool getEncryptTox() const;
|
|
||||||
void setEncryptTox(bool newValue);
|
|
||||||
|
|
||||||
Db::syncType getDbSyncType() const;
|
Db::syncType getDbSyncType() const;
|
||||||
void setDbSyncType(int newValue);
|
void setDbSyncType(int newValue);
|
||||||
|
|
||||||
|
@ -303,8 +297,6 @@ private:
|
||||||
uint32_t currentProfileId;
|
uint32_t currentProfileId;
|
||||||
|
|
||||||
bool enableLogging;
|
bool enableLogging;
|
||||||
bool encryptLogs;
|
|
||||||
bool encryptTox = false;
|
|
||||||
|
|
||||||
int autoAwayTime;
|
int autoAwayTime;
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,6 @@ void Nexus::start()
|
||||||
qRegisterMetaType<QPixmap>("QPixmap");
|
qRegisterMetaType<QPixmap>("QPixmap");
|
||||||
qRegisterMetaType<ToxFile>("ToxFile");
|
qRegisterMetaType<ToxFile>("ToxFile");
|
||||||
qRegisterMetaType<ToxFile::FileDirection>("ToxFile::FileDirection");
|
qRegisterMetaType<ToxFile::FileDirection>("ToxFile::FileDirection");
|
||||||
qRegisterMetaType<Core::PasswordType>("Core::PasswordType");
|
|
||||||
qRegisterMetaType<std::shared_ptr<VideoFrame>>("std::shared_ptr<VideoFrame>");
|
qRegisterMetaType<std::shared_ptr<VideoFrame>>("std::shared_ptr<VideoFrame>");
|
||||||
|
|
||||||
loginScreen = new LoginScreen();
|
loginScreen = new LoginScreen();
|
||||||
|
|
|
@ -176,9 +176,9 @@ QByteArray Profile::loadToxSave()
|
||||||
|
|
||||||
uint8_t salt[TOX_PASS_SALT_LENGTH];
|
uint8_t salt[TOX_PASS_SALT_LENGTH];
|
||||||
tox_get_salt(reinterpret_cast<uint8_t *>(data.data()), salt);
|
tox_get_salt(reinterpret_cast<uint8_t *>(data.data()), salt);
|
||||||
core->setPassword(password, Core::ptMain, salt);
|
core->setPassword(password, salt);
|
||||||
|
|
||||||
data = core->decryptData(data, Core::ptMain);
|
data = core->decryptData(data);
|
||||||
if (data.isEmpty())
|
if (data.isEmpty())
|
||||||
qCritical() << "Failed to decrypt the tox save file";
|
qCritical() << "Failed to decrypt the tox save file";
|
||||||
}
|
}
|
||||||
|
@ -218,8 +218,8 @@ void Profile::saveToxSave(QByteArray data)
|
||||||
|
|
||||||
if (!password.isEmpty())
|
if (!password.isEmpty())
|
||||||
{
|
{
|
||||||
core->setPassword(password, Core::ptMain);
|
core->setPassword(password);
|
||||||
data = core->encryptData(data, Core::ptMain);
|
data = core->encryptData(data);
|
||||||
if (data.isEmpty())
|
if (data.isEmpty())
|
||||||
{
|
{
|
||||||
qCritical() << "Failed to encrypt, can't save!";
|
qCritical() << "Failed to encrypt, can't save!";
|
||||||
|
@ -239,7 +239,12 @@ bool Profile::profileExists(QString name)
|
||||||
return QFile::exists(path+".tox") && QFile::exists(path+".ini");
|
return QFile::exists(path+".tox") && QFile::exists(path+".ini");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Profile::isProfileEncrypted(QString name)
|
bool Profile::isEncrypted()
|
||||||
|
{
|
||||||
|
return !password.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Profile::isEncrypted(QString name)
|
||||||
{
|
{
|
||||||
uint8_t data[encryptHeaderSize] = {0};
|
uint8_t data[encryptHeaderSize] = {0};
|
||||||
QString path = Settings::getSettingsDirPath() + QDir::separator() + name + ".tox";
|
QString path = Settings::getSettingsDirPath() + QDir::separator() + name + ".tox";
|
||||||
|
@ -303,3 +308,8 @@ bool Profile::checkPassword()
|
||||||
|
|
||||||
return !loadToxSave().isEmpty();
|
return !loadToxSave().isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Profile::getPassword()
|
||||||
|
{
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
|
@ -26,7 +26,10 @@ public:
|
||||||
|
|
||||||
void startCore(); ///< Starts the Core thread
|
void startCore(); ///< Starts the Core thread
|
||||||
bool isNewProfile();
|
bool isNewProfile();
|
||||||
|
bool isEncrypted(); ///< Returns true if we have a password set (doesn't check the actual file on disk)
|
||||||
bool checkPassword(); ///< Checks whether the password is valid
|
bool checkPassword(); ///< Checks whether the password is valid
|
||||||
|
QString getPassword();
|
||||||
|
|
||||||
QByteArray loadToxSave(); ///< Loads the profile's .tox save from file, unencrypted
|
QByteArray loadToxSave(); ///< Loads the profile's .tox save from file, unencrypted
|
||||||
void saveToxSave(); ///< Saves the profile's .tox save, encrypted if needed. Invalid on deleted profiles.
|
void saveToxSave(); ///< Saves the profile's .tox save, encrypted if needed. Invalid on deleted profiles.
|
||||||
void saveToxSave(QByteArray data); ///< Write the .tox save, encrypted if needed. Invalid on deleted profiles.
|
void saveToxSave(QByteArray data); ///< Write the .tox save, encrypted if needed. Invalid on deleted profiles.
|
||||||
|
@ -45,7 +48,7 @@ public:
|
||||||
static QVector<QString> getProfiles();
|
static QVector<QString> getProfiles();
|
||||||
|
|
||||||
static bool profileExists(QString name);
|
static bool profileExists(QString name);
|
||||||
static bool isProfileEncrypted(QString name); ///< Returns false on error.
|
static bool isEncrypted(QString name); ///< Returns false on error. Checks the actual file on disk.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Profile(QString name, QString password, bool newProfile);
|
Profile(QString name, QString password, bool newProfile);
|
||||||
|
|
|
@ -31,15 +31,8 @@ PrivacyForm::PrivacyForm() :
|
||||||
bodyUI = new Ui::PrivacySettings;
|
bodyUI = new Ui::PrivacySettings;
|
||||||
bodyUI->setupUi(this);
|
bodyUI->setupUi(this);
|
||||||
|
|
||||||
bodyUI->encryptToxHLayout->addStretch();
|
|
||||||
bodyUI->encryptLogsHLayout->addStretch();
|
|
||||||
|
|
||||||
connect(bodyUI->cbTypingNotification, SIGNAL(stateChanged(int)), this, SLOT(onTypingNotificationEnabledUpdated()));
|
connect(bodyUI->cbTypingNotification, SIGNAL(stateChanged(int)), this, SLOT(onTypingNotificationEnabledUpdated()));
|
||||||
connect(bodyUI->cbKeepHistory, SIGNAL(stateChanged(int)), this, SLOT(onEnableLoggingUpdated()));
|
connect(bodyUI->cbKeepHistory, SIGNAL(stateChanged(int)), this, SLOT(onEnableLoggingUpdated()));
|
||||||
connect(bodyUI->cbEncryptHistory, SIGNAL(clicked()), this, SLOT(onEncryptLogsUpdated()));
|
|
||||||
connect(bodyUI->changeLogsPwButton, &QPushButton::clicked, this, &PrivacyForm::setChatLogsPassword);
|
|
||||||
connect(bodyUI->cbEncryptTox, SIGNAL(clicked()), this, SLOT(onEncryptToxUpdated()));
|
|
||||||
connect(bodyUI->changeToxPwButton, &QPushButton::clicked, this, &PrivacyForm::setToxPassword);
|
|
||||||
connect(bodyUI->nospamLineEdit, SIGNAL(editingFinished()), this, SLOT(setNospam()));
|
connect(bodyUI->nospamLineEdit, SIGNAL(editingFinished()), this, SLOT(setNospam()));
|
||||||
connect(bodyUI->randomNosapamButton, SIGNAL(clicked()), this, SLOT(generateRandomNospam()));
|
connect(bodyUI->randomNosapamButton, SIGNAL(clicked()), this, SLOT(generateRandomNospam()));
|
||||||
connect(bodyUI->nospamLineEdit, SIGNAL(textChanged(QString)), this, SLOT(onNospamEdit()));
|
connect(bodyUI->nospamLineEdit, SIGNAL(textChanged(QString)), this, SLOT(onNospamEdit()));
|
||||||
|
@ -53,7 +46,6 @@ PrivacyForm::~PrivacyForm()
|
||||||
void PrivacyForm::onEnableLoggingUpdated()
|
void PrivacyForm::onEnableLoggingUpdated()
|
||||||
{
|
{
|
||||||
Settings::getInstance().setEnableLogging(bodyUI->cbKeepHistory->isChecked());
|
Settings::getInstance().setEnableLogging(bodyUI->cbKeepHistory->isChecked());
|
||||||
bodyUI->cbEncryptHistory->setEnabled(bodyUI->cbKeepHistory->isChecked());
|
|
||||||
HistoryKeeper::resetInstance();
|
HistoryKeeper::resetInstance();
|
||||||
Widget::getInstance()->clearAllReceipts();
|
Widget::getInstance()->clearAllReceipts();
|
||||||
}
|
}
|
||||||
|
@ -63,205 +55,6 @@ void PrivacyForm::onTypingNotificationEnabledUpdated()
|
||||||
Settings::getInstance().setTypingNotification(bodyUI->cbTypingNotification->isChecked());
|
Settings::getInstance().setTypingNotification(bodyUI->cbTypingNotification->isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PrivacyForm::setChatLogsPassword()
|
|
||||||
{
|
|
||||||
Core* core = Core::getInstance();
|
|
||||||
SetPasswordDialog* dialog;
|
|
||||||
|
|
||||||
// check if an encrypted history exists because it was disabled earlier, and use it if possible
|
|
||||||
QString path = HistoryKeeper::getHistoryPath(QString(), 1);
|
|
||||||
QByteArray salt = core->getSaltFromFile(path);
|
|
||||||
bool haveEncHist = salt.size() > 0;
|
|
||||||
|
|
||||||
QString body = tr("Please set your new chat history password.");
|
|
||||||
if (haveEncHist)
|
|
||||||
body += "\n\n" + tr("It appears you have an unused encrypted chat history; if the password matches, it will be added to your current history.");
|
|
||||||
|
|
||||||
if (core->isPasswordSet(Core::ptMain))
|
|
||||||
dialog = new SetPasswordDialog(body, tr("Use data file password", "pushbutton text"), 0);
|
|
||||||
else
|
|
||||||
dialog = new SetPasswordDialog(body, QString(), 0);
|
|
||||||
|
|
||||||
do {
|
|
||||||
int r = dialog->exec();
|
|
||||||
if (r == QDialog::Rejected)
|
|
||||||
break;
|
|
||||||
|
|
||||||
QList<HistoryKeeper::HistMessage> oldMessages = HistoryKeeper::exportMessagesDeleteFile();
|
|
||||||
|
|
||||||
QString newpw = dialog->getPassword();
|
|
||||||
|
|
||||||
if (r == SetPasswordDialog::Tertiary)
|
|
||||||
core->useOtherPassword(Core::ptHistory);
|
|
||||||
else if (haveEncHist)
|
|
||||||
core->setPassword(newpw, Core::ptHistory, reinterpret_cast<uint8_t*>(salt.data()));
|
|
||||||
else
|
|
||||||
core->setPassword(newpw, Core::ptHistory);
|
|
||||||
|
|
||||||
if (!haveEncHist || HistoryKeeper::checkPassword(1))
|
|
||||||
{
|
|
||||||
Settings::getInstance().setEncryptLogs(true);
|
|
||||||
HistoryKeeper::getInstance()->importMessages(oldMessages);
|
|
||||||
if (haveEncHist)
|
|
||||||
{
|
|
||||||
Widget::getInstance()->reloadHistory();
|
|
||||||
GUI::showWarning(tr("Successfully decrypted old chat history","popup title"), tr("You have succesfully decrypted the old chat history, and it has been added to your current history and re-encrypted.", "popup text"));
|
|
||||||
}
|
|
||||||
delete dialog;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (GUI::askQuestion(tr("Old encrypted chat history", "popup title"), tr("There is currently an unused encrypted chat history, but the password you just entered doesn't match.\n\nIf you don't care about the old history, you may delete it and use the password you just entered.\nOtherwise, hit Cancel to try again.", "This happens when enabling encryption after previously \"Disabling History\""), tr("Delete"), tr("Cancel")))
|
|
||||||
{
|
|
||||||
if (GUI::askQuestion(tr("Old encrypted chat history", "popup title"), tr("Are you absolutely sure you want to lose the unused encrypted chat history?", "secondary popup"), tr("Delete"), tr("Cancel")))
|
|
||||||
haveEncHist = false; // logically this is really just a `break`, but conceptually this is more accurate
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (haveEncHist);
|
|
||||||
|
|
||||||
delete dialog;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PrivacyForm::onEncryptLogsUpdated()
|
|
||||||
{
|
|
||||||
Core* core = Core::getInstance();
|
|
||||||
|
|
||||||
if (bodyUI->cbEncryptHistory->isChecked())
|
|
||||||
{
|
|
||||||
if (!core->isPasswordSet(Core::ptHistory))
|
|
||||||
{
|
|
||||||
if (setChatLogsPassword())
|
|
||||||
{
|
|
||||||
bodyUI->cbEncryptHistory->setChecked(true);
|
|
||||||
bodyUI->changeLogsPwButton->setEnabled(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QMessageBox box(QMessageBox::Warning,
|
|
||||||
tr("Old encrypted chat history", "title"),
|
|
||||||
tr("Would you like to decrypt your chat history?\nOtherwise it will be deleted."),
|
|
||||||
QMessageBox::NoButton, Widget::getInstance());
|
|
||||||
QPushButton* decryptBtn = box.addButton(tr("Decrypt"), QMessageBox::YesRole);
|
|
||||||
QPushButton* deleteBtn = box.addButton(tr("Delete"), QMessageBox::NoRole);
|
|
||||||
QPushButton* cancelBtn = box.addButton(tr("Cancel"), QMessageBox::RejectRole);
|
|
||||||
box.setDefaultButton(cancelBtn);
|
|
||||||
box.setEscapeButton(cancelBtn);
|
|
||||||
|
|
||||||
box.exec();
|
|
||||||
|
|
||||||
if (box.clickedButton() == decryptBtn)
|
|
||||||
{
|
|
||||||
QList<HistoryKeeper::HistMessage> oldMessages = HistoryKeeper::exportMessagesDeleteFile(true);
|
|
||||||
core->clearPassword(Core::ptHistory);
|
|
||||||
Settings::getInstance().setEncryptLogs(false);
|
|
||||||
HistoryKeeper::getInstance()->importMessages(oldMessages);
|
|
||||||
}
|
|
||||||
else if (box.clickedButton() == deleteBtn)
|
|
||||||
{
|
|
||||||
QMessageBox box2(QMessageBox::Critical,
|
|
||||||
tr("Old encrypted chat history", "title"),
|
|
||||||
tr("Are you sure you want to lose your entire chat history?"),
|
|
||||||
QMessageBox::NoButton, Widget::getInstance());
|
|
||||||
QPushButton* deleteBtn2 = box2.addButton(tr("Delete"), QMessageBox::AcceptRole);
|
|
||||||
QPushButton* cancelBtn2 = box2.addButton(tr("Cancel"), QMessageBox::RejectRole);
|
|
||||||
box2.setDefaultButton(cancelBtn2);
|
|
||||||
box2.setEscapeButton(cancelBtn2);
|
|
||||||
box2.exec();
|
|
||||||
|
|
||||||
if (box2.clickedButton() == deleteBtn2)
|
|
||||||
{
|
|
||||||
HistoryKeeper::removeHistory(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bodyUI->cbEncryptHistory->setChecked(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bodyUI->cbEncryptHistory->setChecked(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
core->clearPassword(Core::ptHistory);
|
|
||||||
Settings::getInstance().setEncryptLogs(false);
|
|
||||||
bodyUI->cbEncryptHistory->setChecked(false);
|
|
||||||
bodyUI->changeLogsPwButton->setEnabled(false);
|
|
||||||
HistoryKeeper::resetInstance();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PrivacyForm::setToxPassword()
|
|
||||||
{
|
|
||||||
Core* core = Core::getInstance();
|
|
||||||
SetPasswordDialog* dialog;
|
|
||||||
QString body = tr("Please set your new data file password.");
|
|
||||||
if (core->isPasswordSet(Core::ptHistory))
|
|
||||||
dialog = new SetPasswordDialog(body, tr("Use chat history password", "pushbutton text"), 0);
|
|
||||||
else
|
|
||||||
dialog = new SetPasswordDialog(body, QString(), 0);
|
|
||||||
|
|
||||||
if (int r = dialog->exec())
|
|
||||||
{
|
|
||||||
QString newpw = dialog->getPassword();
|
|
||||||
delete dialog;
|
|
||||||
|
|
||||||
if (r == SetPasswordDialog::Tertiary)
|
|
||||||
core->useOtherPassword(Core::ptMain);
|
|
||||||
else
|
|
||||||
core->setPassword(newpw, Core::ptMain);
|
|
||||||
|
|
||||||
Settings::getInstance().setEncryptTox(true);
|
|
||||||
Settings::getInstance().save();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
delete dialog;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PrivacyForm::onEncryptToxUpdated()
|
|
||||||
{
|
|
||||||
Core* core = Core::getInstance();
|
|
||||||
|
|
||||||
if (bodyUI->cbEncryptTox->isChecked())
|
|
||||||
{
|
|
||||||
if (!core->isPasswordSet(Core::ptMain))
|
|
||||||
{
|
|
||||||
if (setToxPassword())
|
|
||||||
{
|
|
||||||
bodyUI->cbEncryptTox->setChecked(true);
|
|
||||||
bodyUI->changeToxPwButton->setEnabled(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!GUI::askQuestion(tr("Decrypt your data file", "title"),
|
|
||||||
tr("Would you like to decrypt your data file?"),
|
|
||||||
tr("Decrypt"), tr("Cancel")))
|
|
||||||
{
|
|
||||||
bodyUI->cbEncryptTox->setChecked(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// affirmative answer falls through to the catch all below
|
|
||||||
}
|
|
||||||
|
|
||||||
bodyUI->cbEncryptTox->setChecked(false);
|
|
||||||
Settings::getInstance().setEncryptTox(false);
|
|
||||||
bodyUI->changeToxPwButton->setEnabled(false);
|
|
||||||
core->clearPassword(Core::ptMain);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PrivacyForm::setNospam()
|
void PrivacyForm::setNospam()
|
||||||
{
|
{
|
||||||
QString newNospam = bodyUI->nospamLineEdit->text();
|
QString newNospam = bodyUI->nospamLineEdit->text();
|
||||||
|
@ -277,11 +70,6 @@ void PrivacyForm::present()
|
||||||
bodyUI->nospamLineEdit->setText(Core::getInstance()->getSelfId().noSpam);
|
bodyUI->nospamLineEdit->setText(Core::getInstance()->getSelfId().noSpam);
|
||||||
bodyUI->cbTypingNotification->setChecked(Settings::getInstance().isTypingNotificationEnabled());
|
bodyUI->cbTypingNotification->setChecked(Settings::getInstance().isTypingNotificationEnabled());
|
||||||
bodyUI->cbKeepHistory->setChecked(Settings::getInstance().getEnableLogging());
|
bodyUI->cbKeepHistory->setChecked(Settings::getInstance().getEnableLogging());
|
||||||
bodyUI->cbEncryptHistory->setChecked(Settings::getInstance().getEncryptLogs());
|
|
||||||
bodyUI->changeLogsPwButton->setEnabled(Settings::getInstance().getEncryptLogs());
|
|
||||||
bodyUI->cbEncryptHistory->setEnabled(Settings::getInstance().getEnableLogging());
|
|
||||||
bodyUI->cbEncryptTox->setChecked(Settings::getInstance().getEncryptTox());
|
|
||||||
bodyUI->changeToxPwButton->setEnabled(Settings::getInstance().getEncryptTox());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrivacyForm::generateRandomNospam()
|
void PrivacyForm::generateRandomNospam()
|
||||||
|
|
|
@ -36,10 +36,6 @@ private slots:
|
||||||
void setNospam();
|
void setNospam();
|
||||||
void generateRandomNospam();
|
void generateRandomNospam();
|
||||||
void onNospamEdit();
|
void onNospamEdit();
|
||||||
void onEncryptLogsUpdated();
|
|
||||||
bool setChatLogsPassword();
|
|
||||||
void onEncryptToxUpdated();
|
|
||||||
bool setToxPassword();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::PrivacySettings* bodyUI;
|
Ui::PrivacySettings* bodyUI;
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>380</width>
|
<width>380</width>
|
||||||
<height>391</height>
|
<height>280</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
@ -47,7 +47,7 @@
|
||||||
<string comment="tooltip for typing notifications setting">Your friends will be able to see when you are typing.</string>
|
<string comment="tooltip for typing notifications setting">Your friends will be able to see when you are typing.</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Send Typing Notifications</string>
|
<string>Send typing notifications</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -58,77 +58,10 @@
|
||||||
Save format changes are possible, which may result in data loss.</string>
|
Save format changes are possible, which may result in data loss.</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Keep chat history (mostly stable)</string>
|
<string>Keep chat history</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item alignment="Qt::AlignTop">
|
|
||||||
<widget class="QGroupBox" name="encryptionGroup">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="title">
|
|
||||||
<string>Local file encryption</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="encryptStatement">
|
|
||||||
<property name="text">
|
|
||||||
<string>All Tox communications over the internet are encrypted, and this cannot be disabled. However, you may optionally password protect your local Tox files.</string>
|
|
||||||
</property>
|
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="encryptToxHLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="cbEncryptTox">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Encrypt Tox data file</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="changeToxPwButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>Change password</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="encryptLogsHLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="cbEncryptHistory">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Encrypt chat history</string>
|
|
||||||
</property>
|
|
||||||
<property name="checkable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="changeLogsPwButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>Change password</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item alignment="Qt::AlignTop">
|
<item alignment="Qt::AlignTop">
|
||||||
<widget class="QGroupBox" name="nospamGroup">
|
<widget class="QGroupBox" name="nospamGroup">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
|
@ -138,9 +71,19 @@ When you change nospam, your current contacts still can communicate with you,
|
||||||
but new contacts need to know your new Tox ID to be able to add you.</string>
|
but new contacts need to know your new Tox ID to be able to add you.</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Nospam</string>
|
<string>NoSpam</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>The NoSpam is part of your Tox ID, if you are getting spammed with friend requests, change the NoSpam.</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<item>
|
<item>
|
||||||
|
@ -153,7 +96,7 @@ but new contacts need to know your new Tox ID to be able to add you.</string>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="randomNosapamButton">
|
<widget class="QPushButton" name="randomNosapamButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Generate random nospam</string>
|
<string>Generate random NoSpam</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -108,7 +108,7 @@ void LoginScreen::onLoginUsernameSelected(const QString &name)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ui->loginPassword->clear();
|
ui->loginPassword->clear();
|
||||||
if (Profile::isProfileEncrypted(name))
|
if (Profile::isEncrypted(name))
|
||||||
{
|
{
|
||||||
ui->loginPasswordLabel->show();
|
ui->loginPasswordLabel->show();
|
||||||
ui->loginPassword->show();
|
ui->loginPassword->show();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user