mirror of https://github.com/qTox/qTox.git
Browse Source
As of 2019-10-09, toxme.io was taken offline permanently. Remove UI and code in qTox relating to it. Revert this commit if it comes back online in the future. Fix #5897reviewable/pr5898/r2
15 changed files with 7 additions and 1318 deletions
@ -1,295 +0,0 @@ |
|||||||
/*
|
|
||||||
Copyright © 2015-2019 by The qTox Project Contributors |
|
||||||
|
|
||||||
This file is part of qTox, a Qt-based graphical interface for Tox. |
|
||||||
|
|
||||||
qTox is libre software: you can redistribute it and/or modify |
|
||||||
it under the terms of the GNU General Public License as published by |
|
||||||
the Free Software Foundation, either version 3 of the License, or |
|
||||||
(at your option) any later version. |
|
||||||
|
|
||||||
qTox is distributed in the hope that it will be useful, |
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
GNU General Public License for more details. |
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License |
|
||||||
along with qTox. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/ |
|
||||||
|
|
||||||
#include "toxme.h" |
|
||||||
#include "src/core/core.h" |
|
||||||
#include "src/core/toxpk.h" |
|
||||||
#include "src/net/toxmedata.h" |
|
||||||
#include "src/persistence/settings.h" |
|
||||||
|
|
||||||
#include <ctime> |
|
||||||
#include <sodium/crypto_box.h> |
|
||||||
#include <sodium/randombytes.h> |
|
||||||
#include <string> |
|
||||||
|
|
||||||
#include <QCoreApplication> |
|
||||||
#include <QNetworkAccessManager> |
|
||||||
#include <QNetworkReply> |
|
||||||
#include <QThread> |
|
||||||
#include <QtDebug> |
|
||||||
|
|
||||||
static ToxmeData toxmeData; |
|
||||||
|
|
||||||
/**
|
|
||||||
* @class Toxme |
|
||||||
* @brief This class implements a client for the toxme.se API |
|
||||||
* |
|
||||||
* @note The class is thread safe |
|
||||||
* @note May process events while waiting for blocking calls |
|
||||||
*/ |
|
||||||
|
|
||||||
QByteArray Toxme::makeJsonRequest(QString url, QString json, QNetworkReply::NetworkError& error) |
|
||||||
{ |
|
||||||
if (error) |
|
||||||
return QByteArray(); |
|
||||||
|
|
||||||
QNetworkAccessManager netman; |
|
||||||
netman.setProxy(Settings::getInstance().getProxy()); |
|
||||||
QNetworkRequest request{url}; |
|
||||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); |
|
||||||
QNetworkReply* reply = netman.post(request, json.toUtf8()); |
|
||||||
|
|
||||||
while (!reply->isFinished()) { |
|
||||||
QThread::msleep(1); |
|
||||||
qApp->processEvents(); |
|
||||||
} |
|
||||||
|
|
||||||
QByteArray result = reply->readAll(); |
|
||||||
delete reply; |
|
||||||
return result; |
|
||||||
} |
|
||||||
|
|
||||||
QByteArray Toxme::getServerPubkey(QString url, QNetworkReply::NetworkError& error) |
|
||||||
{ |
|
||||||
if (error) |
|
||||||
return QByteArray(); |
|
||||||
|
|
||||||
// Get key
|
|
||||||
QNetworkAccessManager netman; |
|
||||||
netman.setProxy(Settings::getInstance().getProxy()); |
|
||||||
QNetworkRequest request{url}; |
|
||||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); |
|
||||||
QNetworkReply* reply = netman.get(request); |
|
||||||
|
|
||||||
while (!reply->isFinished()) { |
|
||||||
QThread::msleep(1); |
|
||||||
qApp->processEvents(); |
|
||||||
} |
|
||||||
|
|
||||||
error = reply->error(); |
|
||||||
if (error) { |
|
||||||
qWarning() << "getServerPubkey: A network error occured:" << reply->errorString(); |
|
||||||
return QByteArray(); |
|
||||||
} |
|
||||||
|
|
||||||
QString json = reply->readAll(); |
|
||||||
delete reply; |
|
||||||
return toxmeData.parsePublicKey(json); |
|
||||||
} |
|
||||||
|
|
||||||
QByteArray Toxme::prepareEncryptedJson(QString url, int action, QString payload) |
|
||||||
{ |
|
||||||
QPair<QByteArray, QByteArray> keypair = Core::getInstance()->getKeypair(); |
|
||||||
if (keypair.first.isEmpty() || keypair.second.isEmpty()) { |
|
||||||
qWarning() << "prepareEncryptedJson: Couldn't get our keypair, aborting"; |
|
||||||
return QByteArray(); |
|
||||||
} |
|
||||||
|
|
||||||
QNetworkReply::NetworkError error = QNetworkReply::NoError; |
|
||||||
QByteArray key = getServerPubkey(url, error); |
|
||||||
if (error != QNetworkReply::NoError) |
|
||||||
return QByteArray(); |
|
||||||
|
|
||||||
QByteArray nonce(crypto_box_NONCEBYTES, 0); |
|
||||||
randombytes((uint8_t*)nonce.data(), crypto_box_NONCEBYTES); |
|
||||||
|
|
||||||
QByteArray payloadData = payload.toUtf8(); |
|
||||||
const size_t cypherlen = crypto_box_MACBYTES + payloadData.size(); |
|
||||||
unsigned char* payloadEnc = new unsigned char[cypherlen]; |
|
||||||
|
|
||||||
int cryptResult = crypto_box_easy(payloadEnc, (uint8_t*)payloadData.data(), payloadData.size(), |
|
||||||
(uint8_t*)nonce.data(), (unsigned char*)key.constData(), |
|
||||||
(uint8_t*)keypair.second.data()); |
|
||||||
|
|
||||||
if (cryptResult != 0) // error
|
|
||||||
return QByteArray(); |
|
||||||
|
|
||||||
QByteArray payloadEncData(reinterpret_cast<char*>(payloadEnc), cypherlen); |
|
||||||
delete[] payloadEnc; |
|
||||||
|
|
||||||
return toxmeData.encryptedJson(action, keypair.first, payloadEncData, nonce).toUtf8(); |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Converts a toxme address to a Tox ID. |
|
||||||
* @param address Toxme address. |
|
||||||
* @return Found ToxId (an empty ID on error). |
|
||||||
*/ |
|
||||||
ToxId Toxme::lookup(QString address) |
|
||||||
{ |
|
||||||
// JSON injection ?
|
|
||||||
address = address.trimmed(); |
|
||||||
address.replace('\\', "\\\\"); |
|
||||||
address.replace('"', "\""); |
|
||||||
|
|
||||||
const QString json = toxmeData.lookupRequest(address); |
|
||||||
|
|
||||||
QString apiUrl = "https://" + address.split(QLatin1Char('@')).last() + "/api"; |
|
||||||
QNetworkReply::NetworkError error = QNetworkReply::NoError; |
|
||||||
QString response = makeJsonRequest(apiUrl, json, error); |
|
||||||
|
|
||||||
if (error != QNetworkReply::NoError) |
|
||||||
return ToxId(); |
|
||||||
|
|
||||||
return toxmeData.lookup(response); |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Creates a new toxme address associated with a Tox ID. |
|
||||||
* @param[out] code Tox error code @see getErrorMessage. |
|
||||||
* @param[in] server Create toxme account on this server. |
|
||||||
* @param[in] id ToxId of current user. |
|
||||||
* @param[in] address Create toxme account with this adress. |
|
||||||
* @param[in] keepPrivate If true, the address will not be published on toxme site. |
|
||||||
* @param[in] bio A short optional description of yourself if you want to publish your address. |
|
||||||
* @return password on success, else sets code parameter and returns an empty QString. |
|
||||||
*/ |
|
||||||
QString Toxme::createAddress(ToxmeData::ExecCode& code, QString server, ToxId id, QString address, |
|
||||||
bool keepPrivate, QString bio) |
|
||||||
{ |
|
||||||
// JSON injection ?
|
|
||||||
bio.replace('\\', "\\\\"); |
|
||||||
bio.replace('"', "\""); |
|
||||||
|
|
||||||
address.replace('\\', "\\\\"); |
|
||||||
address.replace('"', "\""); |
|
||||||
|
|
||||||
bio = bio.trimmed(); |
|
||||||
address = address.trimmed(); |
|
||||||
server = server.trimmed(); |
|
||||||
if (!server.contains("://")) |
|
||||||
server = "https://" + server; |
|
||||||
|
|
||||||
const QString payload = toxmeData.createAddressRequest(id, address, bio, keepPrivate); |
|
||||||
QString pubkeyUrl = server + "/pk"; |
|
||||||
QString apiUrl = server + "/api"; |
|
||||||
QNetworkReply::NetworkError error = QNetworkReply::NoError; |
|
||||||
QByteArray encrypted = prepareEncryptedJson(pubkeyUrl, 1, payload); |
|
||||||
QByteArray response = makeJsonRequest(apiUrl, encrypted, error); |
|
||||||
|
|
||||||
code = toxmeData.extractCode(response); |
|
||||||
if ((code != ToxmeData::Ok && code != ToxmeData::Updated) || error != QNetworkReply::NoError) |
|
||||||
return QString(); |
|
||||||
|
|
||||||
return toxmeData.getPass(response, code); |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Deletes the address associated with your current Tox ID. |
|
||||||
* @param server Server to delete the address from. |
|
||||||
* @param id ToxId to delete. |
|
||||||
* @return Status code returned from server. |
|
||||||
*/ |
|
||||||
ToxmeData::ExecCode Toxme::deleteAddress(QString server, ToxPk pk) |
|
||||||
{ |
|
||||||
const QString payload = toxmeData.deleteAddressRequest(pk); |
|
||||||
|
|
||||||
server = server.trimmed(); |
|
||||||
if (!server.contains("://")) |
|
||||||
server = "https://" + server; |
|
||||||
|
|
||||||
QString pubkeyUrl = server + "/pk"; |
|
||||||
QString apiUrl = server + "/api"; |
|
||||||
QNetworkReply::NetworkError error = QNetworkReply::NoError; |
|
||||||
QByteArray response = makeJsonRequest(apiUrl, prepareEncryptedJson(pubkeyUrl, 2, payload), error); |
|
||||||
|
|
||||||
return toxmeData.extractCode(response); |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Return string of the corresponding error code |
|
||||||
* @param errorCode Code to get error message |
|
||||||
* @return Source error message |
|
||||||
*/ |
|
||||||
QString Toxme::getErrorMessage(int errorCode) |
|
||||||
{ |
|
||||||
switch (errorCode) { |
|
||||||
case ToxmeData::IncorrectResponse: |
|
||||||
return "Incorrect response"; |
|
||||||
case ToxmeData::NoPassword: |
|
||||||
return "No password in response"; |
|
||||||
case ToxmeData::ServerError: |
|
||||||
return "Server doesn't support Toxme"; |
|
||||||
case -1: |
|
||||||
return "You must send POST requests to /api"; |
|
||||||
case -2: |
|
||||||
return "Problem with HTTPS connection"; |
|
||||||
case -3: |
|
||||||
return "I was unable to read your encrypted payload"; |
|
||||||
case -4: |
|
||||||
return "You're making too many requests. Wait an hour and try again"; |
|
||||||
case -25: |
|
||||||
return "This name is already in use"; |
|
||||||
case -26: |
|
||||||
return "This Tox ID is already registered under another name"; |
|
||||||
case -27: |
|
||||||
return "Please don't use a space in your name"; |
|
||||||
case -28: |
|
||||||
return "Password incorrect"; |
|
||||||
case -29: |
|
||||||
return "You can't use this name"; |
|
||||||
case -30: |
|
||||||
return "Name not found"; |
|
||||||
case -31: |
|
||||||
return "Tox ID not sent"; |
|
||||||
case -41: |
|
||||||
return "Lookup failed because the server replied with invalid data"; |
|
||||||
case -42: |
|
||||||
return "That user does not exist"; |
|
||||||
case -43: |
|
||||||
return "Internal lookup error. Please file a bug"; |
|
||||||
default: |
|
||||||
return QString("Unknown error (%1)").arg(errorCode); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Return translated error message |
|
||||||
* @param errorCode Code to translate |
|
||||||
* @return Translated Toxme error message |
|
||||||
*/ |
|
||||||
QString Toxme::translateErrorMessage(int errorCode) |
|
||||||
{ |
|
||||||
switch (errorCode) { |
|
||||||
case ToxmeData::ServerError: |
|
||||||
return QObject::tr("Server doesn't support Toxme"); |
|
||||||
case -2: |
|
||||||
return QObject::tr("Problem with HTTPS connection"); |
|
||||||
case -4: |
|
||||||
return QObject::tr("You're making too many requests. Wait an hour and try again"); |
|
||||||
case -25: |
|
||||||
return QObject::tr("This name is already in use"); |
|
||||||
case -26: |
|
||||||
return QObject::tr("This Tox ID is already registered under another name"); |
|
||||||
case -27: |
|
||||||
return QObject::tr("Please don't use a space in your name"); |
|
||||||
case -28: |
|
||||||
return QObject::tr("Password incorrect"); |
|
||||||
case -29: |
|
||||||
return QObject::tr("You can't use this name"); |
|
||||||
case -30: |
|
||||||
return QObject::tr("Name not found"); |
|
||||||
case -31: |
|
||||||
return QObject::tr("Tox ID not sent"); |
|
||||||
case -42: |
|
||||||
return QObject::tr("That user does not exist"); |
|
||||||
default: |
|
||||||
return QObject::tr("Internal ToxMe error"); |
|
||||||
} |
|
||||||
} |
|
@ -1,56 +0,0 @@ |
|||||||
/*
|
|
||||||
Copyright © 2015-2019 by The qTox Project Contributors |
|
||||||
|
|
||||||
This file is part of qTox, a Qt-based graphical interface for Tox. |
|
||||||
|
|
||||||
qTox is libre software: you can redistribute it and/or modify |
|
||||||
it under the terms of the GNU General Public License as published by |
|
||||||
the Free Software Foundation, either version 3 of the License, or |
|
||||||
(at your option) any later version. |
|
||||||
|
|
||||||
qTox is distributed in the hope that it will be useful, |
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
GNU General Public License for more details. |
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License |
|
||||||
along with qTox. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/ |
|
||||||
|
|
||||||
|
|
||||||
#ifndef TOXME_H |
|
||||||
#define TOXME_H |
|
||||||
|
|
||||||
#include "src/core/toxid.h" |
|
||||||
#include "src/net/toxmedata.h" |
|
||||||
#include <QMap> |
|
||||||
#include <QMutex> |
|
||||||
#include <QNetworkReply> |
|
||||||
#include <QString> |
|
||||||
#include <memory> |
|
||||||
|
|
||||||
class QNetworkAccessManager; |
|
||||||
|
|
||||||
class Toxme |
|
||||||
{ |
|
||||||
public: |
|
||||||
static ToxId lookup(QString address); |
|
||||||
static QString createAddress(ToxmeData::ExecCode& code, QString server, ToxId id, |
|
||||||
QString address, bool keepPrivate = true, QString bio = QString()); |
|
||||||
static ToxmeData::ExecCode deleteAddress(QString server, ToxPk id); |
|
||||||
static QString getErrorMessage(int errorCode); |
|
||||||
static QString translateErrorMessage(int errorCode); |
|
||||||
|
|
||||||
private: |
|
||||||
Toxme() = delete; |
|
||||||
static QByteArray makeJsonRequest(QString url, QString json, QNetworkReply::NetworkError& error); |
|
||||||
static QByteArray prepareEncryptedJson(QString url, int action, QString payload); |
|
||||||
static QByteArray getServerPubkey(QString url, QNetworkReply::NetworkError& error); |
|
||||||
static ToxmeData::ExecCode extractError(QString json); |
|
||||||
|
|
||||||
private: |
|
||||||
static const QMap<QString, QString> pubkeyUrls; |
|
||||||
static const QMap<QString, QString> apiUrls; |
|
||||||
}; |
|
||||||
|
|
||||||
#endif // TOXME_H
|
|
@ -1,194 +0,0 @@ |
|||||||
/*
|
|
||||||
Copyright © 2017-2019 by The qTox Project Contributors |
|
||||||
|
|
||||||
This file is part of qTox, a Qt-based graphical interface for Tox. |
|
||||||
|
|
||||||
qTox is libre software: you can redistribute it and/or modify |
|
||||||
it under the terms of the GNU General Public License as published by |
|
||||||
the Free Software Foundation, either version 3 of the License, or |
|
||||||
(at your option) any later version. |
|
||||||
|
|
||||||
qTox is distributed in the hope that it will be useful, |
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
GNU General Public License for more details. |
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License |
|
||||||
along with qTox. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/ |
|
||||||
|
|
||||||
#include "toxmedata.h" |
|
||||||
#include "src/core/toxid.h" |
|
||||||
|
|
||||||
#include <QDateTime> |
|
||||||
#include <QJsonDocument> |
|
||||||
#include <QJsonObject> |
|
||||||
#include <QString> |
|
||||||
|
|
||||||
namespace { |
|
||||||
namespace consts { |
|
||||||
namespace keys { |
|
||||||
const QString Key{QStringLiteral("key")}; |
|
||||||
const QString Action{QStringLiteral("action")}; |
|
||||||
const QString PublicKey{QStringLiteral("public_key")}; |
|
||||||
const QString Encrypted{QStringLiteral("encrypted")}; |
|
||||||
const QString Nonce{QStringLiteral("nonce")}; |
|
||||||
const QString Name{QStringLiteral("name")}; |
|
||||||
const QString ToxId{QStringLiteral("tox_id")}; |
|
||||||
const QString Code{QStringLiteral("c")}; |
|
||||||
const QString Bio{QStringLiteral("bio")}; |
|
||||||
const QString Privacy{QStringLiteral("privacy")}; |
|
||||||
const QString Timestamp{QStringLiteral("timestamp")}; |
|
||||||
const QString Password{QStringLiteral("password")}; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static qint64 getCurrentTime() |
|
||||||
{ |
|
||||||
return QDateTime::currentDateTimeUtc().toMSecsSinceEpoch() / 1000; |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get server public key from Json. |
|
||||||
* @param text Json text. |
|
||||||
* @return Server public key. |
|
||||||
*/ |
|
||||||
QByteArray ToxmeData::parsePublicKey(const QString& text) const |
|
||||||
{ |
|
||||||
const QJsonObject json = QJsonDocument::fromJson(text.toLatin1()).object(); |
|
||||||
const QString& key = json[consts::keys::Key].toString(); |
|
||||||
return QByteArray::fromHex(key.toLatin1()); |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Build Json with encrypted payload. |
|
||||||
* @param action Action number. |
|
||||||
* @param pk User public key |
|
||||||
* @param encrypted Encrypted payload. |
|
||||||
* @param nonce Crypto nonce. |
|
||||||
* @return Json with action and encrypted payload. |
|
||||||
*/ |
|
||||||
QString ToxmeData::encryptedJson(int action, const QByteArray& pk, const QByteArray& encrypted, |
|
||||||
const QByteArray& nonce) const |
|
||||||
{ |
|
||||||
const QJsonObject json = { |
|
||||||
{ consts::keys::Action, action }, |
|
||||||
{ consts::keys::PublicKey, QString{pk.toHex()} }, |
|
||||||
{ consts::keys::Encrypted, QString{encrypted.toBase64()} }, |
|
||||||
{ consts::keys::Nonce, QString{nonce.toBase64()} }, |
|
||||||
}; |
|
||||||
|
|
||||||
return QJsonDocument{json}.toJson(QJsonDocument::Compact); |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Build lookup request Json. |
|
||||||
* @param address Address to lookup. |
|
||||||
* @return Json to lookup. |
|
||||||
*/ |
|
||||||
QString ToxmeData::lookupRequest(const QString& address) const |
|
||||||
{ |
|
||||||
const QJsonObject json = { |
|
||||||
{ consts::keys::Action, 3 }, |
|
||||||
{ consts::keys::Name, address }, |
|
||||||
}; |
|
||||||
|
|
||||||
return QJsonDocument{json}.toJson(QJsonDocument::Compact); |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Extract ToxId from lookup Json. |
|
||||||
* @param inText Json text. |
|
||||||
* @return User ToxId. |
|
||||||
*/ |
|
||||||
ToxId ToxmeData::lookup(const QString& inText) const |
|
||||||
{ |
|
||||||
const QJsonObject json = QJsonDocument::fromJson(inText.toLatin1()).object(); |
|
||||||
const QString& text = json[consts::keys::ToxId].toString(); |
|
||||||
return ToxId{text}; |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Extract toxme result code. |
|
||||||
* @param srcJson Json text. |
|
||||||
* @return Toxme code result. |
|
||||||
*/ |
|
||||||
ToxmeData::ExecCode ToxmeData::extractCode(const QString& srcJson) const |
|
||||||
{ |
|
||||||
const QJsonObject json = QJsonDocument::fromJson(srcJson.toLatin1()).object(); |
|
||||||
if (json.isEmpty()) { |
|
||||||
return ServerError; |
|
||||||
} |
|
||||||
|
|
||||||
const int code = json[consts::keys::Code].toInt(INT32_MAX); |
|
||||||
if (code == INT32_MAX) { |
|
||||||
return IncorrectResponse; |
|
||||||
} |
|
||||||
|
|
||||||
return ExecCode(code); |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Build create address request Json. |
|
||||||
* @param id Self ToxId. |
|
||||||
* @param address Preferred address. |
|
||||||
* @param bio Self biography. |
|
||||||
* @param keepPrivate If true, the address will not be published on toxme site. |
|
||||||
* @return Json to register Toxme address. |
|
||||||
*/ |
|
||||||
QString ToxmeData::createAddressRequest(const ToxId id, const QString& address, const QString& bio, |
|
||||||
bool keepPrivate) const |
|
||||||
{ |
|
||||||
const QJsonObject json = { |
|
||||||
{ consts::keys::Bio, bio }, |
|
||||||
{ consts::keys::Name, address }, |
|
||||||
{ consts::keys::ToxId, id.toString() }, |
|
||||||
{ consts::keys::Privacy, keepPrivate ? 0 : 2 }, |
|
||||||
{ consts::keys::Timestamp, getCurrentTime() }, |
|
||||||
}; |
|
||||||
|
|
||||||
return QJsonDocument{json}.toJson(QJsonDocument::Compact); |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Extrace password from Json answer. |
|
||||||
* @param srcJson[in] Json text. |
|
||||||
* @param code[out] Result code. Changed if password not extracted. |
|
||||||
* @return Extracted password. |
|
||||||
*/ |
|
||||||
QString ToxmeData::getPass(const QString& srcJson, ToxmeData::ExecCode& code) |
|
||||||
{ |
|
||||||
const QJsonObject json = QJsonDocument::fromJson(srcJson.toLatin1()).object(); |
|
||||||
if (json.isEmpty()) { |
|
||||||
code = ToxmeData::NoPassword; |
|
||||||
return QString{}; |
|
||||||
} |
|
||||||
|
|
||||||
const QJsonValue pass = json[consts::keys::Password]; |
|
||||||
if (pass.isNull()) { |
|
||||||
code = ToxmeData::Updated; |
|
||||||
return QString{}; |
|
||||||
} |
|
||||||
|
|
||||||
if (!pass.isString()) { |
|
||||||
code = ToxmeData::IncorrectResponse; |
|
||||||
return QString{}; |
|
||||||
} |
|
||||||
|
|
||||||
return pass.toString(); |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Build Json to delete address. |
|
||||||
* @param pk Self public key. |
|
||||||
* @return Json to delete address. |
|
||||||
*/ |
|
||||||
QString ToxmeData::deleteAddressRequest(const ToxPk& pk) |
|
||||||
{ |
|
||||||
QJsonObject json = { |
|
||||||
{ consts::keys::PublicKey, pk.toString() }, |
|
||||||
{ consts::keys::Timestamp, getCurrentTime() }, |
|
||||||
}; |
|
||||||
return QJsonDocument{json}.toJson(QJsonDocument::Compact); |
|
||||||
} |
|
@ -1,55 +0,0 @@ |
|||||||
/*
|
|
||||||
Copyright © 2017-2019 by The qTox Project Contributors |
|
||||||
|
|
||||||
This file is part of qTox, a Qt-based graphical interface for Tox. |
|
||||||
|
|
||||||
qTox is libre software: you can redistribute it and/or modify |
|
||||||
it under the terms of the GNU General Public License as published by |
|
||||||
the Free Software Foundation, either version 3 of the License, or |
|
||||||
(at your option) any later version. |
|
||||||
|
|
||||||
qTox is distributed in the hope that it will be useful, |
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
GNU General Public License for more details. |
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License |
|
||||||
along with qTox. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef TOXME_DATA_H |
|
||||||
#define TOXME_DATA_H |
|
||||||
|
|
||||||
#include <QByteArray> |
|
||||||
|
|
||||||
#include "src/core/toxid.h" |
|
||||||
|
|
||||||
class QString; |
|
||||||
|
|
||||||
class ToxmeData |
|
||||||
{ |
|
||||||
public: |
|
||||||
enum ExecCode |
|
||||||
{ |
|
||||||
ExecError = -50, |
|
||||||
Ok = 0, |
|
||||||
Updated = 1, |
|
||||||
ServerError = 2, |
|
||||||
IncorrectResponse = 3, |
|
||||||
NoPassword = 4 |
|
||||||
}; |
|
||||||
|
|
||||||
QByteArray parsePublicKey(const QString& text) const; |
|
||||||
QString encryptedJson(int action, const QByteArray& pk, const QByteArray& encrypted, |
|
||||||
const QByteArray& nonce) const; |
|
||||||
QString lookupRequest(const QString& address) const; |
|
||||||
ToxId lookup(const QString& text) const; |
|
||||||
|
|
||||||
ExecCode extractCode(const QString& json) const; |
|
||||||
QString createAddressRequest(const ToxId id, const QString& address, const QString& bio, |
|
||||||
bool keepPrivate) const; |
|
||||||
QString getPass(const QString& json, ToxmeData::ExecCode& code); |
|
||||||
QString deleteAddressRequest(const ToxPk& pk); |
|
||||||
}; |
|
||||||
|
|
||||||
#endif // TOXME_DATA_H
|
|
@ -1,289 +0,0 @@ |
|||||||
/*
|
|
||||||
Copyright © 2017-2019 by The qTox Project Contributors |
|
||||||
|
|
||||||
This file is part of qTox, a Qt-based graphical interface for Tox. |
|
||||||
|
|
||||||
qTox is libre software: you can redistribute it and/or modify |
|
||||||
it under the terms of the GNU General Public License as published by |
|
||||||
the Free Software Foundation, either version 3 of the License, or |
|
||||||
(at your option) any later version. |
|
||||||
|
|
||||||
qTox is distributed in the hope that it will be useful, |
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
GNU General Public License for more details. |
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License |
|
||||||
along with qTox. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/ |
|
||||||
|
|
||||||
#include "src/net/toxmedata.h" |
|
||||||
|
|
||||||
#include <ctime> |
|
||||||
|
|
||||||
#include <QtTest/QtTest> |
|
||||||
#include <QString> |
|
||||||
#include <QJsonDocument> |
|
||||||
#include <QJsonObject> |
|
||||||
|
|
||||||
const QByteArray testToxId = |
|
||||||
QByteArrayLiteral("\xC7\x71\x9C\x68\x08\xC1\x4B\x77\x34\x80\x04\x95\x6D\x1D\x98\x04" |
|
||||||
"\x6C\xE0\x9A\x34\x37\x0E\x76\x08\x15\x0E\xAD\x74\xC3\x81\x5D\x30" |
|
||||||
"\xC8\xBA\x3A\xB9\xBE\xB9"); |
|
||||||
const QByteArray testPublicKey = |
|
||||||
QByteArrayLiteral("\xC7\x71\x9C\x68\x08\xC1\x4B\x77\x34\x80\x04\x95\x6D\x1D\x98\x04" |
|
||||||
"\x6C\xE0\x9A\x34\x37\x0E\x76\x08\x15\x0E\xAD\x74\xC3\x81\x5D\x30"); |
|
||||||
|
|
||||||
class TestToxmeData : public QObject |
|
||||||
{ |
|
||||||
Q_OBJECT |
|
||||||
private slots: |
|
||||||
void parsePublicKeyTest(); |
|
||||||
void encryptedJsonTest(); |
|
||||||
void lookupRequestTest(); |
|
||||||
|
|
||||||
void lookup_data(); |
|
||||||
void lookup(); |
|
||||||
|
|
||||||
void extractCode_data(); |
|
||||||
void extractCode(); |
|
||||||
|
|
||||||
void createAddressRequest(); |
|
||||||
|
|
||||||
void getPassTest_data(); |
|
||||||
void getPassTest(); |
|
||||||
|
|
||||||
void deleteAddressRequestTest(); |
|
||||||
}; |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Test if parse public key works correctly. |
|
||||||
*/ |
|
||||||
void TestToxmeData::parsePublicKeyTest() |
|
||||||
{ |
|
||||||
ToxmeData data; |
|
||||||
QString publicKeyStr = testPublicKey.toHex(); |
|
||||||
QString json = QStringLiteral(R"({"key": "%1"})").arg(publicKeyStr); |
|
||||||
QByteArray result = data.parsePublicKey(json); |
|
||||||
QCOMPARE(result, testPublicKey); |
|
||||||
|
|
||||||
json = QStringLiteral("Some wrong string"); |
|
||||||
result = data.parsePublicKey(json); |
|
||||||
QVERIFY(result.isEmpty()); |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Test if generation action json with encrypted payload is correct. |
|
||||||
*/ |
|
||||||
void TestToxmeData::encryptedJsonTest() |
|
||||||
{ |
|
||||||
ToxmeData data; |
|
||||||
int action = 123; |
|
||||||
QByteArray encrypted{QStringLiteral("sometext").toLatin1()}; |
|
||||||
QByteArray nonce{QStringLiteral("nonce").toLatin1()}; |
|
||||||
QString text = data.encryptedJson(action, testPublicKey, encrypted, nonce); |
|
||||||
QJsonObject json = QJsonDocument::fromJson(text.toLatin1()).object(); |
|
||||||
|
|
||||||
int actionRes = json["action"].toInt(); |
|
||||||
QCOMPARE(actionRes, 123); |
|
||||||
|
|
||||||
QByteArray pkRes = QByteArray::fromHex(json["public_key"].toString().toLatin1()); |
|
||||||
QCOMPARE(pkRes, testPublicKey); |
|
||||||
|
|
||||||
QByteArray encRes = QByteArray::fromBase64(json["encrypted"].toString().toLatin1()); |
|
||||||
QCOMPARE(encRes, encrypted); |
|
||||||
|
|
||||||
QByteArray nonceRes = QByteArray::fromBase64(json["nonce"].toString().toLatin1()); |
|
||||||
QCOMPARE(nonceRes, nonce); |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Test if request for lookup generated correctly. |
|
||||||
*/ |
|
||||||
void TestToxmeData::lookupRequestTest() |
|
||||||
{ |
|
||||||
ToxmeData data; |
|
||||||
QString json = QStringLiteral(R"({"action":3,"name":"testname"})"); |
|
||||||
QString result = data.lookupRequest("testname"); |
|
||||||
QCOMPARE(result, json); |
|
||||||
} |
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(ToxId) |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Data function for lookup test. |
|
||||||
*/ |
|
||||||
void TestToxmeData::lookup_data() |
|
||||||
{ |
|
||||||
qRegisterMetaType<ToxId>("ToxId"); |
|
||||||
QTest::addColumn<QString>("input", nullptr); |
|
||||||
QTest::addColumn<ToxId>("result", nullptr); |
|
||||||
QString sToxId = testToxId.toHex(); |
|
||||||
|
|
||||||
QTest::newRow("Valid ToxId") << QStringLiteral(R"({"tox_id": "%1"})").arg(sToxId) |
|
||||||
<< ToxId(testToxId); |
|
||||||
|
|
||||||
QTest::newRow("Invalid ToxId") << QStringLiteral(R"({"tox_id": "SomeTextHere"})") |
|
||||||
<< ToxId{}; |
|
||||||
QTest::newRow("Not json") << QStringLiteral("Not json string") |
|
||||||
<< ToxId{}; |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Test if ToxId parsed from lookup response correcly. |
|
||||||
*/ |
|
||||||
void TestToxmeData::lookup() |
|
||||||
{ |
|
||||||
QFETCH(QString, input); |
|
||||||
QFETCH(ToxId, result); |
|
||||||
ToxmeData data; |
|
||||||
ToxId toxId = data.lookup(input); |
|
||||||
QCOMPARE(result, toxId); |
|
||||||
} |
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(ToxmeData::ExecCode) |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Data function for extractCode test. |
|
||||||
*/ |
|
||||||
void TestToxmeData::extractCode_data() |
|
||||||
{ |
|
||||||
qRegisterMetaType<ToxmeData::ExecCode>("ToxmeData::ExecCode"); |
|
||||||
QTest::addColumn<QString>("input", nullptr); |
|
||||||
QTest::addColumn<ToxmeData::ExecCode>("result", nullptr); |
|
||||||
|
|
||||||
QTest::newRow("Custom code") << QStringLiteral(R"({"c": 123})") |
|
||||||
<< ToxmeData::ExecCode(123); |
|
||||||
QTest::newRow("Ok code") << QStringLiteral(R"({"c": 0})") |
|
||||||
<< ToxmeData::ExecCode::Ok; |
|
||||||
|
|
||||||
QTest::newRow("String code") << QStringLiteral(R"({"c": "string here"})") |
|
||||||
<< ToxmeData::ExecCode::IncorrectResponse; |
|
||||||
QTest::newRow("Invalid code") << QStringLiteral(R"({"c": text})") |
|
||||||
<< ToxmeData::ExecCode::ServerError; |
|
||||||
QTest::newRow("Not json") << QStringLiteral("Not json string") |
|
||||||
<< ToxmeData::ExecCode::ServerError; |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Test if exec code extracts correctly. |
|
||||||
*/ |
|
||||||
void TestToxmeData::extractCode() |
|
||||||
{ |
|
||||||
QFETCH(QString, input); |
|
||||||
QFETCH(ToxmeData::ExecCode, result); |
|
||||||
ToxmeData data; |
|
||||||
ToxmeData::ExecCode code = data.extractCode(input); |
|
||||||
QCOMPARE(result, code); |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Test if request for address creation is correct. |
|
||||||
*/ |
|
||||||
void TestToxmeData::createAddressRequest() |
|
||||||
{ |
|
||||||
ToxmeData data; |
|
||||||
ToxId id{testToxId}; |
|
||||||
QString name{"Test address"}; |
|
||||||
QString bio{"Bio text"}; |
|
||||||
bool keepPrivate = true; |
|
||||||
int timestamp = static_cast<int>(time(nullptr)); |
|
||||||
QString text = data.createAddressRequest(id, name, bio, keepPrivate); |
|
||||||
QJsonObject json = QJsonDocument::fromJson(text.toLatin1()).object(); |
|
||||||
|
|
||||||
QByteArray toxIdData = QByteArray::fromHex(json["tox_id"].toString().toLatin1()); |
|
||||||
ToxId toxIdRes{toxIdData}; |
|
||||||
QCOMPARE(toxIdRes, id); |
|
||||||
|
|
||||||
QString nameRes = json["name"].toString(); |
|
||||||
QCOMPARE(nameRes, name); |
|
||||||
|
|
||||||
bool privRes = json["privacy"].toInt(); |
|
||||||
QCOMPARE(privRes, privRes); |
|
||||||
|
|
||||||
QString bioRes = json["bio"].toString(); |
|
||||||
QCOMPARE(bioRes, bio); |
|
||||||
|
|
||||||
int timeRes = json["timestamp"].toInt(); |
|
||||||
// Test will be failed if `createAddressRequest` will take more
|
|
||||||
// than 100 seconds
|
|
||||||
QVERIFY(qAbs(timeRes - timestamp) < 100); |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Data function for getPassTest. |
|
||||||
*/ |
|
||||||
void TestToxmeData::getPassTest_data() |
|
||||||
{ |
|
||||||
qRegisterMetaType<ToxmeData::ExecCode>("ToxmeData::ExecCode"); |
|
||||||
QTest::addColumn<QString>("input", nullptr); |
|
||||||
QTest::addColumn<QString>("result", nullptr); |
|
||||||
QTest::addColumn<ToxmeData::ExecCode>("code", nullptr); |
|
||||||
|
|
||||||
QTest::newRow("Valid password") << QStringLiteral(R"({"password": "123qwe"})") |
|
||||||
<< QStringLiteral("123qwe") |
|
||||||
<< ToxmeData::ExecCode::Ok; |
|
||||||
|
|
||||||
QTest::newRow("Null password") << QStringLiteral(R"({"password": null})") |
|
||||||
<< QStringLiteral("") |
|
||||||
<< ToxmeData::ExecCode::Updated; |
|
||||||
|
|
||||||
QTest::newRow("Valid password with null") << QStringLiteral(R"({"password": "null"})") |
|
||||||
<< QStringLiteral("null") |
|
||||||
<< ToxmeData::ExecCode::Ok; |
|
||||||
|
|
||||||
// ERROR: password value with invalid text, but started with 'null' interpreted as Update
|
|
||||||
#if 0 |
|
||||||
QTest::newRow("Invalid null password") << QStringLiteral(R"({"password": nulla})") |
|
||||||
<< QStringLiteral("") |
|
||||||
<< ToxmeData::ExecCode::IncorrectResponse; |
|
||||||
#endif |
|
||||||
|
|
||||||
QTest::newRow("Invalid int password") << QStringLiteral(R"({"password": 123})") |
|
||||||
<< QStringLiteral("") |
|
||||||
<< ToxmeData::ExecCode::IncorrectResponse; |
|
||||||
|
|
||||||
QTest::newRow("Not json") << QStringLiteral("Not json") |
|
||||||
<< QStringLiteral("") |
|
||||||
<< ToxmeData::ExecCode::NoPassword; |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Test if password extraction is correct. |
|
||||||
*/ |
|
||||||
void TestToxmeData::getPassTest() |
|
||||||
{ |
|
||||||
QFETCH(QString, input); |
|
||||||
QFETCH(QString, result); |
|
||||||
QFETCH(ToxmeData::ExecCode, code); |
|
||||||
|
|
||||||
ToxmeData data; |
|
||||||
ToxmeData::ExecCode resCode = ToxmeData::ExecCode::Ok; |
|
||||||
QString password = data.getPass(input, resCode); |
|
||||||
QCOMPARE(password, result); |
|
||||||
QCOMPARE(resCode, code); |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Test if request for address deletation generated correct. |
|
||||||
*/ |
|
||||||
void TestToxmeData::deleteAddressRequestTest() |
|
||||||
{ |
|
||||||
ToxmeData data; |
|
||||||
ToxPk pk{testPublicKey}; |
|
||||||
int timestamp = static_cast<int>(time(nullptr)); |
|
||||||
QString text = data.deleteAddressRequest(pk); |
|
||||||
QJsonObject json = QJsonDocument::fromJson(text.toLatin1()).object(); |
|
||||||
|
|
||||||
QByteArray pkRes = QByteArray::fromHex(json["public_key"].toString().toLatin1()); |
|
||||||
QCOMPARE(pkRes, testPublicKey); |
|
||||||
|
|
||||||
int timeRes = json["timestamp"].toInt(); |
|
||||||
// Test will be failed if `deleteAddressRequest` will take more
|
|
||||||
// than 100 seconds
|
|
||||||
QVERIFY(qAbs(timeRes - timestamp) < 100); |
|
||||||
} |
|
||||||
|
|
||||||
QTEST_GUILESS_MAIN(TestToxmeData) |
|
||||||
#include "toxmedata_test.moc" |
|
Loading…
Reference in new issue