#include "HGVersion.h" #include "base/HGDef.h" #include "base/HGInc.h" #include "base/HGInfo.h" #include "base/HGMd5.h" #include "base/HGUtility.h" #include "cJSON.h" #include "curl/curl.h" #include #include #include #include #if defined(HG_CMP_MSC) #include #include #endif static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream) { std::string data((const char*) ptr, (size_t) size * nmemb); *((std::stringstream*) stream) << data << std::endl; return size * nmemb; } static bool GetServerConfig(bool &postCrashInfo, bool & postUserBehavior, bool &postDeviceInfo) { postCrashInfo = false; postUserBehavior = false; postDeviceInfo = false; bool ret = false; CURL* curl = curl_easy_init(); if (nullptr != curl) { std::stringstream out; std::string url = "http://up.appqy.com/api/ver/setting"; curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 2); curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); struct curl_slist* headers = nullptr; headers = curl_slist_append(headers, "Accept-Encoding:gzip, deflate, sdch"); headers = curl_slist_append(headers, "Accept-Language:zh-CN,zh;q=0.8"); headers = curl_slist_append(headers, "Connection:keep-alive"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_HTTPGET, 1); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &out); /* Perform the request, res will get the return code */ CURLcode res = curl_easy_perform(curl); /* Check for errors */ if (res != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s", curl_easy_strerror(res)); else { std::string str_json = out.str(); // 返回值 HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "str_json=%s", str_json.c_str()); cJSON* json = cJSON_Parse(str_json.c_str()); if (nullptr != json) { cJSON* p = json->child; while (nullptr != p) { if (0 == strcmp(p->string, "code") && p->type == cJSON_Number) { if (1 == p->valueint) ret = true; } else if (0 == strcmp(p->string, "data") && p->type == cJSON_Object) { cJSON* p2 = p->child; while (nullptr != p2) { if (0 == strcmp(p2->string, "report_switch")) postUserBehavior = (bool)p2->valueint; else if (0 == strcmp(p2->string, "collapse_switch")) postCrashInfo = (bool)p2->valueint; else if (0 == strcmp(p2->string, "device_info_switch")) postDeviceInfo = (bool)p2->valueint; p2 = p2->next; } } p = p->next; } cJSON_Delete(json); } } curl_slist_free_all(headers); /* always cleanup */ curl_easy_cleanup(curl); } return ret; } static int xferinfo(void* p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) { HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "ulnow=%lld, ultotal=%lld", ulnow, ultotal); return 0; } static bool CrashFileUpload(const std::string &filePath, std::string &crashFileUrl) { crashFileUrl.clear(); bool ret = false; CURL* curl = curl_easy_init(); if (nullptr != curl) { std::stringstream out; struct curl_httppost* formpost = nullptr; struct curl_httppost* lastptr = nullptr; curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "file", CURLFORM_FILE, filePath.c_str(), CURLFORM_END); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "submit", CURLFORM_COPYCONTENTS, "Submit", CURLFORM_END); std::string url = "http://up.appqy.com/api/coollapse/upload"; curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 2); curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xferinfo); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &out); /* Perform the request, res will get the return code */ CURLcode res = curl_easy_perform(curl); /* Check for errors */ if (res != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s", curl_easy_strerror(res)); else { std::string str_json = out.str(); // 返回值 HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "str_json=%s", str_json.c_str()); cJSON* json = cJSON_Parse(str_json.c_str()); if (nullptr != json) { cJSON* p = json->child; while (nullptr != p) { if (0 == strcmp(p->string, "code") && p->type == cJSON_Number) { if (1 == p->valueint) ret = true; } else if (0 == strcmp(p->string, "data") && p->type == cJSON_Object) { cJSON* p2 = p->child; while (nullptr != p2) { if (0 == strcmp(p2->string, "url") && p2->type == cJSON_String) crashFileUrl = p2->valuestring; p2 = p2->next; } } p = p->next; } cJSON_Delete(json); } } /* then cleanup the formpost chain */ curl_formfree(formpost); /* always cleanup */ curl_easy_cleanup(curl); } return ret; } static void GetMacAddrList(std::vector &macList) { macList.clear(); #if defined(HG_CMP_MSC) ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO); PIP_ADAPTER_INFO pAdapterInfo = (PIP_ADAPTER_INFO)malloc(ulOutBufLen); ULONG nRet = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen); if (ERROR_BUFFER_OVERFLOW == nRet) { free(pAdapterInfo); pAdapterInfo = nullptr; pAdapterInfo = (PIP_ADAPTER_INFO)malloc(ulOutBufLen); nRet = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen); } if (ERROR_SUCCESS == nRet) { PIP_ADAPTER_INFO pAdapter = pAdapterInfo; while (nullptr != pAdapter) { DWORD dwCharacteristics = 0; HKEY hKey = nullptr; RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}", 0, KEY_ENUMERATE_SUB_KEYS, &hKey); if (nullptr != hKey) { DWORD dwIndex = 0; while (1) { CHAR szValueName[256]; if (ERROR_SUCCESS != RegEnumKeyA(hKey, dwIndex, szValueName, 256)) { break; } HKEY hKey2 = nullptr; RegOpenKeyExA(hKey, szValueName, 0, KEY_QUERY_VALUE, &hKey2); if (nullptr != hKey2) { DWORD dwType; CHAR szData[256] = { 0 }; DWORD cbData = 256; if (ERROR_SUCCESS == RegQueryValueExA(hKey2, "NetCfgInstanceId", nullptr, &dwType, (LPBYTE)szData, &cbData) && REG_SZ == dwType) { if (0 == _stricmp(szData, pAdapter->AdapterName)) { if (ERROR_SUCCESS == RegQueryValueExA(hKey2, "Characteristics", nullptr, &dwType, (LPBYTE)szData, &cbData) && REG_DWORD == dwType) { dwCharacteristics = *(DWORD*)szData; } } } RegCloseKey(hKey2); } ++dwIndex; } RegCloseKey(hKey); } if ((dwCharacteristics & 0x4)) { std::string strMacAddr; for (UINT i = 0; i < pAdapter->AddressLength; i++) { char str[10]; sprintf(str, "%02x", pAdapter->Address[i]); strMacAddr += str; if (i != pAdapter->AddressLength - 1) strMacAddr += "-"; } macList.push_back(strMacAddr); } pAdapter = pAdapter->Next; } } free(pAdapterInfo); pAdapterInfo = nullptr; #else DIR *dir = opendir("/sys/class/net"); if (nullptr != dir) { printf("opendir success\n"); struct dirent *ent; while ((ent = readdir(dir)) != nullptr) { if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) continue; if (strstr(ent->d_name, "docker") == ent->d_name || strstr(ent->d_name, "sit") == ent->d_name || strstr(ent->d_name, "ip6tnl") == ent->d_name || strcmp(ent->d_name, "lo") == 0) continue; printf("name %s\n", ent->d_name); char addrPath[256]; sprintf(addrPath, "/sys/class/net/%s/address", ent->d_name); FILE *file = fopen(addrPath, "rb"); if (nullptr != file) { char mac[1025] = {0}; fread(mac, 1, 1024, file); int len = (int)strlen(mac); for (int i = 0; i < len; ++i) { if (mac[i] == ':') mac[i] = '-'; else if (mac[i] == '\n') mac[i] = '\0'; } if (strlen(mac) > 0) { macList.push_back(mac); } printf("mac %s\n", mac); fclose(file); } else { printf("fopen fail\n"); } } closedir(dir); } else { printf("opendir fail\n"); } #endif } static std::string GetCurrVersion() { std::string version = "0.0.0.0"; #if defined(HG_CMP_MSC) #if defined(OEM_HANWANG) std::string regName = "SOFTWARE\\HanvonScan"; #elif defined(OEM_LISICHENG) std::string regName = "SOFTWARE\\LanxumScan"; #else std::string regName = "SOFTWARE\\HuaGoScan"; #endif HKEY hKey = nullptr; RegOpenKeyExA(HKEY_LOCAL_MACHINE, regName.c_str(), 0, KEY_QUERY_VALUE, &hKey); if (nullptr != hKey) { CHAR szData[MAX_PATH] = { 0 }; DWORD cbData = MAX_PATH; if (ERROR_SUCCESS == RegQueryValueExA(hKey, "AppVersion", nullptr, nullptr, (LPBYTE)szData, &cbData)) { version = szData; } RegCloseKey(hKey); } #else #if defined(OEM_HANWANG) std::string appName = "com.hanvonchina.hanvonscan"; #elif defined(OEM_LISICHENG) std::string appName = "com.lanxumchina.lanxumscan"; #else std::string appName = "com.huagaochina.huagoscan"; #endif std::string cmd = "dpkg -l " + appName; FILE* fp = popen(cmd.c_str(), "r"); if (nullptr != fp) { char buff[2048] = { 0 }; fread(buff, 2048, 1, fp); char* p = strstr(buff, appName.c_str()); if (nullptr != p) { char* p2 = p + appName.size(); while (!isdigit(*p2) && '.' != *p2) ++p2; int len = (int)strlen(p2); for (int i = 0; i < len; ++i) { if (!isdigit(p2[i]) && '.' != p2[i]) { p2[i] = '\0'; break; } } version = p2; } pclose(fp); } #endif return version; } static bool Greater(const std::string &str1, const std::string &str2) { return str1 > str2; } static bool PostInfo(int type, const std::string &crashFileUrl, const std::string &exceptionAddr, const std::string &feedbackInfo, const std::string &feedbackContact, const std::string &desc) { bool ret = false; CURL* curl = curl_easy_init(); if (nullptr != curl) { std::stringstream out; std::string url = "http://up.appqy.com/api/recode"; curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 2); curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); std::vector macList; GetMacAddrList(macList); if (macList.empty()) macList.push_back("00-00-00-00-00-00"); std::sort(macList.begin(), macList.end(), Greater); std::string strMacAddrTotal; for (int i = 0; i < (int)macList.size(); ++i) { strMacAddrTotal += macList[i]; } HGByte md5[16] = {0}; HGBase_MakeMd5((const HGByte *)strMacAddrTotal.c_str(), strMacAddrTotal.size(), md5); char md5Str[64] = {0}; char *pstr = md5Str; for (int i = 0; i < 16; ++i) { sprintf(pstr, "%02x", md5[i]); pstr += 2; } std::string version = GetCurrVersion(); std::string osName, archName, oemName; #if defined(HG_CMP_MSC) osName = "Windows"; archName = "unknown"; SYSTEM_INFO si; GetNativeSystemInfo(&si); if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) archName = "x64"; else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) archName = "x86"; #else osName = "Linux"; archName = "unknown"; FILE *fp = popen("cat /etc/issue | cut -d\' \' -f1", "r"); if (nullptr != fp) { char buff[1024] = {0}; fread(buff, 1024, 1, fp); int len = (int)strlen(buff); for (int i = 0; i < len; ++i) { if (buff[i] == '\n') buff[i] = '\0'; } osName = buff; pclose(fp); } fp = popen("arch", "r"); if (nullptr != fp) { char buff[1024] = {0}; fread(buff, 1024, 1, fp); int len = (int)strlen(buff); for (int i = 0; i < len; ++i) { if (buff[i] == '\n') buff[i] = '\0'; } archName = buff; pclose(fp); } #endif #if defined(OEM_HANWANG) oemName = "Hanvon"; #elif defined(OEM_LISICHENG) oemName = "Lanxum"; #else oemName = "Huago"; #endif std::string source = osName + "-" + archName + "-" + oemName; char json[1024]; if (3 == type) { sprintf(json, "{\"type\":%d, \"mac\":\"%s\", \"localid\":\"%s\", \"v\":\"%s\", \"ref\":\"%s\", \"desc\":\"%s\", \"crashaddress\":\"%s\", \"crash_data\":\"%s\"}", type, macList[0].c_str(), md5Str, version.c_str(), source.c_str(), desc.c_str(), exceptionAddr.c_str(), crashFileUrl.c_str()); } else { assert(4 == type); sprintf(json, "{\"type\":%d, \"mac\":\"%s\", \"localid\":\"%s\", \"v\":\"%s\", \"ref\":\"%s\", \"desc\":\"%s\", \"content\":\"%s\", \"contact\":\"%s\"}", type, macList[0].c_str(), md5Str, version.c_str(), source.c_str(), desc.c_str(), feedbackInfo.c_str(), feedbackContact.c_str()); } struct curl_slist* headers = nullptr; headers = curl_slist_append(headers, "Content-Type:application/json;charset=UTF-8"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_POST, 1); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &out); /* Perform the request, res will get the return code */ CURLcode res = curl_easy_perform(curl); /* Check for errors */ if (res != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s", curl_easy_strerror(res)); else { std::string str_json = out.str(); // 返回值 HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "str_json=%s", str_json.c_str()); cJSON* json = cJSON_Parse(str_json.c_str()); if (nullptr != json) { cJSON* p = json->child; while (nullptr != p) { if (0 == strcmp(p->string, "code") && p->type == cJSON_Number) { if (1 == p->valueint) ret = true; } p = p->next; } cJSON_Delete(json); } } curl_slist_free_all(headers); /* always cleanup */ curl_easy_cleanup(curl); } return ret; } static bool PostCrashInfo(const std::string& crashFilePath, const std::string& exceptionAddr) { std::string crashFileUrl; bool ret = CrashFileUpload(crashFilePath, crashFileUrl); if (ret && !crashFileUrl.empty()) { ret = PostInfo(3, crashFileUrl, exceptionAddr, "", "", "collapse"); } return ret; } static bool PostUserFeedback(const std::string &info, const std::string &contact) { return PostInfo(4, "", "", info, contact, "feedback"); } static bool GetVersionInfoList(std::list& versionList) { versionList.clear(); bool ret = false; CURL* curl = curl_easy_init(); if (nullptr != curl) { std::stringstream out; std::string osName, archName, oemName; #if defined(HG_CMP_MSC) osName = "Windows"; #ifdef _WIN64 archName = "x64"; #else archName = "x86"; #endif #else osName = "Linux"; archName = "unknown"; FILE *fp = popen("cat /etc/issue | cut -d\' \' -f1", "r"); if (nullptr != fp) { char buff[1024] = {0}; fread(buff, 1024, 1, fp); int len = (int)strlen(buff); for (int i = 0; i < len; ++i) { if (buff[i] == '\n') buff[i] = '\0'; } osName = buff; pclose(fp); } fp = popen("arch", "r"); if (nullptr != fp) { char buff[1024] = {0}; fread(buff, 1024, 1, fp); int len = (int)strlen(buff); for (int i = 0; i < len; ++i) { if (buff[i] == '\n') buff[i] = '\0'; } archName = buff; pclose(fp); } #endif #if defined(OEM_HANWANG) oemName = "Hanvon"; #elif defined(OEM_LISICHENG) oemName = "Lanxum"; #else oemName = "Huago"; #endif std::string url = "http://up.appqy.com/api/ver?app=Scanner&oem=" + oemName + "&cpu=" + archName + "&sys=" + osName; curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 2); curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); struct curl_slist* headers = nullptr; headers = curl_slist_append(headers, "Accept-Encoding:gzip, deflate, sdch"); headers = curl_slist_append(headers, "Accept-Language:zh-CN,zh;q=0.8"); headers = curl_slist_append(headers, "Connection:keep-alive"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_HTTPGET, 1); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &out); /* Perform the request, res will get the return code */ CURLcode res = curl_easy_perform(curl); /* Check for errors */ if (res != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s", curl_easy_strerror(res)); else { std::string str_json = out.str(); // 返回值 HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "str_json=%s", str_json.c_str()); cJSON* json = cJSON_Parse(str_json.c_str()); if (nullptr != json) { cJSON* p = json->child; while (nullptr != p) { if (0 == strcmp(p->string, "code") && p->type == cJSON_Number) { if (1 == p->valueint) ret = true; } else if (0 == strcmp(p->string, "data") && p->type == cJSON_Array) { cJSON* p2 = p->child; while (nullptr != p2) { VersionInfo version; cJSON* p3 = p2->child; while (nullptr != p3) { if (0 == strcmp(p3->string, "full") && p3->type == cJSON_String) version.url = p3->valuestring; else if (0 == strcmp(p3->string, "size") && p3->type == cJSON_String) version.size = atoi(p3->valuestring); else if (0 == strcmp(p3->string, "desc") && p3->type == cJSON_String) version.desc = p3->valuestring; else if (0 == strcmp(p3->string, "bug") && p3->type == cJSON_String) version.bugInfo = p3->valuestring; else if (0 == strcmp(p3->string, "md5") && p3->type == cJSON_String) version.md5 = p3->valuestring; else if (0 == strcmp(p3->string, "v") && p3->type == cJSON_String) version.version = p3->valuestring; p3 = p3->next; } versionList.push_back(version); p2 = p2->next; } } p = p->next; } cJSON_Delete(json); } } curl_slist_free_all(headers); /* always cleanup */ curl_easy_cleanup(curl); } return ret; } static std::vector split(std::string strtem, char a) { std::vector strvec; std::string::size_type pos1, pos2; pos2 = strtem.find(a); pos1 = 0; while (std::string::npos != pos2) { strvec.push_back(strtem.substr(pos1, pos2 - pos1)); pos1 = pos2 + 1; pos2 = strtem.find(a, pos1); } strvec.push_back(strtem.substr(pos1)); return strvec; } static int CompareVersion(const std::string& version1, const std::string& version2) { std::vector versionList1 = split(version1, '.'); std::vector versionList2 = split(version2, '.'); int size1 = versionList1.size(); int size2 = versionList2.size(); int i = 0; while (i < size1 && i < size2) { if (atoi(versionList1[i].c_str()) < atoi(versionList2[i].c_str())) { return -1; } else if (atoi(versionList1[i].c_str()) > atoi(versionList2[i].c_str())) { return 1; } ++i; } if (i == size1 && i < size2) return -1; else if (i < size1 && i == size2) return 1; assert(i == size1 && i == size2); return 0; } static size_t curlWriteFunction(void *ptr, size_t size, size_t nmemb, FILE *stream) { return fwrite(ptr, size, nmemb, stream); } struct myprogress { HttpDownloadFunc func; void* param; }; static int xferinfo2(void* p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) { HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "ulnow=%lld, ultotal=%lld", ulnow, ultotal); struct myprogress *myp = (struct myprogress *)p; if (nullptr != myp->func) return myp->func(dltotal, dlnow, myp->param); return 0; } static bool HttpDownload(const std::string& url, const std::string& saveFilePath, HttpDownloadFunc func, void* param) { bool ret = false; CURL* curl = curl_easy_init(); if (nullptr != curl) { FILE *fp = fopen(saveFilePath.c_str(), "wb"); // 打开文件,准备写入 if (nullptr != fp) { curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 2); curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlWriteFunction); struct myprogress prog; prog.func = func; prog.param = param; curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &prog); curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xferinfo2); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); /* Perform the request, res will get the return code */ CURLcode res = curl_easy_perform(curl); /* Check for errors */ if (res != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s", curl_easy_strerror(res)); else ret = true; fclose(fp); } curl_easy_cleanup(curl); } return ret; } // HGVersion Class #if defined(HG_CMP_MSC) static LONG WINAPI UnhandledExceptionFilterEx(struct _EXCEPTION_POINTERS* ExceptionInfo) { HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "Unhandled Exception!!!"); HGChar tmpPath[256]; HGBase_GetTmpFileName("dmp", tmpPath, 256); HANDLE hFile = CreateFileA(tmpPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hFile) { return EXCEPTION_EXECUTE_HANDLER; } MINIDUMP_EXCEPTION_INFORMATION mdei; mdei.ThreadId = GetCurrentThreadId(); mdei.ExceptionPointers = ExceptionInfo; mdei.ClientPointers = TRUE; MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &mdei, NULL, NULL); CloseHandle(hFile); char exceptionAddr[32] = { 0 }; #ifdef _WIN64 sprintf(exceptionAddr, "0x%016p", ExceptionInfo->ExceptionRecord->ExceptionAddress); #else sprintf(exceptionAddr, "0x%08p", ExceptionInfo->ExceptionRecord->ExceptionAddress); #endif // 上传 ::PostCrashInfo(tmpPath, exceptionAddr); HGBase_DeleteFile(tmpPath); return EXCEPTION_EXECUTE_HANDLER; } #endif HGVersion::HGVersion() { m_isPostCrashInfo = false; m_isPostUserBehavior = false; m_isPostDeviceInfo = false; m_thread = nullptr; curl_global_init(CURL_GLOBAL_ALL); GetServerConfig(m_isPostCrashInfo, m_isPostUserBehavior, m_isPostDeviceInfo); if (m_isPostCrashInfo) { #if defined(HG_CMP_MSC) SetUnhandledExceptionFilter(UnhandledExceptionFilterEx); #endif } } HGVersion::~HGVersion() { curl_global_cleanup(); } bool HGVersion::IsPostUserBehavior() { return m_isPostUserBehavior; } bool HGVersion::IsPostDeviceInfo() { return m_isPostDeviceInfo; } bool HGVersion::PostUserFeedback(const std::string& info, const std::string& contact) { return ::PostUserFeedback(info, contact); } std::string HGVersion::GetCurrVersion() { return ::GetCurrVersion(); } bool HGVersion::GetVersionInfoList(std::list& versionList) { return ::GetVersionInfoList(versionList); } int HGVersion::CompareVersion(const std::string& version1, const std::string& version2) { return ::CompareVersion(version1, version2); } bool HGVersion::HttpDownload(const std::string& url, const std::string& saveFilePath, HttpDownloadFunc func, void* param) { return ::HttpDownload(url, saveFilePath, func, param); }