catch text encode/decode errors in more places
This commit is contained in:
@@ -4,7 +4,6 @@
|
|||||||
- Implement decrypt/encrypt actions for VMS files
|
- Implement decrypt/encrypt actions for VMS files
|
||||||
- Make UI strings localizable (e.g. entries in menus, welcome message, etc.)
|
- Make UI strings localizable (e.g. entries in menus, welcome message, etc.)
|
||||||
- Add an idle connection timeout for proxy sessions
|
- Add an idle connection timeout for proxy sessions
|
||||||
- Look into JP heart symbol bug on Linux
|
|
||||||
- Check server's rare enemy logic against GC's logic
|
- Check server's rare enemy logic against GC's logic
|
||||||
|
|
||||||
## Episode 3
|
## Episode 3
|
||||||
|
|||||||
+15
-10
@@ -1145,7 +1145,7 @@ static HandlerResult C_B_D9(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t
|
|||||||
add_color_inplace(decoded);
|
add_color_inplace(decoded);
|
||||||
data = tt_utf8_to_utf16(data.data(), data.size());
|
data = tt_utf8_to_utf16(data.data(), data.size());
|
||||||
} catch (const runtime_error& e) {
|
} catch (const runtime_error& e) {
|
||||||
ses->log.warning("Failed to replace escape characters in D9 command: %s", e.what());
|
ses->log.warning("Failed to decode and unescape D9 command: %s", e.what());
|
||||||
}
|
}
|
||||||
// TODO: We should check if the info board text was actually modified and
|
// TODO: We should check if the info board text was actually modified and
|
||||||
// return HandlerResult::FORWARD if not.
|
// return HandlerResult::FORWARD if not.
|
||||||
@@ -1610,16 +1610,21 @@ static HandlerResult C_06(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t,
|
|||||||
strip_trailing_zeroes(text);
|
strip_trailing_zeroes(text);
|
||||||
|
|
||||||
uint8_t private_flags = 0;
|
uint8_t private_flags = 0;
|
||||||
if (uses_utf16(ses->version())) {
|
try {
|
||||||
if (text.size() & 1) {
|
if (uses_utf16(ses->version())) {
|
||||||
text.push_back(0);
|
if (text.size() & 1) {
|
||||||
|
text.push_back(0);
|
||||||
|
}
|
||||||
|
text = tt_decode_marked(text, ses->language(), true);
|
||||||
|
} else if (!text.empty() && (text[0] != '\t') && is_ep3(ses->version())) {
|
||||||
|
private_flags = text[0];
|
||||||
|
text = tt_decode_marked(text.substr(1), ses->language(), false);
|
||||||
|
} else {
|
||||||
|
text = tt_decode_marked(text, ses->language(), false);
|
||||||
}
|
}
|
||||||
text = tt_decode_marked(text, ses->language(), true);
|
} catch (const runtime_error& e) {
|
||||||
} else if (!text.empty() && (text[0] != '\t') && is_ep3(ses->version())) {
|
ses->log.warning("Failed to decode and unescape chat text: %s", e.what());
|
||||||
private_flags = text[0];
|
return HandlerResult::Type::FORWARD;
|
||||||
text = tt_decode_marked(text.substr(1), ses->language(), false);
|
|
||||||
} else {
|
|
||||||
text = tt_decode_marked(text, ses->language(), false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (text.empty()) {
|
if (text.empty()) {
|
||||||
|
|||||||
+65
-23
@@ -2978,7 +2978,11 @@ static void on_61_98(shared_ptr<Client> c, uint16_t command, uint32_t flag, stri
|
|||||||
if (auto_reply.size() & 1) {
|
if (auto_reply.size() & 1) {
|
||||||
auto_reply.push_back(0);
|
auto_reply.push_back(0);
|
||||||
}
|
}
|
||||||
player->auto_reply.encode(tt_utf16_to_utf8(auto_reply), player->inventory.language);
|
try {
|
||||||
|
player->auto_reply.encode(tt_utf16_to_utf8(auto_reply), player->inventory.language);
|
||||||
|
} catch (const runtime_error& e) {
|
||||||
|
c->log.warning("Failed to decode auto-reply message: %s", e.what());
|
||||||
|
}
|
||||||
c->license->auto_reply_message = auto_reply;
|
c->license->auto_reply_message = auto_reply;
|
||||||
} else {
|
} else {
|
||||||
player->auto_reply.clear();
|
player->auto_reply.clear();
|
||||||
@@ -3001,8 +3005,12 @@ static void on_61_98(shared_ptr<Client> c, uint16_t command, uint32_t flag, stri
|
|||||||
if (cmd.auto_reply_enabled) {
|
if (cmd.auto_reply_enabled) {
|
||||||
string auto_reply = data.substr(sizeof(cmd), 0xAC);
|
string auto_reply = data.substr(sizeof(cmd), 0xAC);
|
||||||
strip_trailing_zeroes(auto_reply);
|
strip_trailing_zeroes(auto_reply);
|
||||||
string encoded = tt_decode_marked(auto_reply, player->inventory.language, false);
|
try {
|
||||||
player->auto_reply.encode(encoded, player->inventory.language);
|
string encoded = tt_decode_marked(auto_reply, player->inventory.language, false);
|
||||||
|
player->auto_reply.encode(encoded, player->inventory.language);
|
||||||
|
} catch (const runtime_error& e) {
|
||||||
|
c->log.warning("Failed to decode auto-reply message: %s", e.what());
|
||||||
|
}
|
||||||
c->license->auto_reply_message = auto_reply;
|
c->license->auto_reply_message = auto_reply;
|
||||||
} else {
|
} else {
|
||||||
player->auto_reply.clear();
|
player->auto_reply.clear();
|
||||||
@@ -3073,8 +3081,12 @@ static void on_61_98(shared_ptr<Client> c, uint16_t command, uint32_t flag, stri
|
|||||||
if (cmd->auto_reply_enabled) {
|
if (cmd->auto_reply_enabled) {
|
||||||
string auto_reply = data.substr(sizeof(cmd), 0xAC);
|
string auto_reply = data.substr(sizeof(cmd), 0xAC);
|
||||||
strip_trailing_zeroes(auto_reply);
|
strip_trailing_zeroes(auto_reply);
|
||||||
string encoded = tt_decode_marked(auto_reply, player->inventory.language, false);
|
try {
|
||||||
player->auto_reply.encode(encoded, player->inventory.language);
|
string encoded = tt_decode_marked(auto_reply, player->inventory.language, false);
|
||||||
|
player->auto_reply.encode(encoded, player->inventory.language);
|
||||||
|
} catch (const runtime_error& e) {
|
||||||
|
c->log.warning("Failed to decode auto-reply message: %s", e.what());
|
||||||
|
}
|
||||||
c->license->auto_reply_message = auto_reply;
|
c->license->auto_reply_message = auto_reply;
|
||||||
} else {
|
} else {
|
||||||
player->auto_reply.clear();
|
player->auto_reply.clear();
|
||||||
@@ -3098,7 +3110,11 @@ static void on_61_98(shared_ptr<Client> c, uint16_t command, uint32_t flag, stri
|
|||||||
if (auto_reply.size() & 1) {
|
if (auto_reply.size() & 1) {
|
||||||
auto_reply.push_back(0);
|
auto_reply.push_back(0);
|
||||||
}
|
}
|
||||||
player->auto_reply.encode(tt_utf16_to_utf8(auto_reply), player->inventory.language);
|
try {
|
||||||
|
player->auto_reply.encode(tt_utf16_to_utf8(auto_reply), player->inventory.language);
|
||||||
|
} catch (const runtime_error& e) {
|
||||||
|
c->log.warning("Failed to decode auto-reply message: %s", e.what());
|
||||||
|
}
|
||||||
c->license->auto_reply_message = auto_reply;
|
c->license->auto_reply_message = auto_reply;
|
||||||
} else {
|
} else {
|
||||||
player->auto_reply.clear();
|
player->auto_reply.clear();
|
||||||
@@ -3223,7 +3239,13 @@ static void on_06(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
|||||||
text = text.substr(1);
|
text = text.substr(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
text = tt_decode_marked(text, c->language(), is_w);
|
try {
|
||||||
|
text = tt_decode_marked(text, c->language(), is_w);
|
||||||
|
} catch (const runtime_error& e) {
|
||||||
|
c->log.warning("Failed to decode chat message: %s", e.what());
|
||||||
|
send_text_message_printf(c, "$C4Failed to decode\nchat message:\n%s", e.what());
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (text.empty()) {
|
if (text.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3247,32 +3269,42 @@ static void on_06(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
|||||||
if (from_name.size() >= 2 && from_name[0] == '\t' && (from_name[1] == 'E' || from_name[1] == 'J')) {
|
if (from_name.size() >= 2 && from_name[0] == '\t' && (from_name[1] == 'E' || from_name[1] == 'J')) {
|
||||||
from_name = from_name.substr(2);
|
from_name = from_name.substr(2);
|
||||||
}
|
}
|
||||||
|
static const string whisper_text = "(whisper)";
|
||||||
for (size_t x = 0; x < l->max_clients; x++) {
|
for (size_t x = 0; x < l->max_clients; x++) {
|
||||||
if (l->clients[x]) {
|
if (l->clients[x]) {
|
||||||
if (private_flags & (1 << x)) {
|
const string& effective_text = (private_flags & (1 << x)) ? whisper_text : text;
|
||||||
send_chat_message(l->clients[x], c->license->serial_number, from_name, "(whisper)", private_flags);
|
try {
|
||||||
} else {
|
send_chat_message(l->clients[x], c->license->serial_number, from_name, effective_text, private_flags);
|
||||||
send_chat_message(l->clients[x], c->license->serial_number, from_name, text, private_flags);
|
} catch (const runtime_error& e) {
|
||||||
|
l->clients[x]->log.warning("Failed to encode chat message: %s", e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const auto& watcher_l : l->watcher_lobbies) {
|
for (const auto& watcher_l : l->watcher_lobbies) {
|
||||||
for (size_t x = 0; x < watcher_l->max_clients; x++) {
|
for (size_t x = 0; x < watcher_l->max_clients; x++) {
|
||||||
if (watcher_l->clients[x]) {
|
if (watcher_l->clients[x]) {
|
||||||
send_chat_message(watcher_l->clients[x], c->license->serial_number, from_name, text, private_flags);
|
try {
|
||||||
|
send_chat_message(watcher_l->clients[x], c->license->serial_number, from_name, text, private_flags);
|
||||||
|
} catch (const runtime_error& e) {
|
||||||
|
watcher_l->clients[x]->log.warning("Failed to encode chat message: %s", e.what());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l->battle_record && l->battle_record->battle_in_progress()) {
|
if (l->battle_record && l->battle_record->battle_in_progress()) {
|
||||||
auto prepared_message = prepare_chat_data(
|
try {
|
||||||
c->version(),
|
auto prepared_message = prepare_chat_data(
|
||||||
c->language(),
|
c->version(),
|
||||||
c->lobby_client_id,
|
c->language(),
|
||||||
p->disp.name.decode(c->language()),
|
c->lobby_client_id,
|
||||||
text,
|
p->disp.name.decode(c->language()),
|
||||||
private_flags);
|
text,
|
||||||
l->battle_record->add_chat_message(c->license->serial_number, std::move(prepared_message));
|
private_flags);
|
||||||
|
l->battle_record->add_chat_message(c->license->serial_number, std::move(prepared_message));
|
||||||
|
} catch (const runtime_error& e) {
|
||||||
|
l->log.warning("Failed to encode chat message for battle record: %s", e.what());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3902,7 +3934,11 @@ void on_D9(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
|||||||
if (is_w && (data.size() & 1)) {
|
if (is_w && (data.size() & 1)) {
|
||||||
data.push_back(0);
|
data.push_back(0);
|
||||||
}
|
}
|
||||||
c->character(true, false)->info_board.encode(tt_decode_marked(data, c->language(), is_w), c->language());
|
try {
|
||||||
|
c->character(true, false)->info_board.encode(tt_decode_marked(data, c->language(), is_w), c->language());
|
||||||
|
} catch (const runtime_error& e) {
|
||||||
|
c->log.warning("Failed to decode info board message: %s", e.what());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_C7(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
void on_C7(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
||||||
@@ -3912,8 +3948,14 @@ void on_C7(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
|||||||
data.push_back(0);
|
data.push_back(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
string message = tt_decode_marked(data, c->language(), is_w);
|
string message;
|
||||||
c->character(true, false)->auto_reply.encode(message, c->language());
|
try {
|
||||||
|
message = tt_decode_marked(data, c->language(), is_w);
|
||||||
|
c->character(true, false)->auto_reply.encode(message, c->language());
|
||||||
|
} catch (const runtime_error& e) {
|
||||||
|
c->log.warning("Failed to decode auto-reply message: %s", e.what());
|
||||||
|
return;
|
||||||
|
}
|
||||||
c->license->auto_reply_message = message;
|
c->license->auto_reply_message = message;
|
||||||
c->license->save();
|
c->license->save();
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-12
@@ -711,16 +711,21 @@ static void send_text(
|
|||||||
color_mode = ColorMode::STRIP;
|
color_mode = ColorMode::STRIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (color_mode) {
|
try {
|
||||||
case ColorMode::NONE:
|
switch (color_mode) {
|
||||||
w.write(tt_encode_marked_optional(text, ch.language, is_w));
|
case ColorMode::NONE:
|
||||||
break;
|
w.write(tt_encode_marked_optional(text, ch.language, is_w));
|
||||||
case ColorMode::ADD:
|
break;
|
||||||
w.write(tt_encode_marked_optional(add_color(text), ch.language, is_w));
|
case ColorMode::ADD:
|
||||||
break;
|
w.write(tt_encode_marked_optional(add_color(text), ch.language, is_w));
|
||||||
case ColorMode::STRIP:
|
break;
|
||||||
w.write(tt_encode_marked_optional(strip_color(text), ch.language, is_w));
|
case ColorMode::STRIP:
|
||||||
break;
|
w.write(tt_encode_marked_optional(strip_color(text), ch.language, is_w));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (const runtime_error& e) {
|
||||||
|
log_warning("Failed to encode message for %02hX command: %s", command, e.what());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_w) {
|
if (is_w) {
|
||||||
@@ -776,7 +781,13 @@ void send_message_box(shared_ptr<Client> c, const string& text) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void send_ep3_timed_message_box(Channel& ch, uint32_t frames, const string& message) {
|
void send_ep3_timed_message_box(Channel& ch, uint32_t frames, const string& message) {
|
||||||
string encoded = tt_encode_marked(add_color(message), ch.language, false);
|
string encoded;
|
||||||
|
try {
|
||||||
|
encoded = tt_encode_marked(add_color(message), ch.language, false);
|
||||||
|
} catch (const runtime_error& e) {
|
||||||
|
log_warning("Failed to encode message for EA command: %s", e.what());
|
||||||
|
return;
|
||||||
|
}
|
||||||
StringWriter w;
|
StringWriter w;
|
||||||
w.put<S_TimedMessageBoxHeader_GC_Ep3_EA>({frames});
|
w.put<S_TimedMessageBoxHeader_GC_Ep3_EA>({frames});
|
||||||
w.write(encoded);
|
w.write(encoded);
|
||||||
@@ -921,7 +932,12 @@ void send_prepared_chat_message(shared_ptr<Lobby> l, uint32_t from_guild_card_nu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_chat_message(shared_ptr<Client> c, uint32_t from_guild_card_number, const string& from_name, const string& text, char private_flags) {
|
void send_chat_message(
|
||||||
|
shared_ptr<Client> c,
|
||||||
|
uint32_t from_guild_card_number,
|
||||||
|
const string& from_name,
|
||||||
|
const string& text,
|
||||||
|
char private_flags) {
|
||||||
string prepared_data = prepare_chat_data(
|
string prepared_data = prepare_chat_data(
|
||||||
c->version(),
|
c->version(),
|
||||||
c->language(),
|
c->language(),
|
||||||
|
|||||||
Reference in New Issue
Block a user