diff --git a/src/core/core.cpp b/src/core/core.cpp index d6358a613..1b50a2c17 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -607,7 +607,7 @@ void Core::requestFriendship(const QString& friendAddress, const QString& messag Profile* profile = Nexus::getProfile(); if (profile->isHistoryEnabled()) - profile->getHistory()->addNewMessage(userId, inviteStr, getSelfId().publicKey, QDateTime::currentDateTime(), true, QString()); + profile->getHistory()->addNewMessage(userId, inviteStr, getSelfId().getPublicKeyString(), QDateTime::currentDateTime(), true, QString()); emit friendAdded(friendId, userId); emit friendshipChanged(friendId); } @@ -839,7 +839,7 @@ void Core::setAvatar(const QByteArray& data) { QPixmap pic; pic.loadFromData(data); - profile.saveAvatar(data, getSelfId().publicKey); + profile.saveAvatar(data, getSelfId().getPublicKeyString()); emit selfAvatarChanged(pic); } else diff --git a/src/core/toxid.cpp b/src/core/toxid.cpp index 4648c237c..7459927b1 100644 --- a/src/core/toxid.cpp +++ b/src/core/toxid.cpp @@ -25,10 +25,14 @@ #include #include -#define TOX_ID_PUBLIC_KEY_LENGTH 64 -#define TOX_ID_NO_SPAM_LENGTH 8 -#define TOX_ID_CHECKSUM_LENGTH 4 -#define TOX_HEX_ID_LENGTH 2*TOX_ADDRESS_SIZE +// Tox doesn't publicly define these +#define NOSPAM_BYTES 4 +#define CHECKSUM_BYTES 2 + +#define PUBLIC_KEY_HEX_CHARS (2*TOX_PUBLIC_KEY_SIZE) +#define NOSPAM_HEX_CHARS (2*NOSPAM_BYTES) +#define CHECKSUM_HEX_CHARS (2*CHECKSUM_BYTES) +#define TOXID_HEX_CHARS (2*TOX_ADDRESS_SIZE) /** * @class ToxId @@ -51,7 +55,7 @@ * @brief The default constructor. Creates an empty Tox ID. */ ToxId::ToxId() -: publicKey(), noSpam(), checkSum() +: toxId() {} /** @@ -59,11 +63,11 @@ ToxId::ToxId() * @param other ToxId to copy */ ToxId::ToxId(const ToxId &other) -: publicKey(other.publicKey), noSpam(other.noSpam), checkSum(other.checkSum) +: toxId(other.toxId) {} /** - * @brief Create a Tox ID from QString. + * @brief Create a Tox ID from a QString. * * If the given id is not a valid Tox ID, then: * publicKey == id and noSpam == "" == checkSum. @@ -74,13 +78,41 @@ ToxId::ToxId(const QString &id) { if (isToxId(id)) { - publicKey = id.left(TOX_ID_PUBLIC_KEY_LENGTH); - noSpam = id.mid(TOX_ID_PUBLIC_KEY_LENGTH, TOX_ID_NO_SPAM_LENGTH); - checkSum = id.right(TOX_ID_CHECKSUM_LENGTH); + toxId = QByteArray::fromHex(id.toLatin1()); + } + else if(id.length() >= PUBLIC_KEY_HEX_CHARS) + { + toxId = QByteArray::fromHex(id.left(PUBLIC_KEY_HEX_CHARS).toLatin1()); } else { - publicKey = id; + toxId = QByteArray(TOX_ADDRESS_SIZE, 0x00); // invalid id string + } +} + +/** + * @brief Create a Tox ID from a QByteArray. + * + * If the given id is not a valid Tox ID, then: + * publicKey == id and noSpam == "" == checkSum. + * + * @param id Tox ID string to convert to ToxId object + */ +ToxId::ToxId(const QByteArray &rawId) +{ + if(rawId.length() == TOX_SECRET_KEY_SIZE) + { + toxId = QByteArray(rawId); // construct from PK only + } + else if (rawId.length() == TOX_ADDRESS_SIZE + && isToxId(rawId.toHex().toUpper())) + { + + toxId = QByteArray(rawId); // construct from full toxid + } + else + { + toxId = QByteArray(TOX_ADDRESS_SIZE, 0x00); // invalid id string } } @@ -91,7 +123,7 @@ ToxId::ToxId(const QString &id) */ bool ToxId::operator==(const ToxId& other) const { - return publicKey == other.publicKey; + return getPublicKey() == other.getPublicKey(); } /** @@ -101,7 +133,7 @@ bool ToxId::operator==(const ToxId& other) const */ bool ToxId::operator!=(const ToxId &other) const { - return publicKey != other.publicKey; + return getPublicKey() != other.getPublicKey(); } /** @@ -110,7 +142,7 @@ bool ToxId::operator!=(const ToxId &other) const */ QString ToxId::toString() const { - return publicKey + noSpam + checkSum; + return toxId.toHex().toUpper(); } /** @@ -118,9 +150,7 @@ QString ToxId::toString() const */ void ToxId::clear() { - publicKey.clear(); - noSpam.clear(); - checkSum.clear(); + toxId.clear(); } /** @@ -132,7 +162,39 @@ void ToxId::clear() bool ToxId::isValidToxId(const QString& id) { const QRegularExpression hexRegExp("^[A-Fa-f0-9]+$"); - return id.length() == TOX_HEX_ID_LENGTH && id.contains(hexRegExp); + return id.length() == TOXID_HEX_CHARS && id.contains(hexRegExp); +} + +/** + * @brief Gets the Public Key part of the ToxID + * @return Public Key of the ToxID + */ +QByteArray ToxId::getPublicKey() const +{ + return toxId.mid(0, TOX_PUBLIC_KEY_SIZE); +} + +/** + * @brief Returns the Public Key converted to QString. + * @return The Public Key as QString. + */ +QString ToxId::getPublicKeyString() const +{ + return getPublicKey().toHex().toUpper(); +} + +/** + * @brief Returns the NoSpam value converted to QString. + * @return The NoSpam value as QString or "" if the ToxId was constructed from a Public Key. + */ +QString ToxId::getNoSpamString() const +{ + if(toxId.length() == TOX_ADDRESS_SIZE) + { + return toxId.mid(TOX_PUBLIC_KEY_SIZE, NOSPAM_BYTES).toHex().toUpper(); + } + + return {}; } /** @@ -147,9 +209,9 @@ bool ToxId::isToxId(const QString& id) return false; } - uint32_t size = TOX_ID_PUBLIC_KEY_LENGTH + TOX_ID_NO_SPAM_LENGTH; + uint32_t size = PUBLIC_KEY_HEX_CHARS + NOSPAM_HEX_CHARS; QString publicKeyStr = id.left(size); - QString checksumStr = id.right(TOX_ID_CHECKSUM_LENGTH); + QString checksumStr = id.right(CHECKSUM_HEX_CHARS); QByteArray publicKey = QByteArray::fromHex(publicKeyStr.toLatin1()); QByteArray checksum = QByteArray::fromHex(checksumStr.toLatin1()); diff --git a/src/core/toxid.h b/src/core/toxid.h index 4d3aa131a..c258685b8 100644 --- a/src/core/toxid.h +++ b/src/core/toxid.h @@ -29,6 +29,7 @@ public: ToxId(); ToxId(const ToxId& other); explicit ToxId(const QString& id); + explicit ToxId(const QByteArray& rawId); bool operator==(const ToxId& other) const; bool operator!=(const ToxId& other) const; @@ -37,11 +38,13 @@ public: static bool isToxId(const QString& id); static bool isValidToxId(const QString &id); + QByteArray getToxId() const; + QByteArray getPublicKey() const; + QString getPublicKeyString() const; + QString getNoSpamString() const; -public: - QString publicKey; - QString noSpam; - QString checkSum; +private: + QByteArray toxId; }; #endif // TOXID_H diff --git a/src/friend.cpp b/src/friend.cpp index 672979ec3..a0c20e854 100644 --- a/src/friend.cpp +++ b/src/friend.cpp @@ -37,7 +37,7 @@ Friend::Friend(uint32_t FriendId, const ToxId &UserId) { if (userName.size() == 0) - userName = UserId.publicKey; + userName = UserId.getPublicKeyString(); userAlias = Settings::getInstance().getFriendAlias(UserId); @@ -65,7 +65,7 @@ void Friend::loadHistory() void Friend::setName(QString name) { if (name.isEmpty()) - name = userID.publicKey; + name = userID.getPublicKeyString(); userName = name; if (userAlias.size() == 0) diff --git a/src/friendlist.cpp b/src/friendlist.cpp index 66cdb41a7..d67b15c5f 100644 --- a/src/friendlist.cpp +++ b/src/friendlist.cpp @@ -25,7 +25,7 @@ #include QHash FriendList::friendList; -QHash FriendList::tox2id; +QHash FriendList::tox2id; Friend* FriendList::addFriend(int friendId, const ToxId& userId) { @@ -35,7 +35,7 @@ Friend* FriendList::addFriend(int friendId, const ToxId& userId) Friend* newfriend = new Friend(friendId, userId); friendList[friendId] = newfriend; - tox2id[userId.publicKey] = friendId; + tox2id[userId.getPublicKey()] = friendId; return newfriend; } @@ -69,7 +69,7 @@ void FriendList::clear() Friend* FriendList::findFriend(const ToxId& userId) { - auto id = tox2id.find(userId.publicKey); + auto id = tox2id.find(userId.getPublicKey()); if (id != tox2id.end()) { Friend *f = findFriend(*id); diff --git a/src/friendlist.h b/src/friendlist.h index 60447ff8b..16a572896 100644 --- a/src/friendlist.h +++ b/src/friendlist.h @@ -23,7 +23,7 @@ template class QList; template class QHash; class Friend; -class QString; +class QByteArray; class ToxId; class FriendList @@ -38,7 +38,7 @@ public: private: static QHash friendList; - static QHash tox2id; + static QHash tox2id; }; #endif // FRIENDLIST_H diff --git a/src/group.cpp b/src/group.cpp index 47e277384..c96d8322d 100644 --- a/src/group.cpp +++ b/src/group.cpp @@ -49,7 +49,7 @@ Group::~Group() void Group::updatePeer(int peerId, QString name) { ToxId id = Core::getInstance()->getGroupPeerToxId(groupId, peerId); - QString toxid = id.publicKey; + QString toxid = id.getPublicKey(); peers[peerId] = name; toxids[toxid] = name; @@ -95,7 +95,7 @@ void Group::regeneratePeerList() if (id == self) selfPeerNum = i; - QString toxid = id.publicKey; + QString toxid = id.getPublicKey(); toxids[toxid] = peers[i]; if (toxids[toxid].isEmpty()) toxids[toxid] = tr("", "Placeholder when someone's name in a group chat is empty"); @@ -170,7 +170,7 @@ int Group::getMentionedFlag() const QString Group::resolveToxId(const ToxId &id) const { - QString key = id.publicKey; + QString key = id.getPublicKeyString(); auto it = toxids.find(key); if (it != toxids.end()) diff --git a/src/persistence/profile.cpp b/src/persistence/profile.cpp index 3309273f8..797d23de1 100644 --- a/src/persistence/profile.cpp +++ b/src/persistence/profile.cpp @@ -417,7 +417,7 @@ QString Profile::avatarPath(const QString& ownerId, bool forceUnencrypted) return Settings::getInstance().getSettingsDirPath() + "avatars/" + ownerId + ".png"; QByteArray idData = ownerId.toUtf8(); - QByteArray pubkeyData = core->getSelfId().publicKey.toUtf8(); + QByteArray pubkeyData = core->getSelfId().getPublicKey(); constexpr int hashSize = TOX_PUBLIC_KEY_SIZE; static_assert(hashSize >= crypto_generichash_BYTES_MIN && hashSize <= crypto_generichash_BYTES_MAX, "Hash size not supported by libsodium"); @@ -434,7 +434,7 @@ QString Profile::avatarPath(const QString& ownerId, bool forceUnencrypted) */ QPixmap Profile::loadAvatar() { - return loadAvatar(core->getSelfId().publicKey); + return loadAvatar(core->getSelfId().getPublicKeyString()); } /** @@ -503,7 +503,7 @@ void Profile::loadDatabase(const QString& id) return; } - QByteArray salt = QByteArray::fromHex(ToxId {id}.publicKey.toUtf8()); + QByteArray salt = ToxId {id}.getPublicKey(); if(salt.size() != TOX_PASS_SALT_LENGTH) { qWarning() << "Couldn't compute salt from public key" << name; @@ -572,7 +572,7 @@ QByteArray Profile::getAvatarHash(const QString& ownerId) */ void Profile::removeAvatar() { - removeAvatar(core->getSelfId().publicKey); + removeAvatar(core->getSelfId().getPublicKeyString()); } /** @@ -600,7 +600,7 @@ History* Profile::getHistory() void Profile::removeAvatar(const QString& ownerId) { QFile::remove(avatarPath(ownerId)); - if (ownerId == core->getSelfId().publicKey) + if (ownerId == core->getSelfId().getPublicKeyString()) core->setAvatar({}); } @@ -789,7 +789,7 @@ void Profile::restartCore() */ void Profile::setPassword(const QString& newPassword) { - QByteArray avatar = loadAvatarData(core->getSelfId().publicKey); + QByteArray avatar = loadAvatarData(core->getSelfId().getPublicKeyString()); QString oldPassword = password; password = newPassword; passkey = core->createPasskey(password); @@ -801,7 +801,7 @@ void Profile::setPassword(const QString& newPassword) } Nexus::getDesktopGUI()->reloadHistory(); - saveAvatar(avatar, core->getSelfId().publicKey); + saveAvatar(avatar, core->getSelfId().getPublicKeyString()); QVector friendList = core->getFriendList(); QVectorIterator i(friendList); diff --git a/src/persistence/settings.cpp b/src/persistence/settings.cpp index 9e2e9a9ed..791939366 100644 --- a/src/persistence/settings.cpp +++ b/src/persistence/settings.cpp @@ -390,7 +390,7 @@ void Settings::loadPersonal(Profile* profile) if (getEnableLogging()) fp.activity = ps.value("activity", QDate()).toDate(); - friendLst[ToxId(fp.addr).publicKey] = fp; + friendLst[ToxId(fp.addr).getPublicKeyString()] = fp; } ps.endArray(); } @@ -1433,7 +1433,7 @@ void Settings::setAutoAwayTime(int newValue) QString Settings::getAutoAcceptDir(const ToxId& id) const { QMutexLocker locker{&bigLock}; - QString key = id.publicKey; + QString key = id.getPublicKeyString(); auto it = friendLst.find(key); if (it != friendLst.end()) @@ -1445,7 +1445,7 @@ QString Settings::getAutoAcceptDir(const ToxId& id) const void Settings::setAutoAcceptDir(const ToxId &id, const QString& dir) { QMutexLocker locker{&bigLock}; - QString key = id.publicKey; + QString key = id.getPublicKeyString(); auto it = friendLst.find(key); if (it != friendLst.end()) @@ -1462,7 +1462,7 @@ void Settings::setAutoAcceptDir(const ToxId &id, const QString& dir) Settings::AutoAcceptCallFlags Settings::getAutoAcceptCall(const ToxId &id) const { QMutexLocker locker{&bigLock}; - QString key = id.publicKey; + QString key = id.getPublicKeyString(); auto it = friendLst.find(key); if (it != friendLst.end()) @@ -1474,7 +1474,7 @@ Settings::AutoAcceptCallFlags Settings::getAutoAcceptCall(const ToxId &id) const void Settings::setAutoAcceptCall(const ToxId& id, AutoAcceptCallFlags accept) { QMutexLocker locker{&bigLock}; - QString key = id.publicKey; + QString key = id.getPublicKeyString(); auto it = friendLst.find(key); if(it != friendLst.end()) @@ -1488,7 +1488,7 @@ QString Settings::getContactNote(const ToxId &id) const { QMutexLocker locker{&bigLock}; - auto it = friendLst.find(id.publicKey); + auto it = friendLst.find(id.getPublicKeyString()); if (it != friendLst.end()) return it->note; @@ -1499,7 +1499,7 @@ void Settings::setContactNote(const ToxId &id, const QString& note) { QMutexLocker locker{&bigLock}; - auto it = friendLst.find(id.publicKey); + auto it = friendLst.find(id.getPublicKeyString()); if (it != friendLst.end()) { qDebug() << note; @@ -2009,7 +2009,7 @@ void Settings::setCamVideoFPS(unsigned short newValue) QString Settings::getFriendAddress(const QString& publicKey) const { QMutexLocker locker{&bigLock}; - QString key = ToxId(publicKey).publicKey; + QString key = ToxId(publicKey).getPublicKeyString(); auto it = friendLst.find(key); if (it != friendLst.end()) return it->addr; @@ -2020,7 +2020,7 @@ QString Settings::getFriendAddress(const QString& publicKey) const void Settings::updateFriendAddress(const QString& newAddr) { QMutexLocker locker{&bigLock}; - QString key = ToxId(newAddr).publicKey; + QString key = ToxId(newAddr).getPublicKeyString(); auto it = friendLst.find(key); if (it != friendLst.end()) { @@ -2040,7 +2040,7 @@ void Settings::updateFriendAddress(const QString& newAddr) QString Settings::getFriendAlias(const ToxId& id) const { QMutexLocker locker{&bigLock}; - QString key = id.publicKey; + QString key = id.getPublicKeyString(); auto it = friendLst.find(key); if (it != friendLst.end()) return it->alias; @@ -2051,7 +2051,7 @@ QString Settings::getFriendAlias(const ToxId& id) const void Settings::setFriendAlias(const ToxId& id, const QString& alias) { QMutexLocker locker{&bigLock}; - QString key = id.publicKey; + QString key = id.getPublicKeyString(); auto it = friendLst.find(key); if (it != friendLst.end()) { @@ -2070,7 +2070,7 @@ void Settings::setFriendAlias(const ToxId& id, const QString& alias) int Settings::getFriendCircleID(const ToxId& id) const { - QString key = id.publicKey; + QString key = id.getPublicKeyString(); auto it = friendLst.find(key); if (it != friendLst.end()) return it->circleID; @@ -2080,7 +2080,7 @@ int Settings::getFriendCircleID(const ToxId& id) const void Settings::setFriendCircleID(const ToxId& id, int circleID) { - QString key = id.publicKey; + QString key = id.getPublicKeyString(); auto it = friendLst.find(key); if (it != friendLst.end()) { @@ -2100,7 +2100,7 @@ void Settings::setFriendCircleID(const ToxId& id, int circleID) QDate Settings::getFriendActivity(const ToxId& id) const { - QString key = id.publicKey; + QString key = id.getPublicKeyString(); auto it = friendLst.find(key); if (it != friendLst.end()) return it->activity; @@ -2110,7 +2110,7 @@ QDate Settings::getFriendActivity(const ToxId& id) const void Settings::setFriendActivity(const ToxId& id, const QDate& activity) { - QString key = id.publicKey; + QString key = id.getPublicKeyString(); auto it = friendLst.find(key); if (it != friendLst.end()) { @@ -2132,7 +2132,7 @@ void Settings::setFriendActivity(const ToxId& id, const QDate& activity) void Settings::removeFriendSettings(const ToxId& id) { QMutexLocker locker{&bigLock}; - QString key = id.publicKey; + QString key = id.getPublicKeyString(); friendLst.remove(key); } diff --git a/src/widget/about/aboutuser.cpp b/src/widget/about/aboutuser.cpp index b59077501..08176fcbb 100644 --- a/src/widget/about/aboutuser.cpp +++ b/src/widget/about/aboutuser.cpp @@ -112,7 +112,7 @@ void AboutUser::onRemoveHistoryClicked() { History* history = Nexus::getProfile()->getHistory(); if (history) - history->removeFriendHistory(toxId.publicKey); + history->removeFriendHistory(toxId.getPublicKeyString()); QMessageBox::information(this, tr("History removed"), tr("Chat history with %1 removed!").arg(ui->userName->text().toHtmlEscaped()), diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index 9d0f6e41d..6c9e24de5 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -717,7 +717,7 @@ void ChatForm::loadHistory(QDateTime since, bool processUndelivered) } } - auto msgs = Nexus::getProfile()->getHistory()->getChatHistory(f->getToxId().publicKey, since, now); + auto msgs = Nexus::getProfile()->getHistory()->getChatHistory(f->getToxId().getPublicKeyString(), since, now); ToxId storedPrevId = previousId; ToxId prevId; @@ -1062,8 +1062,8 @@ void ChatForm::SendMessageStr(QString msg) if (profile->isHistoryEnabled()) { auto* offMsgEngine = getOfflineMsgEngine(); - profile->getHistory()->addNewMessage(f->getToxId().publicKey, qt_msg_hist, - Core::getInstance()->getSelfId().publicKey, timestamp, status, Core::getInstance()->getUsername(), + profile->getHistory()->addNewMessage(f->getToxId().getPublicKeyString(), qt_msg_hist, + Core::getInstance()->getSelfId().getPublicKeyString(), timestamp, status, Core::getInstance()->getUsername(), [offMsgEngine,rec,ma](int64_t id) { offMsgEngine->registerReceipt(rec, id, ma); diff --git a/src/widget/form/settings/privacyform.cpp b/src/widget/form/settings/privacyform.cpp index 4a3112e94..f733c6403 100644 --- a/src/widget/form/settings/privacyform.cpp +++ b/src/widget/form/settings/privacyform.cpp @@ -89,7 +89,7 @@ void PrivacyForm::on_nospamLineEdit_editingFinished() void PrivacyForm::showEvent(QShowEvent*) { const Settings& s = Settings::getInstance(); - bodyUI->nospamLineEdit->setText(Core::getInstance()->getSelfId().noSpam); + bodyUI->nospamLineEdit->setText(Core::getInstance()->getSelfId().getNoSpamString()); bodyUI->cbTypingNotification->setChecked(s.getTypingNotification()); bodyUI->cbKeepHistory->setChecked(Settings::getInstance().getEnableLogging()); } @@ -104,7 +104,7 @@ void PrivacyForm::on_randomNosapamButton_clicked() newNospam = (newNospam<<8) + (qrand() % 256); // Generate byte by byte. For some reason. Core::getInstance()->setNospam(newNospam); - bodyUI->nospamLineEdit->setText(Core::getInstance()->getSelfId().noSpam); + bodyUI->nospamLineEdit->setText(Core::getInstance()->getSelfId().getNoSpamString()); } void PrivacyForm::on_nospamLineEdit_textChanged() diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index 26cb19709..c44fa33a2 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -1222,7 +1222,7 @@ void Widget::onFriendMessageReceived(int friendId, const QString& message, bool Profile* profile = Nexus::getProfile(); if (profile->isHistoryEnabled()) { - QString publicKey = f->getToxId().publicKey; + QString publicKey = f->getToxId().getPublicKeyString(); QString name = f->getDisplayedName(); QString text = message; if (isAction) @@ -1501,7 +1501,7 @@ void Widget::removeFriend(Friend* f, bool fake) if (ask.removeHistory()) { - Nexus::getProfile()->getHistory()->removeFriendHistory(f->getToxId().publicKey); + Nexus::getProfile()->getHistory()->removeFriendHistory(f->getToxId().getPublicKeyString()); } }