#include "validation.h" #include namespace radiantwave::validation { bool isValidEmail(const std::string& email) { if (email.size() < 3 || email.size() > 254) { return false; } const size_t at = email.find('@'); if (at == std::string::npos || at == 0 || at == email.size() - 1) { return false; } if (email.find('@', at + 1) != std::string::npos) { return false; } for (unsigned char c : email) { if (std::isspace(c)) { return false; } } const std::string local = email.substr(0, at); const std::string domain = email.substr(at + 1); // Local part: alphanumerics plus ._%+- , but never leading/trailing dots. if (local.front() == '.' || local.back() == '.') { return false; } for (unsigned char c : local) { if (!(std::isalnum(c) || c == '.' || c == '_' || c == '%' || c == '+' || c == '-')) { return false; } } // Domain part: dot-separated labels of alphanumerics/hyphens. if (domain.front() == '.' || domain.back() == '.') { return false; } int labels = 0; size_t start = 0; for (size_t i = 0; i <= domain.size(); ++i) { if (i == domain.size() || domain[i] == '.') { const size_t len = i - start; if (len == 0) { return false; } for (size_t j = start; j < i; ++j) { const unsigned char c = static_cast(domain[j]); if (!(std::isalnum(c) || c == '-')) { return false; } } ++labels; start = i + 1; } } return labels >= 2; } std::string sanitizeLicenseKey(const std::string& input) { std::string out; out.reserve(16); for (unsigned char c : input) { if (out.size() >= 16) { break; } if (std::isalnum(c)) { out += static_cast(std::toupper(c)); } } return out; } std::string formatLicenseKey(const std::string& sanitized) { std::string out; out.reserve(19); for (size_t i = 0; i < sanitized.size(); ++i) { if (i > 0 && i % 4 == 0) { out += '-'; } out += sanitized[i]; } return out; } } // namespace radiantwave::validation