From bee8b92a6db2855313046b99d0537222cfeb69d3 Mon Sep 17 00:00:00 2001 From: Brad Arant Date: Sun, 6 Sep 2026 18:39:30 +0000 Subject: [PATCH] Fold command names to uppercase at registration, not just at lookup CommandList::processRequest() upper-cases the incoming keyword before looking it up, but add() stored whatever case the caller passed in verbatim - any registration not already uppercase could then never be matched by any input at all, since upper-casing a non-uppercase string cannot produce a match against a non-uppercase key. This was invisible on BARANTMail/APIServer (their own commands - SMTP, POP3/IMAP, the admin console - all happen to already be registered uppercase) but confirmed, via a full Zephora game client/server protocol comparison, to make literally every Zephora game command unreachable, including the base TCPServer's own publish/subscribe/event/etc. registrations that the whole subscription layer depends on. Folding at add() time keeps registration and lookup permanently in sync regardless of caller case; already-uppercase callers are unaffected (idempotent). --- CommandList.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CommandList.cpp b/CommandList.cpp index 9ec1e2e..0bffe34 100644 --- a/CommandList.cpp +++ b/CommandList.cpp @@ -8,6 +8,23 @@ namespace core { CommandList::CommandList(std::string delimiter, int depth) : delimiter(delimiter), depth(depth) {} void CommandList::add(Command &command, std::string name) { + // processRequest() below upper-cases the incoming keyword before + // looking it up, but this previously stored whatever case the + // caller passed in verbatim - any registration that wasn't + // already uppercase (nearly everything outside SMTP/POP3/IMAP's + // own RFC-driven uppercase convention) could then NEVER be + // matched by any input, since upper-casing a non-uppercase string + // can't produce a match against a non-uppercase key. Confirmed: + // this alone made every Zephora game command unreachable, along + // with this class's own base-level "publish"/"subscribe"/"event"/ + // etc. registrations (TCPServer's constructor). Folding the same + // way here keeps registration and lookup permanently in sync + // regardless of what case any given add() call happens to use - + // already-uppercase callers (SMTP, the BARANTMail admin console) + // are unaffected, since upper-casing an uppercase string is a + // no-op. + std::transform(name.begin(), name.end(), name.begin(), + [](unsigned char c) { return std::toupper(c); }); commands.insert(std::make_pair(name, &command)); }