#include "html_util.h" String html_escape(const String &input) { String out; out.reserve(input.length() + 8); for (size_t i = 0; i < input.length(); ++i) { char c = input[i]; switch (c) { case '&': out += "&"; break; case '<': out += "<"; break; case '>': out += ">"; break; case '"': out += """; break; case '\'': out += "'"; break; default: out += c; break; } } return out; } String url_encode_component(const String &input) { String out; out.reserve(input.length() * 3); const char *hex = "0123456789ABCDEF"; for (size_t i = 0; i < input.length(); ++i) { unsigned char c = static_cast(input[i]); bool safe = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '.' || c == '~'; if (safe) { out += static_cast(c); } else { out += '%'; out += hex[(c >> 4) & 0x0F]; out += hex[c & 0x0F]; } } return out; } static bool is_hex_char(char c) { return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); } static String to_upper_hex4(const String &input) { String out = input; out.toUpperCase(); return out; } bool sanitize_device_id(const String &input, String &out_device_id) { String trimmed = input; trimmed.trim(); if (trimmed.length() == 0) { return false; } if (trimmed.indexOf('/') >= 0 || trimmed.indexOf('\\') >= 0 || trimmed.indexOf("..") >= 0) { return false; } if (trimmed.indexOf('%') >= 0) { return false; } if (trimmed.length() == 4) { for (size_t i = 0; i < 4; ++i) { if (!is_hex_char(trimmed[i])) { return false; } } out_device_id = String("dd3-") + to_upper_hex4(trimmed); return true; } if (trimmed.length() == 8 && trimmed.startsWith("dd3-")) { String hex = trimmed.substring(4); for (size_t i = 0; i < 4; ++i) { if (!is_hex_char(hex[i])) { return false; } } out_device_id = String("dd3-") + to_upper_hex4(hex); return true; } return false; }