code_app/app/scanner/HGVersion.cpp

735 lines
21 KiB
C++

#include "HGVersion.h"
#include "base/HGDef.h"
#include "base/HGInc.h"
#include "base/HGInfo.h"
#include "base/HGMd5.h"
#include "cJSON.h"
#include "curl/curl.h"
#include <vector>
#include <iostream>
#include <sstream>
#include <algorithm>
#if defined(HG_CMP_MSC)
#include <iphlpapi.h>
#endif
bool GetServerConfig(ServerConfig& cfg)
{
return false;
}
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 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 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
ret = true;
/* then cleanup the formpost chain */
curl_formfree(formpost);
std::string str_json = out.str(); // 返回值
printf("%s\n", str_json.c_str());
cJSON *json = cJSON_Parse(str_json.c_str());
if (nullptr != json)
{
cJSON *p = json->child;
if (nullptr != p)
{
while (nullptr != p && 0 != strcmp(p->string, "code"))
p = p->next;
if (nullptr != p && 0 == strcmp(p->string, "code"))
{
cJSON *p2 = p->child;
if (nullptr != p2)
{
while (nullptr != p2 && 0 != strcmp(p2->string, "url"))
p2 = p->next;
if (nullptr != p2 && 0 == strcmp(p2->string, "url") && p2->type == cJSON_String)
{
crashFileUrl = p2->valuestring;
}
}
}
}
cJSON_Delete(json);
}
/* always cleanup */
curl_easy_cleanup(curl);
}
return ret;
}
static void GetMacAddrList(std::vector<std::string> &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 bool Greater(const std::string &str1, const std::string &str2)
{
return str1 > str2;
}
static bool PostCrashInfo(const std::string &crashFileUrl, const std::string &exceptionAddr, 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<std::string> 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];
sprintf(json, "{\"type\":%d, \"mac\":\"%s\", \"localid\":\"%s\", \"v\":\"%s\", \"ref\":\"%s\", \"desc\":\"%s\", \"crashaddress\":\"%s\", \"crash_data\":\"%s\"}",
3, macList[0].c_str(), md5Str, version.c_str(), source.c_str(), desc.c_str(), exceptionAddr.c_str(), crashFileUrl.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
ret = true;
curl_slist_free_all(headers);
std::string str_json = out.str(); // 返回值
printf("%s\n", str_json.c_str());
/* always cleanup */
curl_easy_cleanup(curl);
}
return ret;
}
bool PostCrashInfo(const std::string& crashFilePath, const std::string& exceptionAddr)
{
std::string crashFileUrl;
bool ret = CrashFileUpload(crashFilePath, crashFileUrl);
if (ret)
{
ret = PostCrashInfo(crashFileUrl, exceptionAddr, "collapse");
}
return ret;
}
bool PostUserHabits(const std::list<std::string>& habits)
{
return false;
}
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;
}
bool GetVersionInfoList(std::list<VersionInfo>& 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?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
ret = true;
curl_slist_free_all(headers);
std::string str_json = out.str(); // 返回值
printf("%s\n", str_json.c_str());
cJSON* json = cJSON_Parse(str_json.c_str());
if (nullptr != json)
{
cJSON* p = json->child;
if (nullptr != p)
{
while (nullptr != p && 0 != strcmp(p->string, "data"))
p = p->next;
if (nullptr != p && 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;
}
}
}
cJSON_Delete(json);
}
/* always cleanup */
curl_easy_cleanup(curl);
}
return ret;
}
static std::vector<std::string> split(std::string strtem, char a)
{
std::vector<std::string> 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;
}
int CompareVersion(const std::string& version1, const std::string& version2)
{
std::vector<std::string> versionList1 = split(version1, '.');
std::vector<std::string> 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;
}
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;
}