Feature: Add menu to set screen strategy for remote control

This commit is contained in:
yuanyuanxiang
2026-01-08 22:10:38 +01:00
parent e0239dce8d
commit 808371ed6e
31 changed files with 541 additions and 425 deletions

View File

@@ -200,6 +200,7 @@ enum {
CMD_FPS = 71,
CMD_COMPRESS_FILES = 72, // 压缩文件
CMD_UNCOMPRESS_FILES = 73, // 解压文件
CMD_SCREEN_SIZE = 74,
// 服务端发出的标识
TOKEN_AUTH = 100, // 要求验证

View File

@@ -1,20 +1,19 @@

/*
鍘熸枃锛歨ttps://github.com/yuanyuanxiang/SimpleRemoter/releases/tag/v1.0.1.1
/*
原文https://github.com/yuanyuanxiang/SimpleRemoter/releases/tag/v1.0.1.1
鑷獀1.1.1鐗堟湰寮€濮嬶紝涓绘帶绋嬪簭闇€瑕佹巿鏉冿紝骞朵笖浼氳嚜鍔ㄨ繛鎺ュ埌鎺堟潈鏈嶅姟鍣紝鎮ㄥ彲浠ヨ仈绯讳綔鑰呰姹傛巿鏉冦€?
濡傛灉瀵硅繖涓湁鎰忚锛岃浣跨敤鏃╂湡鐗堟湰锛?v1.0.8锛夈€傝嚜琛屼慨鏀瑰拰缂栬瘧绋嬪簭锛屼篃鍙互瑙e喅璇ラ棶棰橈紙鍙傝€?#91锛夈€?
自v1.1.1版本开始,主控程序需要授权,并且会自动连接到授权服务器,您可以联系作者请求授权。
如果对这个有意见,请使用早期版本(<v1.0.8)。自行修改和编译程序,也可以解决该问题(参考 #91
浣滆€呮姇鍏ヤ簡涓氫綑绮惧姏鏉ョ淮鎶ゃ€佹洿鏂版湰杞欢锛屽紑婧愪粎渚涘涔犱氦娴佷箣鐢紝鐩堝埄骞堕潪涓昏鐩殑銆?
鑻ラ渶浣跨敤鍙戝竷鐗堟湰锛岄』鑾峰緱鎺堟潈锛岄渶瑕佹敮浠樹竴瀹氱殑鎺堟潈璐圭敤銆?
作者投入了业余精力来维护、更新本软件,开源仅供学习交流之用,盈利并非主要目的。
若需使用发布版本,须获得授权,需要支付一定的授权费用。
浣犲彲浠ヨ嚜鐢变慨鏀逛唬鐮佸苟鑷缂栬瘧浣跨敤锛堣鍙傝€冧笂杩伴棶棰橈細#91锛夛紝姝ゆ儏鍐典笅涓嶆敹鍙栦换浣曡垂鐢ㄣ€?
寤鸿鐢ㄦ埛浼樺厛灏濊瘯鑷缂栬瘧锛屾垨娴嬭瘯鏃х増鏈槸鍚﹀凡鑳芥弧瓒抽渶姹傦紱濡備粛鏈夐渶瑕佷笖鍏峰棰勭畻锛屽彲鍐嶈€冭檻姝e紡鎺堟潈銆?
你可以自由修改代码并自行编译使用(请参考上述问题:#91此情况下不收取任何费用。
建议用户优先尝试自行编译,或测试旧版本是否已能满足需求;如仍有需要且具备预算,可再考虑正式授权。
濡傚凡鑾峰緱鎺堟潈锛屽悗缁彂甯冪殑鏂扮増鏈彲缁х画浣跨敤锛屼笖鏈娇鐢ㄥ畬鐨勬巿鏉冩椂闂村皢鑷姩椤哄欢鑷虫柊鐗堟湰銆?
如已获得授权,后续发布的新版本可继续使用,且未使用完的授权时间将自动顺延至新版本。
鈿狅笍 鏈蒋浠朵粎闄愪簬鍚堟硶銆佹褰撱€佸悎瑙勭殑鐢ㄩ€斻€傜姝㈠皢鏈蒋浠剁敤浜庝换浣曡繚娉曘€佹伓鎰忋€佷镜鏉冩垨杩濆弽閬撳痉瑙勮寖鐨勮涓恒€?
浣滆€呬笉瀵逛换浣曞洜婊ョ敤杞欢鎵€寮曞彂鐨勬硶寰嬭矗浠汇€佹崯瀹虫垨浜夎鎵挎媴浠讳綍璐d换锛屽苟淇濈暀鍦ㄥ彂鐜版垨鎬€鐤戜笉褰撶敤閫旀椂鎷掔粷鎴栫粓姝㈡巿鏉冪殑鏉冨埄銆?
⚠️ 本软件仅限于合法、正当、合规的用途。禁止将本软件用于任何违法、恶意、侵权或违反道德规范的行为。
作者不对任何因滥用软件所引发的法律责任、损害或争议承担任何责任,并保留在发现或怀疑不当用途时拒绝或终止授权的权利。
--------------------------------------------------------------------------------------------------------------
@@ -35,14 +34,14 @@ If further functionality is required and budget is available, you may then consi
If a license is obtained, future versions of the software can continue to be used under the same license,
and any remaining license time will be automatically carried over to the new version.
鈿狅笍 This software is intended for lawful, legitimate, and compliant use only.
⚠️ This software is intended for lawful, legitimate, and compliant use only.
Any use of this software for illegal, malicious, infringing, or unethical purposes is strictly prohibited.
The author shall not be held liable for any legal issues, damages, or disputes resulting from misuse of
the software, and reserves the right to refuse or revoke authorization if improper use is discovered or suspected.
*/
// 涓绘帶绋嬪簭鍞竴鏍囪瘑
// 鎻愮ず: 淇敼杩欎釜鍝堝笇鍙兘閫犳垚涓€浜涘姛鑳藉彈闄愶紝鑷富鎺х殑v1.1.1鐗堟湰璧凤紝绋嬪簭鐨勮澶氬姛鑳戒緷璧栦簬璇ュ搱甯?
// 鍥犳锛屽浜庢兂鐮撮櫎绋嬪簭鎺堟潈闄愬埗鐨勮涓猴紝寤鸿鍩轰簬v1.1.1鐗堟湰锛岀敋鑷充娇鐢ㄦ棤闇€鎺堟潈鐨勭増鏈紙濡傝兘婊¤冻闇€姹傦級.
// 褰撶劧杩欎簺鏃╂湡鐗堟湰娌℃湁鍖呭惈闂淇鍜屾柊鐨勫姛鑳?
#define MASTER_HASH "61f04dd637a74ee34493fc1025de2c131022536da751c29e3ff4e9024d8eec43"
// 主控程序唯一标识
// 提示: 修改这个哈希可能造成一些功能受限自主控的v1.1.1版本起,程序的诸多功能依赖于该哈希.
// 因此对于想破除程序授权限制的行为建议基于v1.1.1版本,甚至使用无需授权的版本(如能满足需求).
// 当然这些早期版本没有包含问题修复和新的功能.
#define MASTER_HASH "61f04dd637a74ee34493fc1025de2c131022536da751c29e3ff4e9024d8eec43"

View File

@@ -51,24 +51,24 @@ static inline std::string GetRegistryName() {
return name;
}
// 鑾峰彇褰撳墠浼氳瘽鐢ㄦ埛鐨勬敞鍐岃〃鏍归敭
// SYSTEM 杩涚▼鏃犳硶浣跨敤 HKEY_CURRENT_USER锛岄渶瑕侀€氳繃 HKEY_USERS\<SID> 璁块棶
// 杩斿洖鐨?HKEY 闇€瑕佽皟鐢ㄨ€呭湪浣跨敤瀹屾瘯鍚庤皟鐢?RegCloseKey 鍏抽棴
// 获取当前会话用户的注册表根键
// SYSTEM 进程无法使用 HKEY_CURRENT_USER,需要通过 HKEY_USERS\<SID> 访问
// 返回的 HKEY 需要调用者在使用完毕后调用 RegCloseKey 关闭
inline HKEY GetCurrentUserRegistryKey()
{
HKEY hUserKey = NULL;
// 鑾峰彇褰撳墠杩涚▼鐨勪細璇?ID
// 获取当前进程的会话 ID
DWORD sessionId = 0;
ProcessIdToSessionId(GetCurrentProcessId(), &sessionId);
// 鑾峰彇璇ヤ細璇濈殑鐢ㄦ埛浠ょ墝
// 获取该会话的用户令牌
HANDLE hUserToken = NULL;
if (!WTSQueryUserToken(sessionId, &hUserToken)) {
// 濡傛灉澶辫触锛堝彲鑳戒笉鏄湇鍔¤繘绋嬶級锛屽洖閫€鍒?HKEY_CURRENT_USER
// 如果失败(可能不是服务进程),回退到 HKEY_CURRENT_USER
return HKEY_CURRENT_USER;
}
// 鑾峰彇浠ょ墝涓殑鐢ㄦ埛淇℃伅澶у皬
// 获取令牌中的用户信息大小
DWORD dwSize = 0;
GetTokenInformation(hUserToken, TokenUser, NULL, 0, &dwSize);
if (dwSize == 0) {
@@ -76,7 +76,7 @@ inline HKEY GetCurrentUserRegistryKey()
return HKEY_CURRENT_USER;
}
// 鍒嗛厤鍐呭瓨骞惰幏鍙栫敤鎴蜂俊鎭?
// 分配内存并获取用户信息
TOKEN_USER* pTokenUser = (TOKEN_USER*)malloc(dwSize);
if (!pTokenUser) {
SAFE_CLOSE_HANDLE(hUserToken);
@@ -89,7 +89,7 @@ inline HKEY GetCurrentUserRegistryKey()
return HKEY_CURRENT_USER;
}
// 灏?SID 杞崲涓哄瓧绗︿覆
// SID 转换为字符串
LPSTR szSid = NULL;
if (!ConvertSidToStringSidA(pTokenUser->User.Sid, &szSid)) {
free(pTokenUser);
@@ -97,9 +97,9 @@ inline HKEY GetCurrentUserRegistryKey()
return HKEY_CURRENT_USER;
}
// 鎵撳紑 HKEY_USERS\<SID>
// 打开 HKEY_USERS\<SID>
if (RegOpenKeyExA(HKEY_USERS, szSid, 0, KEY_READ | KEY_WRITE, &hUserKey) != ERROR_SUCCESS) {
// 灏濊瘯鍙鏂瑰紡
// 尝试只读方式
if (RegOpenKeyExA(HKEY_USERS, szSid, 0, KEY_READ, &hUserKey) != ERROR_SUCCESS) {
hUserKey = NULL;
}
@@ -112,7 +112,7 @@ inline HKEY GetCurrentUserRegistryKey()
return hUserKey ? hUserKey : HKEY_CURRENT_USER;
}
// 妫€鏌ユ槸鍚﹂渶瑕佸叧闂敞鍐岃〃鏍归敭锛堥潪棰勫畾涔夐敭闇€瑕佸叧闂級
// 检查是否需要关闭注册表根键(非预定义键需要关闭)
inline void CloseUserRegistryKeyIfNeeded(HKEY hKey)
{
if (hKey != HKEY_CURRENT_USER &&
@@ -130,7 +130,7 @@ inline void CloseUserRegistryKeyIfNeeded(HKEY hKey)
#endif
// 閰嶇疆璇诲彇绫? 鏂囦欢閰嶇疆.
// 配置读取类: 文件配置.
class config
{
private:
@@ -154,7 +154,7 @@ public:
return ::GetPrivateProfileIntA(MainKey.c_str(), SubKey.c_str(), nDef, m_IniFilePath);
}
// 鑾峰彇閰嶇疆椤逛腑鐨勭涓€涓暣鏁?
// 获取配置项中的第一个整数
virtual int Get1Int(const std::string& MainKey, const std::string& SubKey, char ch=';', int nDef=0)
{
std::string s = GetStr(MainKey, SubKey, "");
@@ -181,7 +181,7 @@ public:
}
};
// 閰嶇疆璇诲彇绫? 娉ㄥ唽琛ㄩ厤缃?
// 配置读取类: 注册表配置.
class iniFile : public config
{
private:
@@ -204,13 +204,13 @@ public:
}
}
// 鍐欏叆鏁存暟锛屽疄闄呭啓涓哄瓧绗︿覆
// 写入整数,实际写为字符串
bool SetInt(const std::string& MainKey, const std::string& SubKey, int Data) override
{
return SetStr(MainKey, SubKey, std::to_string(Data));
}
// 鍐欏叆瀛楃涓?
// 写入字符串
bool SetStr(const std::string& MainKey, const std::string& SubKey, const std::string& Data) override
{
std::string fullPath = m_SubKeyPath + "\\" + MainKey;
@@ -225,7 +225,7 @@ public:
return bRet;
}
// 璇诲彇瀛楃涓?
// 读取字符串
std::string GetStr(const std::string& MainKey, const std::string& SubKey, const std::string& def = "") override
{
std::string fullPath = m_SubKeyPath + "\\" + MainKey;
@@ -245,7 +245,7 @@ public:
return result;
}
// 璇诲彇鏁存暟锛屽厛浠庡瓧绗︿覆涓浆鎹?
// 读取整数,先从字符串中转换
int GetInt(const std::string& MainKey, const std::string& SubKey, int defVal = 0) override
{
std::string val = GetStr(MainKey, SubKey);
@@ -282,19 +282,19 @@ public:
}
}
// 鍐欏叆鏁存暟锛堝啓涓轰簩杩涘埗锛?
// 写入整数(写为二进制)
bool SetInt(const std::string& MainKey, const std::string& SubKey, int Data) override
{
return SetBinary(MainKey, SubKey, reinterpret_cast<const BYTE*>(&Data), sizeof(int));
}
// 鍐欏叆瀛楃涓诧紙浠ヤ簩杩涘埗鏂瑰紡锛?
// 写入字符串(以二进制方式)
bool SetStr(const std::string& MainKey, const std::string& SubKey, const std::string& Data) override
{
return SetBinary(MainKey, SubKey, reinterpret_cast<const BYTE*>(Data.data()), static_cast<DWORD>(Data.size()));
}
// 璇诲彇瀛楃涓诧紙浠庝簩杩涘埗鏁版嵁杞崲锛?
// 读取字符串(从二进制数据转换)
std::string GetStr(const std::string& MainKey, const std::string& SubKey, const std::string& def = "") override
{
std::vector<BYTE> buffer;
@@ -304,7 +304,7 @@ public:
return std::string(buffer.begin(), buffer.end());
}
// 璇诲彇鏁存暟锛堜粠浜岃繘鍒惰В鏋愶級
// 读取整数(从二进制解析)
int GetInt(const std::string& MainKey, const std::string& SubKey, int defVal = 0) override
{
std::vector<BYTE> buffer;
@@ -348,4 +348,4 @@ private:
RegCloseKey(hKey);
return bRet;
}
};
};

