From 771beeb82d13916ce3498a51ed8bf1eba24d750b Mon Sep 17 00:00:00 2001 From: ephphatha Date: Sat, 18 Jun 2022 11:25:27 +1000 Subject: [PATCH] Use string_view for UiValidPlayerName --- Source/DiabloUI/diabloui.cpp | 32 ++++++++++++++++++++------------ Source/DiabloUI/diabloui.h | 2 +- Source/platform/locale.cpp | 3 +-- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/Source/DiabloUI/diabloui.cpp b/Source/DiabloUI/diabloui.cpp index bddda44a5..2c0cb0447 100644 --- a/Source/DiabloUI/diabloui.cpp +++ b/Source/DiabloUI/diabloui.cpp @@ -621,19 +621,27 @@ void UiDestroy() UnloadUiGFX(); } -bool UiValidPlayerName(const char *name) +bool UiValidPlayerName(string_view name) { - if (strlen(name) == 0) + if (name.empty()) return false; - if (strpbrk(name, ",<>%&\\\"?*#/:") != nullptr || strpbrk(name, " ") != nullptr) + // Currently only allow saving PLR_NAME_LEN bytes as a player name, so if the name is too long we'd have to truncate it. + // That said the input buffer is only 16 bytes long... + if (name.size() > PLR_NAME_LEN) return false; - for (BYTE *letter = (BYTE *)name; *letter != '\0'; letter++) - if (*letter < 0x20 || (*letter > 0x7E && *letter < 0xC0)) + if (name.find_first_of(",<>%&\\\"?*#/: ") != name.npos) + return false; + + constexpr auto isAsciiControlCharacter = [](char character) -> bool { + return (character >= 0x00 && character < 0x20) || character == 0x7F; + }; + for (char letter : name) + if (isAsciiControlCharacter(letter) || !IsLeadUtf8CodeUnit(letter)) return false; - const char *const bannedNames[] = { + string_view bannedNames[] = { "gvdl", "dvou", "tiju", @@ -644,13 +652,13 @@ bool UiValidPlayerName(const char *name) "benjo", }; - char tmpname[PLR_NAME_LEN]; - CopyUtf8(tmpname, name, sizeof(tmpname)); - for (size_t i = 0, n = strlen(tmpname); i < n; i++) - tmpname[i]++; + std::string buffer { name }; + for (char &character : buffer) + character++; - for (const auto *bannedName : bannedNames) { - if (strstr(tmpname, bannedName) != nullptr) + string_view tempName { buffer }; + for (string_view bannedName : bannedNames) { + if (tempName.find(bannedName) != tempName.npos) return false; } diff --git a/Source/DiabloUI/diabloui.h b/Source/DiabloUI/diabloui.h index eaa4260b8..1710a1011 100644 --- a/Source/DiabloUI/diabloui.h +++ b/Source/DiabloUI/diabloui.h @@ -87,7 +87,7 @@ void UiDestroy(); void UiTitleDialog(); void UnloadUiGFX(); void UiInitialize(); -bool UiValidPlayerName(const char *name); /* check */ +bool UiValidPlayerName(string_view name); /* check */ void UiSelHeroMultDialog(bool (*fninfo)(bool (*fninfofunc)(_uiheroinfo *)), bool (*fncreate)(_uiheroinfo *), bool (*fnremove)(_uiheroinfo *), void (*fnstats)(unsigned int, _uidefaultstats *), _selhero_selections *dlgresult, uint32_t *saveNumber); void UiSelHeroSingDialog(bool (*fninfo)(bool (*fninfofunc)(_uiheroinfo *)), bool (*fncreate)(_uiheroinfo *), bool (*fnremove)(_uiheroinfo *), void (*fnstats)(unsigned int, _uidefaultstats *), _selhero_selections *dlgresult, uint32_t *saveNumber, _difficulty *difficulty); bool UiCreditsDialog(); diff --git a/Source/platform/locale.cpp b/Source/platform/locale.cpp index 86bf5f5ed..4a6fd144f 100644 --- a/Source/platform/locale.cpp +++ b/Source/platform/locale.cpp @@ -191,9 +191,8 @@ std::vector GetLocales() if (!languages.empty()) locales.emplace_back(languages.substr(0, languages.find_first_of("."))); } else { - size_t separatorPos {}; do { - separatorPos = languages.find_first_of(":"); + size_t separatorPos = languages.find_first_of(":"); if (separatorPos != 0) locales.emplace_back(std::string(languages.substr(0, separatorPos)));