This commit is contained in:
UnknownObject
2026-06-30 17:49:51 +08:00
commit 292c09619e
200 changed files with 23718 additions and 0 deletions
+211
View File
@@ -0,0 +1,211 @@
#include "Global.h"
#include <memory>
#include <format>
#include <chrono>
#include <cstring>
#include <fstream>
#ifndef _WIN32
#include "UOHash.h"
#else
#include "../UOHash/UOHash.h"
#endif
#include <sodium.h>
#include "SafeRNG.h"
#include <algorithm>
#include <openssl/evp.h>
#include "PathTraversal.h"
std::string uns::EncodeErrorPage(int code)
{
// size_t str_size = strlen(G_SERVER_NAME) + strlen(G_ERROR_PAGE);
// char* buffer = new char[str_size];
// memset(buffer, 0, str_size);
// snprintf(buffer, str_size, G_ERROR_PAGE, code, code, G_SERVER_NAME);
// std::string ret = buffer;
// delete[] buffer;
// return ret;
return std::vformat(G_ERROR_PAGE, std::make_format_args(code, code, G_SERVER_NAME));
}
std::string uns::EncodeHTTPTime(time_t* time)
{
// struct tm t;
// if (time != NULL)
// gmtime_r(time, &t);
// else
// {
// int64_t ltime_cur;
// ::time(&ltime_cur);
// gmtime_r(&ltime_cur, &t);
// }
// char szTime[100] = { 0 };
// // - Sun, 24 Aug 2008 22:43:45 GMT
// sprintf(szTime, "%s, %d %s %d %d:%d:%d GMT", G_HTTP_STD_WEEK[t.tm_wday].c_str(), t.tm_mday, G_HTTP_STD_MONTH[t.tm_mon].c_str(), t.tm_year + 1900, t.tm_hour, t.tm_min, t.tm_sec);
// return szTime;
// 1. 一行搞定时间点获取:如果指针有效就转换,否则直接取当前系统时间
auto tp = time ? std::chrono::system_clock::from_time_t(*time) : std::chrono::system_clock::now();
// 2. 强制截断到“秒”级(floor),避免有些平台输出微秒等尾巴
auto tp_secs = std::chrono::floor<std::chrono::seconds>(tp);
// 3. 直接利用 chrono 占位符格式化输出
// %a: 星期缩写(Sun), %d: 两位日子(02), %b: 月份缩写(Jun), %Y: 四位年份(2026), %T: 24小时制时间(00:00:00)
return std::format("{:%a, %d %b %Y %T} GMT", tp_secs);
}
std::string uns::btos(bool val)
{
return (val ? "true" : "false");
}
bool uns::stob(const std::string& obj)
{
return (obj == "true");
}
DateTime uns::stot(const std::string& obj)
{
int nYear, nMonth, nDate, nHour, nMin, nSec;
int cnt = sscanf(obj.c_str(), "%d-%d-%d %d:%d:%d", &nYear, &nMonth, &nDate, &nHour, &nMin, &nSec);
if (cnt != 6)
return DateTime();
else
return DateTime(nYear, nMonth, nDate, nHour, nMin, nSec);
}
std::string uns::RestoreURL(const std::string& url)
{
std::string res = url;
std::replace(res.begin(), res.end(), '{', '&');
std::replace(res.begin(), res.end(), '}', '=');
return res;
}
void uns::Stringsplit(const std::string& str, const std::string& splits, std::vector<std::string>& res)
{
if (str == "")
return;
std::string strs = str + splits;
size_t pos = strs.find(splits);
size_t step = splits.size();
while (pos != strs.npos)
{
std::string temp = strs.substr(0, pos);
res.push_back(temp);
strs = strs.substr(pos + step, strs.size());
pos = strs.find(splits);
}
}
void uns::ProcessPOSTArgs(const std::string& args, POSTArgs& args_output)
{
args_output.clear();
std::vector<std::string> c1_split, c2_split;
Stringsplit(args, "&", c1_split);
for (const auto& kv : c1_split)
{
c2_split.clear();
c2_split.shrink_to_fit();
Stringsplit(kv, "=", c2_split);
if (c2_split.size() != 2)
continue;
if (c2_split[0] == "origin_url")
args_output.insert({ c2_split[0], RestoreURL(c2_split[1]) });
else
args_output.insert({ c2_split[0], c2_split[1] });
}
}
std::string uns::tools::EncryptPassword(const std::string reg_date, const std::string& password)
{
std::string res_reg_date = reg_date;
std::reverse(res_reg_date.begin(), res_reg_date.end());
std::string war_pwd = reg_date + password + res_reg_date;
auto res = uns::UOHash::HashString(uns::HashID::SHA3_512, war_pwd);
if (!res)
return "";
return res.GetResult();
}
std::string uns::tools::EncryptPasswordSodium(const std::string& pwd)
{
// ======== 参数(128MB 内存) ========
static const size_t MEMLIMIT = 128UL * 1024 * 1024; // 128 MB
static const uint64_t OPSLIMIT = crypto_pwhash_OPSLIMIT_MODERATE;
// =====================================
// 输出缓冲:libsodium 定义的固定大小
char out_str[crypto_pwhash_STRBYTES] = { 0 };
// 生成编码字符串(包含算法、参数、盐、hash),直接存 DB(TEXT)
if (crypto_pwhash_str(out_str, pwd.c_str(), pwd.size(), OPSLIMIT, MEMLIMIT) != 0)
return "";
else
return std::string(out_str);
}
bool uns::tools::CheckPasswordSodium(const std::string& pwd, const std::string& encrypted)
{
return (crypto_pwhash_str_verify(encrypted.c_str(), pwd.c_str(), pwd.length()) == 0);
}
std::string uns::tools::SecureRandomHex(size_t bytes)
{
return RandomNumberGenerator::SecureRandomHex(bytes);
}
std::string uns::tools::ToUpper(const std::string& s)
{
std::string r; r.reserve(s.size());
for (unsigned char c : s)
r.push_back(static_cast<char>(std::toupper(c)));
return r;
}
std::string uns::tools::ToLower(const std::string& s)
{
std::string r; r.reserve(s.size());
for (unsigned char c : s)
r.push_back(static_cast<char>(std::tolower(c)));
return r;
}
std::string uns::tools::CalculateFileHashSHA256(const std::string & file)
{
// 1. 以二进制模式打开文件
std::ifstream ifs(file, std::ios::binary);
if (!ifs.is_open()) // 文件打开失败,返回空字符串(也可以根据你的项目规范记录日志或抛出异常)
return std::string();
// 2. 初始化 OpenSSL EVP 上下文,使用智能指针自动管理内存释放
std::unique_ptr<EVP_MD_CTX, void(*)(EVP_MD_CTX*)> ctx(EVP_MD_CTX_new(), EVP_MD_CTX_free);
if (!ctx)
return std::string();
// 3. 指定使用 SHA256 算法
if (EVP_DigestInit_ex(ctx.get(), EVP_sha256(), nullptr) != 1)
return std::string();
// 4. 分块读取文件并更新哈希计算(每次读取 4096 字节,避免大文件占用过多内存)
constexpr size_t kBufferSize = 4096;
char buffer[kBufferSize];
while (ifs.read(buffer, kBufferSize) || ifs.gcount() > 0)
{
if (EVP_DigestUpdate(ctx.get(), buffer, ifs.gcount()) != 1)
return std::string();
}
// 5. 结束哈希计算并获取二进制结果
unsigned char hash[EVP_MAX_MD_SIZE];
unsigned int length = 0;
if (EVP_DigestFinal_ex(ctx.get(), hash, &length) != 1)
return std::string();
// 6. 将二进制哈希值转换为 16 进制字符串 (Hex String)
std::string hex_result;
hex_result.reserve(length * 2);
for (unsigned int i = 0; i < length; ++i)
{
char buf[3];
snprintf(buf, sizeof(buf), "%02x", hash[i]);
hex_result.append(buf);
}
return hex_result;
}
bool uns::secure::IsSafePath(const std::string & safe_path, const std::string & requested_path)
{
return PathTraversal::IsSafePath(safe_path, requested_path);
}