From 268ededc1943233b430101b8b9070a34b44a5446 Mon Sep 17 00:00:00 2001 From: waffle2k Date: Mon, 15 Jun 2026 15:47:55 -0700 Subject: [PATCH] Make username lookup case-insensitive finger Pete@peteftw.com (or any mixed-case name) failed because the plan path was built from the raw username while plan files are lower-case on disk. Lower-case the requested name before resolving the plan path; the original spelling is still echoed back when no plan file exists. Add a mock test asserting Pete -> .../pete. --- handler.cpp | 12 +++++++++++- test_handler_mock.cpp | 15 +++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/handler.cpp b/handler.cpp index e0d8bcf..faefe0d 100644 --- a/handler.cpp +++ b/handler.cpp @@ -1,4 +1,6 @@ #include "handler.hpp" +#include +#include #include #include #include @@ -65,8 +67,16 @@ std::string process(const std::string &username, const IFilesystemWrapper &fs, return std::string("InvalidInput: ") + e.what() + std::string("\r\n"); } + // Plan-file lookup is case-insensitive: normalise the requested name to + // lower-case so e.g. "Pete" resolves the on-disk "pete" plan. Plan filenames + // are always lower-case; the original spelling is still echoed back below + // when no plan exists. + std::string lookup = username; + std::transform(lookup.begin(), lookup.end(), lookup.begin(), + [](unsigned char c) { return std::tolower(c); }); + // Attempt to open the plan file (if any) and return the contents as a string - std::filesystem::path planPath = basepath / username; + std::filesystem::path planPath = basepath / lookup; // Check if the plan file exists using the filesystem wrapper if (!fs.exists(planPath)) { diff --git a/test_handler_mock.cpp b/test_handler_mock.cpp index 2f5c3f6..71a19e6 100644 --- a/test_handler_mock.cpp +++ b/test_handler_mock.cpp @@ -64,6 +64,21 @@ TEST_F(ProcessMockTest, ProcessWithEmptyFile) { EXPECT_EQ(result, "emptyfileuser"); } +// Username lookup is case-insensitive: a mixed-case request is lowercased +// before the plan-file path is built, so "Pete" reads .../pete. +TEST_F(ProcessMockTest, ProcessLowercasesUsernameForLookup) { + using ::testing::Return; + const std::filesystem::path base{"/var/finger/users/"}; + + EXPECT_CALL(*mock_filesystem, exists(base / "pete")) + .WillOnce(Return(true)); + EXPECT_CALL(*mock_filesystem, read_file(base / "pete")) + .WillOnce(Return("Just another hacker.\r\n")); + + std::string result = process("Pete", *mock_filesystem, base); + EXPECT_EQ(result, "Just another hacker.\r\n"); +} + // Test showing multiple expectations TEST_F(ProcessMockTest, MultipleFileOperations) { using ::testing::_;