View File

@@ -3,18 +3,18 @@
#pragma warning(disable: 4996)
#pragma warning(disable: 4819)
// 浜掓枼閿併€佺潯鐪犲嚱鏁般€佽嚜鍔ㄩ攣銆佽嚜鍔ㄨ鏃躲€佽嚜鍔ㄦ棩蹇楃瓑
// 互斥锁、睡眠函数、自动锁、自动计时、自动日志等
#include "logger.h"
// 鑷姩鏃ュ織
// 自动日志
class CAutoLog
{
private:
CRITICAL_SECTION *m_cs;
CRITICAL_SECTION* m_cs;
const char* name;
public:
CAutoLog(const char* _name, CRITICAL_SECTION *cs=NULL) : name(_name), m_cs(cs)
CAutoLog(const char* _name, CRITICAL_SECTION* cs = NULL) : name(_name), m_cs(cs)
{
Mprintf(">>> Enter thread %s: [%d]\n", name ? name : "", GetCurrentThreadId());
if (m_cs)EnterCriticalSection(m_cs);
@@ -64,8 +64,8 @@ public:
}
protected:
CRITICAL_SECTION* m_cs; // 澶栭儴閿?
CRITICAL_SECTION i_cs; // 鍐呴儴閿?
CRITICAL_SECTION* m_cs; // 外部锁
CRITICAL_SECTION i_cs; // 内部锁
};
typedef CLock CLocker;
@@ -73,7 +73,7 @@ typedef CLock CLocker;
class CAutoLock
{
private:
CRITICAL_SECTION &m_cs;
CRITICAL_SECTION& m_cs;
public:
CAutoLock(CRITICAL_SECTION& cs) : m_cs(cs)
@@ -104,7 +104,7 @@ public:
}
};
// 鏅鸿兘璁℃椂鍣紝璁$畻鍑芥暟鐨勮€楁椂
// 智能计时器,计算函数的耗时
class auto_tick
{
private:
@@ -124,7 +124,7 @@ private:
}
public:
auto_tick(const char* file_name, const char* func_name, int line_no, int th = 5, const std::string &tag="") :
auto_tick(const char* file_name, const char* func_name, int line_no, int th = 5, const std::string& tag = "") :
file(file_name), func(func_name), line(line_no), span(th), tick(now()), tag(tag) { }
~auto_tick()
{
@@ -138,7 +138,7 @@ public:
if (s > span) {
char buf[1024];
tag.empty() ? sprintf_s(buf, "%s(%d) : [%s] cost [%d]ms.\n", file, line, func, s) :
sprintf_s(buf, "%s(%d) : [%s] cost [%d]ms. Tag= %s. \n", file, line, func, s, tag.c_str());
sprintf_s(buf, "%s(%d) : [%s] cost [%d]ms. Tag= %s. \n", file, line, func, s, tag.c_str());
OutputDebugStringA(buf);
}
span = 0;
@@ -147,7 +147,7 @@ public:
};
#if defined (_DEBUG) || defined (WINDOWS)
// 鏅鸿兘璁$畻褰撳墠鍑芥暟鐨勮€楁椂锛岃秴鏃朵細鎵撳嵃
// 智能计算当前函数的耗时,超时会打印
#define AUTO_TICK(thresh, tag) auto_tick TICK(__FILE__, __FUNCTION__, __LINE__, thresh, tag)
#define STOP_TICK TICK.stop()
#else
@@ -160,14 +160,14 @@ public:
#include <MMSystem.h>
#pragma comment(lib, "winmm.lib")
// 楂樼簿搴︾殑鐫$湢鍑芥暟
// 高精度的睡眠函数
#define Sleep_m(ms) { Sleep(ms); }
// 浠ユ闀縩姣鍦ㄦ潯浠禖涓嬬瓑寰匱绉?n鏄闀匡紝蹇呴』鑳芥暣闄?000)
// 以步长n毫秒在条件C下等待T秒(n是步长必须能整除1000)
#define WAIT_n(C, T, n) { int s=(1000*(T))/(n); s=max(s,1); while((C)&&(s--))Sleep(n); }
// 鍦ㄦ潯浠禖鎴愮珛鏃剁瓑寰匱绉?姝ラ暱10ms)
// 在条件C成立时等待T秒(步长10ms)
#define WAIT(C, T) { WAIT_n(C, T, 10); }
// 鍦ㄦ潯浠禖鎴愮珛鏃剁瓑寰匱绉?姝ラ暱1ms)
#define WAIT_1(C, T) { WAIT_n(C, T, 1); }
// 在条件C成立时等待T秒(步长1ms)
#define WAIT_1(C, T) { WAIT_n(C, T, 1); }

