escape player-provided text in various places

This commit is contained in:
Martin Michelsen
2023-12-26 07:37:00 -08:00
parent 5382e12b8d
commit ccd1b56cae
6 changed files with 74 additions and 25 deletions
+13 -11
View File
@@ -639,7 +639,7 @@ static void proxy_command_get_player_card(shared_ptr<ProxyServer::LinkedSession>
send_guild_card(ses->client_channel, p.guild_card_number, p.guild_card_number, p.name, "", "", p.language, p.section_id, p.char_class);
}
} catch (const exception& e) {
send_text_message_printf(ses->client_channel, "Error: %s", e.what());
send_text_message(ses->client_channel, "Error: " + remove_color(e.what()));
}
}
}
@@ -685,7 +685,7 @@ static void server_command_lobby_event(shared_ptr<Client> c, const std::string&
uint8_t new_event = event_for_name(args);
if (new_event == 0xFF) {
send_text_message(c, "$C6No such lobby event.");
send_text_message(c, "$C6No such lobby event");
return;
}
@@ -699,7 +699,7 @@ static void proxy_command_lobby_event(shared_ptr<ProxyServer::LinkedSession> ses
} else {
uint8_t new_event = event_for_name(args);
if (new_event == 0xFF) {
send_text_message(ses->client_channel, "$C6No such lobby event.");
send_text_message(ses->client_channel, "$C6No such lobby event");
} else {
ses->config.override_lobby_event = new_event;
if (!is_v1_or_v2(ses->version())) {
@@ -714,7 +714,7 @@ static void server_command_lobby_event_all(shared_ptr<Client> c, const std::stri
uint8_t new_event = event_for_name(args);
if (new_event == 0xFF) {
send_text_message(c, "$C6No such lobby event.");
send_text_message(c, "$C6No such lobby event");
return;
}
@@ -919,7 +919,8 @@ static void server_command_password(shared_ptr<Client> c, const std::string& arg
} else {
l->password = args;
send_text_message_printf(l, "$C6Game password:\n%s", l->password.c_str());
string escaped = remove_color(l->password);
send_text_message_printf(l, "$C6Game password:\n%s", escaped.c_str());
}
}
@@ -1113,7 +1114,8 @@ static void server_command_change_bank(shared_ptr<Client> c, const std::string&
} else if (new_char_index <= 4) {
c->use_character_bank(new_char_index - 1);
auto bp = c->current_bank_character();
auto name = bp->disp.name.decode(c->language());
auto name = escape_player_name(bp->disp.name.decode(c->language()));
send_text_message_printf(c, "$C6Using %s\'s bank (%zu)", name.c_str(), new_char_index);
} else {
throw runtime_error("invalid bank number");
@@ -1201,7 +1203,7 @@ static void server_command_save(shared_ptr<Client> c, const std::string&) {
c->save_all();
send_text_message(c, "All data saved");
} catch (const exception& e) {
send_text_message_printf(c, "Can\'t save data:\n%s", e.what());
send_text_message(c, "Can\'t save data:\n" + remove_color(e.what()));
}
c->reschedule_save_game_data_event();
}
@@ -1212,7 +1214,7 @@ static void server_command_save(shared_ptr<Client> c, const std::string&) {
static string name_for_client(shared_ptr<Client> c) {
auto player = c->character(false);
if (player.get()) {
return player->disp.name.decode(player->inventory.language);
return escape_player_name(player->disp.name.decode(player->inventory.language));
}
if (c->license.get()) {
@@ -1778,7 +1780,7 @@ static void server_command_surrender(shared_ptr<Client> c, const std::string&) {
send_text_message(c, "$C6Battle has not\nyet started");
return;
}
const string& name = c->character()->disp.name.decode(c->language());
string name = remove_color(c->character()->disp.name.decode(c->language()));
send_text_message_printf(l, "$C6%s has\nsurrendered", name.c_str());
for (const auto& watcher_l : l->watcher_lobbies) {
send_text_message_printf(watcher_l, "$C6%s has\nsurrendered", name.c_str());
@@ -1983,7 +1985,7 @@ void on_chat_command(std::shared_ptr<Client> c, const std::string& text) {
} catch (const precondition_failed& e) {
send_text_message(c, e.what());
} catch (const exception& e) {
send_text_message_printf(c, "$C6Failed:\n%s", e.what());
send_text_message(c, "$C6Failed:\n" + remove_color(e.what()));
}
}
}
@@ -2007,7 +2009,7 @@ void on_chat_command(shared_ptr<ProxyServer::LinkedSession> ses, const std::stri
} catch (const precondition_failed& e) {
send_text_message(ses->client_channel, e.what());
} catch (const exception& e) {
send_text_message_printf(ses->client_channel, "$C6Failed:\n%s", e.what());
send_text_message(ses->client_channel, "$C6Failed:\n" + remove_color(e.what()));
}
}
}
+3 -3
View File
@@ -1400,8 +1400,7 @@ static HandlerResult S_65_67_68_EB(shared_ptr<ProxyServer::LinkedSession> ses, u
if (index >= ses->lobby_players.size()) {
ses->log.warning("Ignoring invalid player index %zu at position %zu", index, x);
} else {
string name = entry.disp.visual.name.decode(entry.inventory.language);
string name = escape_player_name(entry.disp.visual.name.decode(entry.inventory.language));
if (ses->license && (entry.lobby_data.guild_card_number == ses->remote_guild_card_number)) {
entry.lobby_data.guild_card_number = ses->license->serial_number;
num_replacements++;
@@ -1578,9 +1577,10 @@ static HandlerResult S_66_69_E9(shared_ptr<ProxyServer::LinkedSession> ses, uint
ses->log.warning("Lobby leave command references missing position");
} else {
auto& p = ses->lobby_players[index];
string name = escape_player_name(p.name);
if (ses->config.check_flag(Client::Flag::PROXY_PLAYER_NOTIFICATIONS_ENABLED)) {
send_text_message_printf(ses->client_channel, "$C4Leave: %zu/%" PRIu32 "\n%s",
index, p.guild_card_number, p.name.c_str());
index, p.guild_card_number, name.c_str());
}
p.guild_card_number = 0;
p.name.clear();
+13 -9
View File
@@ -1786,7 +1786,7 @@ static void on_09(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
const auto& game_c = game->clients[x];
if (game_c.get()) {
auto player = game_c->character();
string name = player->disp.name.decode(game_c->language());
string name = escape_player_name(player->disp.name.decode(game_c->language()));
if (game->is_ep3()) {
info += string_printf("%zu: $C6%s$C7 L%" PRIu32 "\n",
x + 1, name.c_str(), player->disp.stats.level + 1);
@@ -1808,16 +1808,16 @@ static void on_09(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
bool cheats_enabled = game->check_flag(Lobby::Flag::CHEATS_ENABLED);
bool locked = !game->password.empty();
if (cheats_enabled && locked) {
info += "$C4Locked$C7, $C6cheats enabled$C7\n";
info += "$C4Locked$C7, $C6cheats on$C7\n";
} else if (cheats_enabled) {
info += "$C6Cheats enabled$C7\n";
info += "$C6Cheats on$C7\n";
} else if (locked) {
info += "$C4Locked$C7\n";
}
if (game->quest) {
info += (game->check_flag(Lobby::Flag::JOINABLE_QUEST_IN_PROGRESS)) ? "$C6Quest: " : "$C4Quest: ";
info += game->quest->name;
info += remove_color(game->quest->name);
info += "\n";
} else if (game->check_flag(Lobby::Flag::JOINABLE_QUEST_IN_PROGRESS)) {
info += "$C6Quest in progress\n";
@@ -1862,17 +1862,18 @@ static void on_09(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
auto team = tourn->get_team(team_index);
if (team) {
string message;
if (team->name.empty()) {
string team_name = escape_player_name(team->name);
if (team_name.empty()) {
message = "(No registrant)";
} else if (team->max_players == 1) {
message = string_printf("$C6%s$C7\n%zu %s (%s)\nPlayers:",
team->name.c_str(),
team_name.c_str(),
team->num_rounds_cleared,
team->num_rounds_cleared == 1 ? "win" : "wins",
team->is_active ? "active" : "defeated");
} else {
message = string_printf("$C6%s$C7\n%zu %s (%s)%s\nPlayers:",
team->name.c_str(),
team_name.c_str(),
team->num_rounds_cleared,
team->num_rounds_cleared == 1 ? "win" : "wins",
team->is_active ? "active" : "defeated",
@@ -1883,10 +1884,13 @@ static void on_09(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
if (player.player_name.empty()) {
message += string_printf("\n $C6%08" PRIX32 "$C7", player.serial_number);
} else {
message += string_printf("\n $C6%s$C7 (%08" PRIX32 ")", player.player_name.c_str(), player.serial_number);
string player_name = escape_player_name(player.player_name);
message += string_printf("\n $C6%s$C7 (%08" PRIX32 ")", player_name.c_str(), player.serial_number);
}
} else {
message += string_printf("\n $C3%s \"%s\"$C7", player.com_deck->player_name.c_str(), player.com_deck->deck_name.c_str());
string player_name = escape_player_name(player.com_deck->player_name);
string deck_name = escape_player_name(player.com_deck->deck_name);
message += string_printf("\n $C3%s \"%s\"$C7", player_name.c_str(), deck_name.c_str());
}
}
send_ship_info(c, message);
+1 -1
View File
@@ -842,7 +842,7 @@ static void on_word_select_t(shared_ptr<Client> c, uint8_t command, uint8_t, voi
}
} catch (const exception& e) {
string name = c->character()->disp.name.decode(c->language());
string name = escape_player_name(c->character()->disp.name.decode(c->language()));
lc->log.warning("Untranslatable Word Select message: %s", e.what());
send_text_message_printf(lc, "$C4Untranslatable Word\nSelect message from\n%s", name.c_str());
}
+37 -1
View File
@@ -281,7 +281,6 @@ void add_color(StringWriter& w, const char* src, size_t max_input_chars) {
}
src++;
}
w.put<char>(0);
}
string add_color(const string& s) {
@@ -290,6 +289,35 @@ string add_color(const string& s) {
return std::move(w.str());
}
void remove_color(StringWriter& w, const char* src, size_t max_input_chars) {
for (size_t x = 0; (x < max_input_chars) && *src; x++) {
if (*src == '$') {
w.put<char>('%');
w.put<char>('s');
} else if (*src == '%') {
w.put<char>('%');
w.put<char>('%');
} else if (*src == '#') {
w.put<char>('%');
w.put<char>('n');
} else if (*src == '\t') {
w.put<char>('$');
} else if (*src == '\n') {
w.put<char>('#');
} else {
w.put<char>(*src);
}
src++;
}
w.put<char>(0);
}
string remove_color(const string& s) {
StringWriter w;
remove_color(w, s.data(), s.size());
return std::move(w.str());
}
string strip_color(const string& s) {
string ret;
for (size_t r = 0; r < s.size(); r++) {
@@ -302,3 +330,11 @@ string strip_color(const string& s) {
}
return ret;
}
string escape_player_name(const string& name) {
if (name.size() > 2 && name[0] == '\t' && name[1] != 'C') {
return remove_color(name.substr(2));
} else {
return remove_color(name);
}
}
+7
View File
@@ -549,4 +549,11 @@ std::string add_color(const std::string& s);
size_t add_color_inplace(char* a, size_t max_chars);
void add_color_inplace(std::string& s);
// remove_color does the opposite of add_color (it changes \t into $, for
// example). strip_color is irreversible; it deletes color escape sequences.
void remove_color(StringWriter& w, const char* src, size_t max_input_chars);
std::string remove_color(const std::string& s);
std::string strip_color(const std::string& s);
std::string escape_player_name(const std::string& name);