#include "Licensed.h" #include "MD5.h" #include #include #include #include #include #include #ifdef _WIN32 #include #include #elif __linux__ #include #elif __APPLE__ #include #endif #include "Token.h" Licensed* g_licensed = nullptr; Licensed::Licensed() { assert(nullptr == g_licensed); g_licensed = this; } Licensed::~Licensed() { assert(nullptr != g_licensed); g_licensed = nullptr; } Licensed& Licensed::Instance() { // TODO: insert return statement here return *g_licensed; } const std::string Licensed::GetKey(void) const { char pCpuId[32] = ""; // GetCpuId(pCpuId, 0); // cout << "origin " << pCpuId << endl; char pCpuIded[32] = ""; // int rad = RAND(0, 9); GetCpuId(pCpuIded, 1); std::string hardDiskId = GetHardDiskID(); std::string res = AddString(pCpuIded, hardDiskId); MD5 md5(res); res = md5.toStr(); return res; } bool Licensed::Valid(const std::string& str) const { const char* data = str.data(); char sz[5] = {0}; memcpy_s(sz, 5, data, 4); int nrand = 0; sscanf_s(sz, "%04X", &nrand); char pCpuIded[32] = ""; GetCpuId(pCpuIded, nrand); MD5 md5(pCpuIded); std::string strCpuid = md5.toStr(); std::string subStr = str.substr(4); return 0 == strCpuid.compare(subStr); } std::string Licensed::Generated(const std::string& key) const { const char* data = key.data(); char sz[5] = { 0 }; memcpy_s(sz, 5, data, 4); int nrand = 0; sscanf_s(sz, "%04X", &nrand); char pCpuIded[32] = ""; GetCpuId(pCpuIded, nrand); std::string subStr = key.substr(4); MD5 md5(subStr); return key.substr(0, 4) + md5.toStr(); } bool Licensed::GeneratedKeyToFile(const std::string& key, const std::string& path) { std::ofstream out(path); if (!out.is_open()) { return false; } out << key <> key ; return Valid(key); return true; } bool Licensed::CheckValid() { Token token = Token::FromConfig(); if (!token.IsValide()) { return true; } const std::string key = GetKey(); if (key != token.GetToken()) { return false; } switch (token.GetCode()) { case Token::CodeType::None: case Token::CodeType::Close: return false; default: break; } return true; } void Licensed::UpdateToken() { const std::string key = GetKey(); Token token = Token::FromServer(key); if (!token.IsValide()) { return; } token.SaveConfig(); } void Licensed::UpdateGetTokenCount(bool success) { if (success) { m_count = 0; return; } if (++m_count > 10) { Token token = Token::FromConfig(); if (!token.IsValide()) { const std::string key = GetKey(); token = Token(key); } token.SetCode(Token::CodeType::Close); token.SaveConfig(); } } void Licensed::GetCpuId(unsigned int CPUInfo[4], unsigned int InfoType) const { #if defined(__GNUC__)// GCC __cpuid(InfoType, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]); #elif defined(_MSC_VER)// MSVC #if _MSC_VER >= 1400 //VC2005才支持__cpuid __cpuid((int*)(void*)CPUInfo, (int)(InfoType)); #else //其他使用getcpuidex getcpuidex(CPUInfo, InfoType, 0); #endif #endif } char* Licensed::GetCpuId(char* pCpuId, int rom) const { int dwBuf[4] = { 0 }; GetCpuId((unsigned int *)dwBuf, 1); sprintf_s(pCpuId, 9, "%08X", dwBuf[3] + rom); sprintf_s(pCpuId + 8, 22, "%08X", dwBuf[0] + rom); return pCpuId; } std::string Licensed::GetHardDiskID() const { std::string hardDiskSerialNumber = "hardDiskSerialNumber"; return hardDiskSerialNumber; #ifdef _WIN32 // 使用Windows API获取硬盘信息 DWORD volumeSerialNumber; GetVolumeInformation("C:\\", nullptr, 0, &volumeSerialNumber, nullptr, nullptr, nullptr, 0); hardDiskSerialNumber = std::to_string(volumeSerialNumber); #elif __linux__ // 使用Linux特定命令获取硬盘信息 char buffer[256]; FILE* fp = popen("lsblk -d -n -o serial /dev/sda", "r"); if (fp != nullptr) { fgets(buffer, sizeof(buffer), fp); pclose(fp); hardDiskSerialNumber = buffer; } #elif __APPLE__ // 使用macOS特定API获取硬盘信息 char buffer[256]; FILE* fp = popen("system_profiler SPNVMeDataType | grep 'Serial Number:' | awk '{print $NF}'", "r"); if (fp != nullptr) { fgets(buffer, sizeof(buffer), fp); pclose(fp); hardDiskSerialNumber = buffer; } #endif return hardDiskSerialNumber; } std::string Licensed::AddString(const std::string& a, const std::string& b) const { std::size_t len = min(a.length(), b.length()); std::string res = a.length() > b.length() ? a : b; for (int i = 0; i < len; ++i) { res[i] = a[i] + b[i]; } return res; } std::string Licensed::GetKeyFromLocalFile() const { /* char appDataPath[MAX_PATH]; if (SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, appDataPath) != S_OK) { std::cout << "获取 AppData 目录路径失败" << std::endl; return ""; } std::ifstream in(std::string(appDataPath) + LICENSED_FILE_NAME, std::ios::in); if (!in.is_open()) { return ""; }*/ return ""; } void Licensed::GetCpuIdex(unsigned int CPUInfo[4], unsigned int InfoType, unsigned int ECXValue) const { #if defined(_MSC_VER) // MSVC #if defined(_WIN64) // 64位下不支持内联汇编. 1600: VS2010, 据说VC2008 SP1之后才支持__cpuidex. __cpuidex((int*)(void*)CPUInfo, (int)InfoType, (int)ECXValue); #else if (NULL == CPUInfo) return; _asm { // load. 读取参数到寄存器. mov edi, CPUInfo; mov eax, InfoType; mov ecx, ECXValue; // CPUID cpuid; // save. 将寄存器保存到CPUInfo mov[edi], eax; mov[edi + 4], ebx; mov[edi + 8], ecx; mov[edi + 12], edx; } #endif #endif }