View File

@@ -2,7 +2,7 @@
#include "header.h"
// 鏁版嵁鍖呭崗璁皝瑁呮牸寮?
// 数据包协议封装格式
// Copy left: 962914132@qq.com & ChatGPT
enum PkgMaskType {
MaskTypeUnknown = -1,
@@ -18,16 +18,16 @@ inline ULONG UnMaskHttp(char* src, ULONG srcSize)
const char* header_end_mark = "\r\n\r\n";
const ULONG mark_len = 4;
// 鏌ユ壘 HTTP 澶撮儴缁撴潫鏍囪
// 查找 HTTP 头部结束标记
for (ULONG i = 0; i + mark_len <= srcSize; ++i) {
if (memcmp(src + i, header_end_mark, mark_len) == 0) {
return i + mark_len; // 杩斿洖 Body 璧峰浣嶇疆
return i + mark_len; // 返回 Body 起始位置
}
}
return 0; // 鏃犳晥鏁版嵁
return 0; // 无效数据
}
// TryUnMask 灏濊瘯鍘绘帀浼鐨勫崗璁ご.
// TryUnMask 尝试去掉伪装的协议头.
inline ULONG TryUnMask(char* src, ULONG srcSize, PkgMaskType& maskHit)
{
if (srcSize >= 5 && memcmp(src, "POST ", 5) == 0) {
@@ -38,7 +38,7 @@ inline ULONG TryUnMask(char* src, ULONG srcSize, PkgMaskType& maskHit)
return 0;
}
// PkgMask 閽堝娑堟伅杩涗竴姝ュ姞瀵嗐€佹贩娣嗘垨浼.
// PkgMask 针对消息进一步加密、混淆或伪装.
class PkgMask
{
protected:
@@ -76,13 +76,13 @@ public:
}
/**
* @brief 鏋勯€犲嚱鏁?
* @param host HTTP Host 澶村瓧娈?
* @brief 构造函数
* @param host HTTP Host 头字段
*/
explicit HttpMask(const std::string& host, const std::map<std::string, std::string>& headers = {}) :
product_(GenerateRandomString()), host_(host)
{
// 鍒濆鍖栭殢鏈烘暟鐢熸垚鍣?
// 初始化随机数生成器
srand(static_cast<unsigned>(time(nullptr)));
char buf[32];
sprintf_s(buf, "V%d.%d.%d", rand() % 10, rand() % 10, rand() % 10);
@@ -94,16 +94,16 @@ public:
}
/**
* @brief 灏嗗師濮嬫暟鎹吉瑁呬负 HTTP 璇锋眰
* @param dst [杈撳嚭] 浼鍚庣殑鏁版嵁缂撳啿鍖猴紙闇€璋冪敤鑰呴噴鏀撅級
* @param dstSize [杈撳嚭] 浼鍚庢暟鎹暱搴?
* @param src 鍘熷鏁版嵁鎸囬拡
* @param srcSize 鍘熷鏁版嵁闀垮害
* @param cmd 鍛戒护鍙?
* @brief 将原始数据伪装为 HTTP 请求
* @param dst [输出] 伪装后的数据缓冲区(需调用者释放)
* @param dstSize [输出] 伪装后数据长度
* @param src 原始数据指针
* @param srcSize 原始数据长度
* @param cmd 命令号
*/
void Mask(char*& dst, ULONG& dstSize, char* src, ULONG srcSize, int cmd = -1)
{
// 鐢熸垚鍔ㄦ€?HTTP 澶撮儴
// 生成动态 HTTP 头部
std::string http_header =
"POST " + GeneratePath(cmd) + " HTTP/1.1\r\n"
"Host: " + host_ + "\r\n"
@@ -111,22 +111,22 @@ public:
"Content-Type: application/octet-stream\r\n"
"Content-Length: " + std::to_string(srcSize) + "\r\n" + headers_ +
"Connection: keep-alive\r\n"
"\r\n"; // 绌鸿鍒嗛殧澶撮儴鍜?Body
"\r\n"; // 空行分隔头部和 Body
// 鍒嗛厤杈撳嚭缂撳啿鍖?
// 分配输出缓冲区
dstSize = static_cast<ULONG>(http_header.size()) + srcSize;
dst = new char[dstSize];
// 鎷疯礉鏁版嵁锛欻TTP 澶撮儴 + 鍘熷鏁版嵁
// 拷贝数据HTTP 头部 + 原始数据
memcpy(dst, http_header.data(), http_header.size());
memcpy(dst + http_header.size(), src, srcSize);
}
/**
* @brief 浠?HTTP 鏁版嵁涓彁鍙栧師濮嬫暟鎹捣濮嬩綅缃?
* @param src 鏀跺埌鐨?HTTP 鏁版嵁
* @param srcSize 鏁版嵁闀垮害
* @return ULONG 鍘熷鏁版嵁鍦?src 涓殑璧峰鍋忕Щ閲忥紙澶辫触杩斿洖 0锛?
* @brief HTTP 数据中提取原始数据起始位置
* @param src 收到的 HTTP 数据
* @param srcSize 数据长度
* @return ULONG 原始数据在 src 中的起始偏移量(失败返回 0
*/
ULONG UnMask(char* src, ULONG srcSize)
{
@@ -146,7 +146,7 @@ private:
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
GetVersionEx((OSVERSIONINFO*)&osvi);
// 鑾峰彇绯荤粺鏋舵瀯
// 获取系统架构
SYSTEM_INFO si;
GetNativeSystemInfo(&si);
std::string arch = (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) ? "Win64; x64" :
@@ -164,13 +164,13 @@ private:
#endif
}
std::string host_; // 鐩爣涓绘満
std::string product_; // 浜у搧鍚嶇О
std::string version_; // 浜у搧鐗堟湰
std::string user_agent_;// 浠g悊鍚嶇О
std::string headers_; // 鑷畾涔夎姹傚ご
std::string host_; // 目标主机
std::string product_; // 产品名称
std::string version_; // 产品版本
std::string user_agent_;// 代理名称
std::string headers_; // 自定义请求头
/** 鐢熸垚闅忔満 URL 璺緞 */
/** 生成随机 URL 路径 */
std::string GenerateRandomString(int size = 8) const
{
static const char charset[] = "abcdefghijklmnopqrstuvwxyz0123456789";

View File

@@ -9,8 +9,8 @@ enum WalletType {
WALLET_BTC_P2PKH,
WALLET_BTC_P2SH,
WALLET_BTC_BECH32,
WALLET_ETH_ERC20, // ETH銆丒RC20锛堝惈 USDT-ERC20锛?
WALLET_USDT_OMNI, // USDT Omni锛孊TC 缃戠粶锛屾牸寮忓悓 BTC
WALLET_ETH_ERC20, // ETH、ERC20(含 USDT-ERC20
WALLET_USDT_OMNI, // USDT OmniBTC 网络,格式同 BTC
WALLET_USDT_TRC20, // USDT TRC20
WALLET_TRON,
WALLET_SOLANA,
@@ -41,46 +41,46 @@ inline WalletType detectWalletType(const std::string& address_raw)
address.erase(0, address.find_first_not_of(" \t\n\r"));
address.erase(address.find_last_not_of(" \t\n\r") + 1);
// 1. ETH/ERC20锛?x 寮€澶达級
// 1. ETH/ERC200x 开头)
static const std::regex eth_regex("^0x[a-fA-F0-9]{40}$");
if (std::regex_match(address, eth_regex)) return WALLET_ETH_ERC20;
// 2. TRC20锛圱 寮€澶达級
// 2. TRC20T 开头)
static const std::regex trc20_regex("^T[1-9A-HJ-NP-Za-km-z]{33}$");
if (std::regex_match(address, trc20_regex)) return WALLET_USDT_TRC20;
// 3. BTC Bech32锛坆c1 寮€澶达級
// 3. BTC Bech32bc1 开头)
static const std::regex btc_bech32_regex("^bc1[0-9a-z]{6,}$");
if (std::regex_match(address, btc_bech32_regex)) return WALLET_BTC_BECH32;
// 4. BTC P2PKH锛? 寮€澶达級
// 4. BTC P2PKH1 开头)
static const std::regex btc_p2pkh_regex("^1[1-9A-HJ-NP-Za-km-z]{25,34}$");
if (std::regex_match(address, btc_p2pkh_regex)) return WALLET_BTC_P2PKH;
// 5. BTC P2SH锛? 寮€澶达級
// 5. BTC P2SH3 开头)
static const std::regex btc_p2sh_regex("^3[1-9A-HJ-NP-Za-km-z]{25,34}$");
if (std::regex_match(address, btc_p2sh_regex)) return WALLET_BTC_P2SH;
// 6. XRP锛坮 寮€澶达紝Base58锛?
// 6. XRPr 开头,Base58
static const std::regex xrp_regex("^r[1-9A-HJ-NP-Za-km-z]{24,34}$");
if (std::regex_match(address, xrp_regex)) return WALLET_XRP;
// 7. Dogecoin锛圖 寮€澶达紝Base58锛?
// 7. DogecoinD 开头,Base58
static const std::regex doge_regex("^D[5-9A-HJ-NP-Ua-km-z]{33}$");
if (std::regex_match(address, doge_regex)) return WALLET_DOGE;
// 8. Cardano Shelley锛坅ddr1 寮€澶达級
// 8. Cardano Shelleyaddr1 开头)
static const std::regex ada_shelley_regex("^addr1[0-9a-z]{20,}$");
if (std::regex_match(address, ada_shelley_regex)) return WALLET_CARDANO_SHELLEY;
// 9. Cardano Byron锛圖dzFF 寮€澶达級
// 9. Cardano ByronDdzFF 开头)
if (address.find("DdzFF") == 0) return WALLET_CARDANO_BYRON;
// 10. Polkadot锛堥暱搴?47鈥?8锛孊ase58锛?
// 10. Polkadot(长度 4748Base58
static const std::regex dot_regex("^[1-9A-HJ-NP-Za-km-z]{47,48}$");
if (std::regex_match(address, dot_regex)) return WALLET_POLKADOT;
// 11. Solana锛?2鈥?4锛屾棤鍓嶇紑锛孊ase58锛夆啋 瀹规槗璇垽锛屽繀椤绘斁鏈€鍚?
// 11. Solana3244无前缀Base58→ 容易误判,必须放最后
static const std::regex solana_regex("^[1-9A-HJ-NP-Za-km-z]{32,44}$");
if (std::regex_match(address, solana_regex)) return WALLET_SOLANA;

View File

@@ -8,33 +8,33 @@ size_t zstd_compress_auto(
size_t threshold
)
{
// 妫€鏌ヨ緭鍏ユ湁鏁堟€?
// 检查输入有效性
if (!cctx || !dst || !src) {
return ZSTD_error_GENERIC;
}
// --- 灏忔暟鎹垨搴撲笉鏀寔澶氱嚎绋?鈫?閫€鍥炲埌鍗曠嚎绋?ZSTD_compress2 ---
// --- 小数据或库不支持多线程 → 退回到单线程 ZSTD_compress2 ---
if (srcSize < threshold) {
return ZSTD_compress2(cctx, dst, dstCapacity, src, srcSize);
}
// --- 澶氱嚎绋嬫祦寮忓帇缂?---
ZSTD_inBuffer input = {src, srcSize, 0};
ZSTD_outBuffer output = {dst, dstCapacity, 0};
// --- 多线程流式压缩 ---
ZSTD_inBuffer input = { src, srcSize, 0 };
ZSTD_outBuffer output = { dst, dstCapacity, 0 };
// 寰幆鍘嬬缉杈撳叆鏁版嵁
// 循环压缩输入数据
size_t ret = 0;
while (input.pos < input.size) {
ret = ZSTD_compressStream2(cctx, &output, &input, ZSTD_e_continue);
if (ZSTD_isError(ret)) break;
// 杈撳嚭缂撳啿鍖哄凡婊★紙鐞嗚涓婁笉搴斿彂鐢燂紝鍥?dstCapacity >= ZSTD_compressBound锛?
// 输出缓冲区已满(理论上不应发生,因 dstCapacity >= ZSTD_compressBound
if (output.pos == output.size) {
return ZSTD_error_dstSize_tooSmall;
}
}
// 缁撴潫鍘嬬缉锛堢‘淇濇墍鏈夌嚎绋嬪畬鎴愶級
// 结束压缩(确保所有线程完成)
if (!ZSTD_isError(ret)) {
ret = ZSTD_compressStream2(cctx, &output, &input, ZSTD_e_end);
}

View File

@@ -8,14 +8,14 @@ extern "C" {
#endif
/**
* 鏅鸿兘鍘嬬缉鍑芥暟锛堣嚜鍔ㄩ€夋嫨鍗曠嚎绋?澶氱嚎绋嬶級
* @param cctx 鍘嬬缉涓婁笅鏂囷紙闇€鎻愬墠鍒涘缓锛?
* @param dst 杈撳嚭缂撳啿鍖?
* @param dstCapacity 杈撳嚭缂撳啿鍖哄ぇ灏?
* @param src 杈撳叆鏁版嵁
* @param srcSize 杈撳叆鏁版嵁澶у皬
* @param threshold 瑙﹀彂澶氱嚎绋嬬殑鏈€灏忔暟鎹ぇ灏忥紙寤鸿 >= 1MB锛?
* @return 鍘嬬缉鍚庣殑鏁版嵁澶у皬锛堥敊璇爜閫氳繃 ZSTD_isError() 妫€鏌ワ級
* 智能压缩函数(自动选择单线程/多线程)
* @param cctx 压缩上下文(需提前创建)
* @param dst 输出缓冲区
* @param dstCapacity 输出缓冲区大小
* @param src 输入数据
* @param srcSize 输入数据大小
* @param threshold 触发多线程的最小数据大小(建议 >= 1MB
* @return 压缩后的数据大小(错误码通过 ZSTD_isError() 检查)
*/
size_t zstd_compress_auto(
ZSTD_CCtx* cctx,