From 05d6174351e1ea82a1c58f6f97c428f32efa6baf Mon Sep 17 00:00:00 2001 From: dongresource Date: Fri, 3 Dec 2021 22:23:59 +0100 Subject: [PATCH] Handle email dumping separately from chat dumping This makes it actually possible to unambiguously parse the full thing on the receiving end. --- src/Email.cpp | 4 +++- src/Email.hpp | 7 +++++- src/servers/Monitor.cpp | 48 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/src/Email.cpp b/src/Email.cpp index 955b3a2..4de3766 100644 --- a/src/Email.cpp +++ b/src/Email.cpp @@ -10,6 +10,8 @@ using namespace Email; +std::vector Email::dump; + // New email notification static void emailUpdateCheck(CNSocket* sock, CNPacketData* data) { INITSTRUCT(sP_FE2CL_REP_PC_NEW_EMAIL, resp); @@ -307,7 +309,7 @@ static void emailSend(CNSocket* sock, CNPacketData* data) { std::string logEmail = "[Email] " + PlayerManager::getPlayerName(plr, true) + " (to " + PlayerManager::getPlayerName(&otherPlr, true) + "): <" + email.SubjectLine + ">\n" + email.MsgBody; std::cout << logEmail << std::endl; - Chat::dump.push_back(logEmail); + dump.push_back(logEmail); } void Email::init() { diff --git a/src/Email.hpp b/src/Email.hpp index 7365b12..3e5c557 100644 --- a/src/Email.hpp +++ b/src/Email.hpp @@ -1,5 +1,10 @@ #pragma once +#include +#include + namespace Email { - void init(); + extern std::vector dump; + + void init(); } diff --git a/src/servers/Monitor.cpp b/src/servers/Monitor.cpp index 60d701b..4b7819f 100644 --- a/src/servers/Monitor.cpp +++ b/src/servers/Monitor.cpp @@ -1,6 +1,7 @@ #include "servers/CNShardServer.hpp" #include "PlayerManager.hpp" #include "Chat.hpp" +#include "Email.hpp" #include "servers/Monitor.hpp" #include "settings.hpp" @@ -38,9 +39,42 @@ static bool transmit(std::list::iterator& it, char *buff, int len) { return true; } +/* + * The longest protocol message is for an email. + * + * message type + two formatted character names + the other formatting chars + * + the email title + the email body = ~1154 + * + * The body can grow to twice its usual size (512) in the pathological case + * where every character is a newline. + * + * Multi-byte Unicode characters aren't a factor, as they should've been + * stripped out by sanitizeText(). + */ +#define BUFSIZE 2048 + +static int process_email(char *buff, std::string email) { + strncpy(buff, "email ", 6); + int i = 6; + + for (char c : email) { + if (i == BUFSIZE-2) + break; + + buff[i++] = c; + + // indent each line to prevent "endemail" spoofing + if (c == '\n') + buff[i++] = '\t'; + } + + buff[i++] = '\n'; + return i; +} + static void tick(CNServer *serv, time_t delta) { std::lock_guard lock(sockLock); - char buff[256]; + char buff[BUFSIZE]; int n; auto it = sockets.begin(); @@ -70,6 +104,17 @@ outer: goto outer; } + // emails + for (auto& str : Email::dump) { + n = process_email(buff, str); + + if (!transmit(it, buff, n)) + goto outer; + + if (!transmit(it, (char*)"endemail\n", 9)) + goto outer; + } + if (!transmit(it, (char*)"end\n", 4)) continue; @@ -77,6 +122,7 @@ outer: } Chat::dump.clear(); + Email::dump.clear(); } bool Monitor::acceptConnection(SOCKET fd, uint16_t revents) {