601 lines
17 KiB
C++
601 lines
17 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();
|
|
|
|
curl_global_init(CURL_GLOBAL_ALL);
|
|
|
|
bool ret = false;
|
|
CURL* curl = curl_easy_init();
|
|
if (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);
|
|
}
|
|
|
|
curl_global_cleanup();
|
|
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 &desc)
|
|
{
|
|
curl_global_init(CURL_GLOBAL_ALL);
|
|
|
|
bool ret = false;
|
|
CURL* curl = curl_easy_init();
|
|
if (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(), "0x00000000", 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);
|
|
}
|
|
|
|
curl_global_cleanup();
|
|
return ret;
|
|
}
|
|
|
|
bool PostCrashInfo(const char* crashFilePath)
|
|
{
|
|
std::string crashFileUrl;
|
|
bool ret = CrashFileUpload(crashFilePath, crashFileUrl);
|
|
if (ret)
|
|
{
|
|
ret = PostCrashInfo(crashFileUrl, "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)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
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 char* url, const char* saveFilePath, HttpDownloadFunc func, void* param)
|
|
{
|
|
curl_global_init(CURL_GLOBAL_ALL);
|
|
|
|
bool ret = false;
|
|
CURL* curl = curl_easy_init();
|
|
if (curl)
|
|
{
|
|
FILE *fp = fopen(saveFilePath, "wb"); // 打开文件,准备写入
|
|
if (nullptr != fp)
|
|
{
|
|
curl_easy_setopt(curl, CURLOPT_URL, url);
|
|
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;
|
|
}
|