mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
refactor(toxme): Move json generation to ToxmeData class
This commit is contained in:
parent
e98297134a
commit
9a543548e0
|
@ -273,6 +273,8 @@ set(${PROJECT_NAME}_SOURCES
|
|||
src/net/avatarbroadcaster.h
|
||||
src/net/toxme.cpp
|
||||
src/net/toxme.h
|
||||
src/net/toxmedata.cpp
|
||||
src/net/toxmedata.h
|
||||
src/net/toxuri.cpp
|
||||
src/net/toxuri.h
|
||||
src/nexus.cpp
|
||||
|
|
|
@ -19,16 +19,22 @@
|
|||
|
||||
#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>
|
||||
#include <ctime>
|
||||
#include <sodium/crypto_box.h>
|
||||
#include <sodium/randombytes.h>
|
||||
#include <src/persistence/settings.h>
|
||||
#include <string>
|
||||
|
||||
static ToxmeData toxmeData;
|
||||
|
||||
/**
|
||||
* @class Toxme
|
||||
|
@ -82,25 +88,9 @@ QByteArray Toxme::getServerPubkey(QString url, QNetworkReply::NetworkError& erro
|
|||
return QByteArray();
|
||||
}
|
||||
|
||||
// Extract key
|
||||
static const QByteArray pattern{"key\":\""};
|
||||
|
||||
QString json = reply->readAll();
|
||||
delete reply;
|
||||
json = json.remove(' ');
|
||||
int start = json.indexOf(pattern) + pattern.length();
|
||||
int end = json.indexOf("\"", start);
|
||||
int pubkeySize = (end - start) / 2;
|
||||
QString rawKey = json.mid(start, pubkeySize * 2);
|
||||
|
||||
QByteArray key;
|
||||
// I think, exist more easy way to convert key to ByteArray
|
||||
for (int i = 0; i < pubkeySize; ++i) {
|
||||
QString byte = rawKey.mid(i * 2, 2);
|
||||
key[i] = byte.toInt(nullptr, 16);
|
||||
}
|
||||
|
||||
return key;
|
||||
return toxmeData.parsePublicKey(json);
|
||||
}
|
||||
|
||||
QByteArray Toxme::prepareEncryptedJson(QString url, int action, QString payload)
|
||||
|
@ -133,14 +123,7 @@ QByteArray Toxme::prepareEncryptedJson(QString url, int action, QString payload)
|
|||
QByteArray payloadEncData(reinterpret_cast<char*>(payloadEnc), cypherlen);
|
||||
delete[] payloadEnc;
|
||||
|
||||
const QString json{"{\"action\":" + QString().setNum(action) + ","
|
||||
"\"public_key\":\""
|
||||
+ keypair.first.toHex() + "\","
|
||||
"\"encrypted\":\""
|
||||
+ payloadEncData.toBase64() + "\","
|
||||
"\"nonce\":\""
|
||||
+ nonce.toBase64() + "\"}"};
|
||||
return json.toUtf8();
|
||||
return toxmeData.encryptedJson(action, keypair.first, payloadEncData, nonce).toUtf8();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -155,64 +138,16 @@ ToxId Toxme::lookup(QString address)
|
|||
address.replace('\\', "\\\\");
|
||||
address.replace('"', "\"");
|
||||
|
||||
const QString json{"{\"action\":3,\"name\":\"" + address + "\"}"};
|
||||
const QString json = toxmeData.lookupRequest(address);
|
||||
|
||||
QString apiUrl = "https://" + address.split(QLatin1Char('@')).last() + "/api";
|
||||
QNetworkReply::NetworkError error = QNetworkReply::NoError;
|
||||
QByteArray response = makeJsonRequest(apiUrl, json, error);
|
||||
QString response = makeJsonRequest(apiUrl, json, error);
|
||||
|
||||
if (error != QNetworkReply::NoError)
|
||||
return ToxId();
|
||||
|
||||
static const QByteArray pattern{"tox_id\""};
|
||||
const int index = response.indexOf(pattern);
|
||||
if (index == -1)
|
||||
return ToxId();
|
||||
|
||||
response = response.mid(index + pattern.size());
|
||||
|
||||
const int idStart = response.indexOf('"');
|
||||
if (idStart == -1)
|
||||
return ToxId();
|
||||
|
||||
response = response.mid(idStart + 1);
|
||||
|
||||
const int idEnd = response.indexOf('"');
|
||||
if (idEnd == -1)
|
||||
return ToxId();
|
||||
|
||||
response.truncate(idEnd);
|
||||
|
||||
return ToxId(QString(response));
|
||||
}
|
||||
|
||||
Toxme::ExecCode Toxme::extractError(QString json)
|
||||
{
|
||||
static const QByteArray pattern{"c\":"};
|
||||
|
||||
if (json.isEmpty())
|
||||
return ServerError;
|
||||
|
||||
json = json.remove(' ');
|
||||
const int start = json.indexOf(pattern);
|
||||
if (start == -1)
|
||||
return ServerError;
|
||||
|
||||
json = json.mid(start + pattern.size());
|
||||
int end = json.indexOf(",");
|
||||
if (end == -1) {
|
||||
end = json.indexOf("}");
|
||||
if (end == -1)
|
||||
return IncorrectResponse;
|
||||
}
|
||||
|
||||
json.truncate(end);
|
||||
bool ok;
|
||||
int r = json.toInt(&ok);
|
||||
if (!ok)
|
||||
return IncorrectResponse;
|
||||
|
||||
return ExecCode(r);
|
||||
return toxmeData.lookup(response);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -225,10 +160,9 @@ Toxme::ExecCode Toxme::extractError(QString json)
|
|||
* @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(ExecCode& code, QString server, ToxId id, QString address,
|
||||
QString Toxme::createAddress(ToxmeData::ExecCode& code, QString server, ToxId id, QString address,
|
||||
bool keepPrivate, QString bio)
|
||||
{
|
||||
int privacy = keepPrivate ? 0 : 2;
|
||||
// JSON injection ?
|
||||
bio.replace('\\', "\\\\");
|
||||
bio.replace('"', "\"");
|
||||
|
@ -242,56 +176,18 @@ QString Toxme::createAddress(ExecCode& code, QString server, ToxId id, QString a
|
|||
if (!server.contains("://"))
|
||||
server = "https://" + server;
|
||||
|
||||
const QString payload{"{\"tox_id\":\"" + id.toString() + "\","
|
||||
"\"name\":\""
|
||||
+ address + "\","
|
||||
"\"privacy\":"
|
||||
+ QString().setNum(privacy) + ","
|
||||
"\"bio\":\""
|
||||
+ bio + "\","
|
||||
"\"timestamp\":"
|
||||
+ QString().setNum(time(0)) + "}"};
|
||||
|
||||
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 = extractError(response);
|
||||
if ((code != Ok && code != Updated) || error != QNetworkReply::NoError)
|
||||
code = toxmeData.extractCode(response);
|
||||
if ((code != ToxmeData::Ok && code != ToxmeData::Updated) || error != QNetworkReply::NoError)
|
||||
return QString();
|
||||
|
||||
return getPass(response, code);
|
||||
}
|
||||
|
||||
QString Toxme::getPass(QString json, ExecCode& code)
|
||||
{
|
||||
static const QByteArray pattern{"password\":"};
|
||||
|
||||
json = json.remove(' ');
|
||||
const int start = json.indexOf(pattern);
|
||||
if (start == -1) {
|
||||
code = NoPassword;
|
||||
return QString();
|
||||
}
|
||||
|
||||
json = json.mid(start + pattern.size());
|
||||
if (json.startsWith("null")) {
|
||||
code = Updated;
|
||||
return QString();
|
||||
}
|
||||
|
||||
json = json.mid(1, json.length());
|
||||
int end = json.indexOf("\"");
|
||||
if (end == -1) {
|
||||
code = IncorrectResponse;
|
||||
return QString();
|
||||
}
|
||||
|
||||
json.truncate(end);
|
||||
|
||||
return json;
|
||||
return toxmeData.getPass(response, code);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -300,11 +196,9 @@ QString Toxme::getPass(QString json, ExecCode& code)
|
|||
* @param id ToxId to delete.
|
||||
* @return Status code returned from server.
|
||||
*/
|
||||
Toxme::ExecCode Toxme::deleteAddress(QString server, ToxPk id)
|
||||
ToxmeData::ExecCode Toxme::deleteAddress(QString server, ToxPk pk)
|
||||
{
|
||||
const QString payload{"{\"public_key\":\"" + id.toString() + "\","
|
||||
"\"timestamp\":"
|
||||
+ QString().setNum(time(0)) + "}"};
|
||||
const QString payload = toxmeData.deleteAddressRequest(pk);
|
||||
|
||||
server = server.trimmed();
|
||||
if (!server.contains("://"))
|
||||
|
@ -315,7 +209,7 @@ Toxme::ExecCode Toxme::deleteAddress(QString server, ToxPk id)
|
|||
QNetworkReply::NetworkError error = QNetworkReply::NoError;
|
||||
QByteArray response = makeJsonRequest(apiUrl, prepareEncryptedJson(pubkeyUrl, 2, payload), error);
|
||||
|
||||
return extractError(response);
|
||||
return toxmeData.extractCode(response);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -326,11 +220,11 @@ Toxme::ExecCode Toxme::deleteAddress(QString server, ToxPk id)
|
|||
QString Toxme::getErrorMessage(int errorCode)
|
||||
{
|
||||
switch (errorCode) {
|
||||
case IncorrectResponse:
|
||||
case ToxmeData::IncorrectResponse:
|
||||
return "Incorrect response";
|
||||
case NoPassword:
|
||||
case ToxmeData::NoPassword:
|
||||
return "No password in response";
|
||||
case ServerError:
|
||||
case ToxmeData::ServerError:
|
||||
return "Server doesn't support Toxme";
|
||||
case -1:
|
||||
return "You must send POST requests to /api";
|
||||
|
@ -373,7 +267,7 @@ QString Toxme::getErrorMessage(int errorCode)
|
|||
QString Toxme::translateErrorMessage(int errorCode)
|
||||
{
|
||||
switch (errorCode) {
|
||||
case ServerError:
|
||||
case ToxmeData::ServerError:
|
||||
return QObject::tr("Server doesn't support Toxme");
|
||||
case -2:
|
||||
return QObject::tr("Problem with HTTPS connection");
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#define TOXME_H
|
||||
|
||||
#include "src/core/toxid.h"
|
||||
#include "src/net/toxmedata.h"
|
||||
#include <QMap>
|
||||
#include <QMutex>
|
||||
#include <QNetworkReply>
|
||||
|
@ -33,20 +34,10 @@ class QNetworkAccessManager;
|
|||
class Toxme
|
||||
{
|
||||
public:
|
||||
enum ExecCode
|
||||
{
|
||||
ExecError = -50,
|
||||
Ok = 0,
|
||||
Updated = 1,
|
||||
ServerError = 2,
|
||||
IncorrectResponse = 3,
|
||||
NoPassword = 4
|
||||
};
|
||||
|
||||
static ToxId lookup(QString address);
|
||||
static QString createAddress(ExecCode& code, QString server, ToxId id, QString address,
|
||||
bool keepPrivate = true, QString bio = QString());
|
||||
static ExecCode deleteAddress(QString server, ToxPk id);
|
||||
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);
|
||||
|
||||
|
@ -55,8 +46,7 @@ private:
|
|||
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 QString getPass(QString json, ExecCode& code);
|
||||
static ExecCode extractError(QString json);
|
||||
static ToxmeData::ExecCode extractError(QString json);
|
||||
|
||||
private:
|
||||
static const QMap<QString, QString> pubkeyUrls;
|
||||
|
|
164
src/net/toxmedata.cpp
Normal file
164
src/net/toxmedata.cpp
Normal file
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
Copyright © 2017 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 <QString>
|
||||
|
||||
QByteArray ToxmeData::parsePublicKey(const QString& text) const
|
||||
{
|
||||
static const QByteArray pattern{"key\":\""};
|
||||
|
||||
QString json = text;
|
||||
json.remove(' ');
|
||||
int start = json.indexOf(pattern) + pattern.length();
|
||||
int end = json.indexOf("\"", start);
|
||||
int pubkeySize = (end - start) / 2;
|
||||
QString rawKey = json.mid(start, pubkeySize * 2);
|
||||
|
||||
QByteArray key;
|
||||
// I think, exist more easy way to convert key to ByteArray
|
||||
for (int i = 0; i < pubkeySize; ++i) {
|
||||
QString byte = rawKey.mid(i * 2, 2);
|
||||
key[i] = byte.toInt(nullptr, 16);
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
QString ToxmeData::encryptedJson(int action, const QByteArray& pk, const QByteArray& encrypted,
|
||||
const QByteArray& nonce) const
|
||||
{
|
||||
return "{\"action\":" + QString().setNum(action) +
|
||||
",\"public_key\":\"" + pk.toHex() +
|
||||
"\",\"encrypted\":\"" + encrypted.toBase64() +
|
||||
"\",\"nonce\":\"" + nonce.toBase64() + "\"}";
|
||||
}
|
||||
|
||||
QString ToxmeData::lookupRequest(const QString& address) const
|
||||
{
|
||||
return "{\"action\":3,\"name\":\"" + address + "\"}";
|
||||
}
|
||||
|
||||
ToxId ToxmeData::lookup(const QString& inText) const
|
||||
{
|
||||
QString text = inText;
|
||||
static const QByteArray pattern{"tox_id\""};
|
||||
const int index = text.indexOf(pattern);
|
||||
if (index == -1)
|
||||
return ToxId();
|
||||
|
||||
text = text.mid(index + pattern.size());
|
||||
|
||||
const int idStart = text.indexOf('"');
|
||||
if (idStart == -1)
|
||||
return ToxId();
|
||||
|
||||
text = text.mid(idStart + 1);
|
||||
|
||||
const int idEnd = text.indexOf('"');
|
||||
if (idEnd == -1)
|
||||
return ToxId();
|
||||
|
||||
text.truncate(idEnd);
|
||||
|
||||
return ToxId(text);
|
||||
}
|
||||
|
||||
ToxmeData::ExecCode ToxmeData::extractCode(const QString& srcJson) const
|
||||
{
|
||||
QString json = srcJson;
|
||||
static const QByteArray pattern{"c\":"};
|
||||
|
||||
if (json.isEmpty())
|
||||
return ServerError;
|
||||
|
||||
json = json.remove(' ');
|
||||
const int start = json.indexOf(pattern);
|
||||
if (start == -1)
|
||||
return ServerError;
|
||||
|
||||
json = json.mid(start + pattern.size());
|
||||
int end = json.indexOf(",");
|
||||
if (end == -1) {
|
||||
end = json.indexOf("}");
|
||||
if (end == -1)
|
||||
return IncorrectResponse;
|
||||
}
|
||||
|
||||
json.truncate(end);
|
||||
bool ok;
|
||||
int r = json.toInt(&ok);
|
||||
if (!ok)
|
||||
return IncorrectResponse;
|
||||
|
||||
return ExecCode(r);
|
||||
}
|
||||
|
||||
QString ToxmeData::createAddressRequest(const ToxId id, const QString& address, const QString& bio,
|
||||
bool keepPrivate) const
|
||||
{
|
||||
int privacy = keepPrivate ? 0 : 2;
|
||||
return "{\"tox_id\":\"" + id.toString() +
|
||||
"\",\"name\":\"" + address +
|
||||
"\",\"privacy\":" + QString().setNum(privacy) +
|
||||
",\"bio\":\"" + bio +
|
||||
"\",\"timestamp\":" + QString().setNum(time(nullptr)) +
|
||||
"}";
|
||||
|
||||
}
|
||||
|
||||
QString ToxmeData::getPass(const QString& srcJson, ToxmeData::ExecCode& code)
|
||||
{
|
||||
QString json = srcJson;
|
||||
static const QByteArray pattern{"password\":"};
|
||||
|
||||
json = json.remove(' ');
|
||||
const int start = json.indexOf(pattern);
|
||||
if (start == -1) {
|
||||
code = ToxmeData::NoPassword;
|
||||
return QString();
|
||||
}
|
||||
|
||||
json = json.mid(start + pattern.size());
|
||||
if (json.startsWith("null")) {
|
||||
code = ToxmeData::Updated;
|
||||
return QString();
|
||||
}
|
||||
|
||||
json = json.mid(1, json.length());
|
||||
int end = json.indexOf("\"");
|
||||
if (end == -1) {
|
||||
code = ToxmeData::IncorrectResponse;
|
||||
return QString();
|
||||
}
|
||||
|
||||
json.truncate(end);
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
QString ToxmeData::deleteAddressRequest(const ToxPk& pk)
|
||||
{
|
||||
return "{\"public_key\":\"" + pk.toString() +
|
||||
"\",\"timestamp\":" + QString().setNum(time(nullptr)) +
|
||||
"}";
|
||||
|
||||
}
|
55
src/net/toxmedata.h
Normal file
55
src/net/toxmedata.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
Copyright © 2017 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
|
|
@ -519,7 +519,7 @@ void ProfileForm::onRegisterButtonClicked()
|
|||
|
||||
Core* oldCore = Core::getInstance();
|
||||
|
||||
Toxme::ExecCode code = Toxme::ExecCode::Ok;
|
||||
ToxmeData::ExecCode code = ToxmeData::ExecCode::Ok;
|
||||
QString response = Toxme::createAddress(code, server, ToxId(id), name, privacy, bio);
|
||||
|
||||
Core* newCore = Core::getInstance();
|
||||
|
@ -527,12 +527,12 @@ void ProfileForm::onRegisterButtonClicked()
|
|||
// before the request is finished, else qTox will crash.
|
||||
if (oldCore == newCore) {
|
||||
switch (code) {
|
||||
case Toxme::Updated:
|
||||
case ToxmeData::Updated:
|
||||
GUI::showInfo(tr("Done!"), tr("Account %1@%2 updated successfully").arg(name, server));
|
||||
Settings::getInstance().setToxme(name, server, bio, privacy);
|
||||
showExistingToxme();
|
||||
break;
|
||||
case Toxme::Ok:
|
||||
case ToxmeData::Ok:
|
||||
GUI::showInfo(tr("Done!"),
|
||||
tr("Successfully added %1@%2 to the database. Save your password")
|
||||
.arg(name, server));
|
||||
|
|
Loading…
Reference in New Issue
Block a user