Files
radiantwave/src/validation.cpp
T
2026-08-07 14:51:41 -05:00

91 lines
2.3 KiB
C++

#include "validation.h"
#include <cctype>
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<unsigned char>(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<char>(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