From 7b92cf28664da516cfe5ec1390a672e358c15424 Mon Sep 17 00:00:00 2001 From: Sadie Powell Date: Mon, 10 May 2021 22:54:16 +0100 Subject: Extract percent encoding logic from spanningtree to inspstring. --- src/inspstring.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) (limited to 'src/inspstring.cpp') diff --git a/src/inspstring.cpp b/src/inspstring.cpp index bb3eab2bb..e65e3918f 100644 --- a/src/inspstring.cpp +++ b/src/inspstring.cpp @@ -26,6 +26,66 @@ #include "inspircd.h" +std::string Percent::Encode(const void* data, size_t length, const char* table, char padding) +{ + if (!table) + table = Percent::TABLE; + + // Preallocate the output buffer to avoid constant reallocations. + std::string buffer; + buffer.reserve(length * 3); + + const unsigned char* udata = reinterpret_cast(data); + for (size_t idx = 0; idx < length; ++idx) + { + unsigned char chr = udata[idx]; + if (strchr(table, chr)) + { + // The character is on the safe list; push it as is. + buffer.push_back(chr); + } + else + { + // The character is not on the safe list; percent encode it. + buffer.push_back('%'); + buffer.push_back(Hex::TABLE_UPPER[chr >> 4]); + buffer.push_back(Hex::TABLE_UPPER[chr & 15]); + } + } + + return buffer; +} + +std::string Percent::Decode(const void* data, size_t length) +{ + // Preallocate the output buffer to avoid constant reallocations. + std::string buffer; + buffer.reserve(length * 3); + + const char* cdata = reinterpret_cast(data); + for (size_t idx = 0; idx < length; ++idx) + { + if (cdata[idx] == '%') + { + // Percent encoding encodes two octets into 1-2 characters. + const char octet1 = ++idx < length ? toupper(cdata[idx]) : 0; + const char octet2 = ++idx < length ? toupper(cdata[idx]) : 0; + + const char* table1 = strchr(Hex::TABLE_UPPER, octet1); + const char* table2 = strchr(Hex::TABLE_UPPER, octet2); + + char pair = ((table1 ? table1 - Hex::TABLE_UPPER : 0) << 4) + (table2 ? table2 - Hex::TABLE_UPPER : 0); + buffer.push_back(pair); + } + else + { + buffer.push_back(cdata[idx]); + } + } + + return buffer; +} + std::string Hex::Encode(const void* data, size_t length, const char* table, char separator) { if (!table) -- cgit v1.3.1-10-gc9f91