Add better escaping

This commit is contained in:
hiimgoodpack 2021-04-07 20:18:21 -04:00
parent 2a4c54ad53
commit 1c52e0f370
Signed by: hiimgoodpack
GPG key ID: 4E0E62733C14AE69

View file

@ -73,7 +73,8 @@ namespace Brainlet {
State state = NOT_CONNECTED; State state = NOT_CONNECTED;
static void onReceive(Client* client, std::string buffer); static void onReceive(Client* client, std::string buffer);
void encode(std::string& string); ///< Encodes a string to a JSON value void escapeJSON(std::string& string); ///< Escapes a string to a JSON value
void escapeOutput(std::string& string); ///< Escapes a string to output safely
public: public:
std::function<void(Channel)> onNewChannel = nullptr; std::function<void(Channel)> onNewChannel = nullptr;
@ -112,7 +113,7 @@ namespace Brainlet {
namespace Brainlet { namespace Brainlet {
Client::Client(const std::string& domain) : domain(domain) {} Client::Client(const std::string& domain) : domain(domain) {}
void Client::encode(std::string& string) { void Client::escapeJSON(std::string& string) {
std::string result; std::string result;
result.reserve(string.size()); result.reserve(string.size());
@ -131,6 +132,20 @@ namespace Brainlet {
string = std::move(result); string = std::move(result);
} }
void Client::escapeOutput(std::string& string) {
std::string result;
result.reserve(string.size());
std::for_each(string.begin(), string.end(), [&](const char character) {
switch (character) {
case '\b':
case '\x1f': result.push_back('?'); break;
default: result.push_back(character); break;
}
});
string = std::move(result);
}
void Client::processNextEvent() { void Client::processNextEvent() {
socket->run_until( socket->run_until(
// Stop in 250 microseconds // Stop in 250 microseconds
@ -172,7 +187,9 @@ namespace Brainlet {
bool didError = value.get("error", true).asBool(); bool didError = value.get("error", true).asBool();
if (didError) { if (didError) {
// TODO: Use exception // TODO: Use exception
std::cerr << "Error while logging in: " << value.get("message", "Server did not specify error").asString() << "\n"; std::string error = value.get("message", "Server did not specify error").asString();
escapeOutput(error);
std::cerr << "Error while logging in: " << error << "\n";
return; return;
} }
@ -210,6 +227,7 @@ namespace Brainlet {
case NOT_CONNECTED: throw std::logic_error("Buffer was received while client is not connected"); case NOT_CONNECTED: throw std::logic_error("Buffer was received while client is not connected");
case WAIT_HELLO: { case WAIT_HELLO: {
if (opcode != HELLO) { if (opcode != HELLO) {
escapeOutput(buffer);
std::cerr << "Failed authentication: Expected HELLO packet, received: " << buffer << "\n"; std::cerr << "Failed authentication: Expected HELLO packet, received: " << buffer << "\n";
client->socket->close(); client->socket->close();
return; return;
@ -225,6 +243,7 @@ namespace Brainlet {
} }
case WAIT_ACK: { case WAIT_ACK: {
if (opcode != YOO_ACK) { if (opcode != YOO_ACK) {
escapeOutput(buffer);
std::cerr << "Failed authentication: Expected YOO_ACK packet, received: " << buffer << "\n"; std::cerr << "Failed authentication: Expected YOO_ACK packet, received: " << buffer << "\n";
client->socket->close(); client->socket->close();
return; return;
@ -243,6 +262,7 @@ namespace Brainlet {
if (client->onNewChannel) if (client->onNewChannel)
client->onNewChannel(channelObject); client->onNewChannel(channelObject);
} }
break;
} }
case READY: { case READY: {
switch (opcode) { switch (opcode) {
@ -260,15 +280,17 @@ namespace Brainlet {
break; break;
} }
default: { default: {
escapeOutput(buffer);
std::cerr << "Unknown opcode " << opcode << ". Buffer " << buffer << "\n"; std::cerr << "Unknown opcode " << opcode << ". Buffer " << buffer << "\n";
break; break;
} }
} }
break;
} }
} }
} }
void Client::sendMessage(std::string message, std::string channelId) { void Client::sendMessage(std::string message, std::string channelId) {
encode(message); escapeJSON(message);
std::ostringstream bufferToSend; std::ostringstream bufferToSend;
bufferToSend << ACTION_CREATE_MESSAGE << "@" << R"({"content":")" << message << R"(","channel":{"_id":")" << channelId << R"("}})"; bufferToSend << ACTION_CREATE_MESSAGE << "@" << R"({"content":")" << message << R"(","channel":{"_id":")" << channelId << R"("}})";