diff --git a/src/core/core.cpp b/src/core/core.cpp index 66ca8d526..08dde62b9 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -859,8 +859,8 @@ void Core::setAvatar(const QByteArray& data) ToxId Core::getSelfId() const { uint8_t friendAddress[TOX_ADDRESS_SIZE] = {0x00}; - tox_self_get_address(tox, friendAddress.data()); - return ToxId(friendAddress); + tox_self_get_address(tox, friendAddress); + return ToxId(friendAddress, TOX_ADDRESS_SIZE); } /** diff --git a/src/core/toxid.cpp b/src/core/toxid.cpp index 94d97c11f..df1285786 100644 --- a/src/core/toxid.cpp +++ b/src/core/toxid.cpp @@ -23,8 +23,8 @@ #include -#include #include +#include // Tox doesn't publicly define these #define NOSPAM_BYTES 4 @@ -35,6 +35,8 @@ #define CHECKSUM_HEX_CHARS (2*CHECKSUM_BYTES) #define TOXID_HEX_CHARS (2*TOX_ADDRESS_SIZE) +const QRegularExpression ToxId::ToxIdRegEx = QRegularExpression(QString("(^|\\s)[A-Fa-f0-9]{%1}($|\\s)").arg(TOXID_HEX_CHARS)); + /** * @class ToxId * @brief This class represents a Tox ID. @@ -56,7 +58,7 @@ * @brief The default constructor. Creates an empty Tox ID. */ ToxId::ToxId() -: toxId() +: toxId(TOX_ADDRESS_SIZE, 0x00) {} /** @@ -103,7 +105,7 @@ ToxId::ToxId(const QString& id) */ ToxId::ToxId(const QByteArray& rawId) { - checkToxId(rawId); + constructToxId(rawId); } /** @@ -117,14 +119,14 @@ ToxId::ToxId(const QByteArray& rawId) * @param len Number of bytes to read. Must be TOX_SECRET_KEY_SIZE for a Public Key or * TOX_ADDRESS_SIZE for a Tox ID. */ -ToxId::ToxId(const uint8_t& rawId, int len) +ToxId::ToxId(const uint8_t* rawId, int len) { QByteArray tmpId(reinterpret_cast(rawId), len); - checkToxId(tmpId); + constructToxId(tmpId); } -void ToxId::checkToxId(const QByteArray& rawId) +void ToxId::constructToxId(const QByteArray& rawId) { if(rawId.length() == TOX_SECRET_KEY_SIZE) { @@ -179,18 +181,6 @@ void ToxId::clear() toxId.clear(); } -/** - * @brief Check, that id is probably a valid Tox ID. - * @param id Tox ID to check. - * @return True if the string can be a ToxID, false otherwise. - * @note Doesn't validate checksum. - */ -bool ToxId::isValidToxId(const QString& id) -{ - const QRegularExpression hexRegExp("^[A-Fa-f0-9]+$"); - return id.length() == TOXID_HEX_CHARS && id.contains(hexRegExp); -} - /** * @brief Gets the ToxID as bytes, convenience function for toxcore interface. * @return The ToxID as uint8_t* @@ -245,27 +235,45 @@ QString ToxId::getNoSpamString() const * @brief Check, that id is a valid Tox ID. * @param id Tox ID to check. * @return True if id is a valid Tox ID, false otherwise. + * @note Validates the checksum. + */ +bool ToxId::isValidToxId(const QString& id) +{ + return isToxId(id) && ToxId(id).isValid(); +} + +/** + * @brief Check, that id is probably a valid Tox ID. + * @param id Tox ID to check. + * @return True if the string can be a ToxID, false otherwise. + * @note Doesn't validate checksum. */ bool ToxId::isToxId(const QString& id) { - if (!isValidToxId(id)) + return id.length() == TOXID_HEX_CHARS && id.contains(ToxIdRegEx); +} + +/** + * @brief Check it it's a valid Tox ID by verifying the checksum + * @return True if it is a valid Tox ID, false otherwise. + */ +bool ToxId::isValid() const +{ + if(toxId.length() != TOX_ADDRESS_SIZE) { return false; } - uint32_t size = PUBLIC_KEY_HEX_CHARS + NOSPAM_HEX_CHARS; - QString publicKeyStr = id.left(size); - QString checksumStr = id.right(CHECKSUM_HEX_CHARS); + const int size = TOX_PUBLIC_KEY_SIZE + NOSPAM_BYTES; - QByteArray publicKey = QByteArray::fromHex(publicKeyStr.toLatin1()); - QByteArray checksum = QByteArray::fromHex(checksumStr.toLatin1()); - uint8_t check[2] = {0}; + QByteArray data = toxId.left(size); + QByteArray checksum = toxId.right(CHECKSUM_BYTES); + QByteArray calculated(CHECKSUM_BYTES, 0x00); - for (uint32_t i = 0; i < size / 2; i++) + for (int i = 0; i < size; i++) { - check[i % 2] ^= publicKey.data()[i]; + calculated[i % 2] = calculated[i % 2] ^ data[i]; } - QByteArray caclulated(reinterpret_cast(check), 2); - return caclulated == checksum; - } + return calculated == checksum; +} diff --git a/src/core/toxid.h b/src/core/toxid.h index 79f6674ff..06972f0a3 100644 --- a/src/core/toxid.h +++ b/src/core/toxid.h @@ -30,15 +30,16 @@ public: ToxId(const ToxId& other); explicit ToxId(const QString& id); explicit ToxId(const QByteArray& rawId); - explicit ToxId(const uint8_t& rawId, int len); + explicit ToxId(const uint8_t* rawId, int len); bool operator==(const ToxId& other) const; bool operator!=(const ToxId& other) const; QString toString() const; void clear(); + bool isValid() const; - static bool isToxId(const QString& id); - static bool isValidToxId(const QString &id); + static bool isValidToxId(const QString& id); + static bool isToxId(const QString &id); const uint8_t* getBytes() const; QByteArray getToxId() const; QByteArray getPublicKey() const; @@ -47,7 +48,10 @@ public: QString getNoSpamString() const; private: - void checkToxId(const QByteArray& rawId); + void constructToxId(const QByteArray& rawId); + +public: + static const QRegularExpression ToxIdRegEx; private: QByteArray toxId; diff --git a/src/widget/form/addfriendform.cpp b/src/widget/form/addfriendform.cpp index 0ba760d38..d910c450a 100644 --- a/src/widget/form/addfriendform.cpp +++ b/src/widget/form/addfriendform.cpp @@ -164,13 +164,13 @@ void AddFriendForm::onSendTriggered() { QString id = toxId.text().trimmed(); - if (!ToxId::isToxId(id)) + if (!ToxId::isValidToxId(id)) { ToxId toxId = Toxme::lookup(id); // Try Toxme if (toxId.toString().isEmpty()) { GUI::showWarning(tr("Couldn't add friend"), - tr("This Tox ID does not exist", "Toxme error")); + tr("This Tox ID is invalid or does not exist", "Toxme error")); return; } id = toxId.toString();