/************************************************************************* * * DeepCam CONFIDENTIAL * FILE: face-detector-tracker.py * * [2016] - [2017] DeepCam, LLC and DeepCam NOTICE: * All information contained herein is, and remains the property of DeepCam LLC. * The intellectual and technical concepts contained herein are proprietary to DeepCam * and may be covered by U.S. and Foreign Patents,patents in process, and are protected by * trade secret or copyright law. * Dissemination of this information or reproduction of this material * is strictly forbidden unless prior written permission is obtained * DeepCam, LLC. * * * Written: Delong Qi * Date: 08/11/2017 * Mail: delong.qi@deepcam.com */ #include "Request.h" #include "openssl\aes.h" #include "openssl\rand.h" #include #include #include using namespace std; /* //获取当前时间的字符串,格式固定,用于做上传到服务器的参数,格式:"%04d-%02d-%02d %02d:%02d:%02d.%d" int _getTimestampFormatString(char * strTime) { SYSTEMTIME wtm; GetLocalTime(&wtm); if (strTime) { sprintf_s(strTime, 128, "%04d-%02d-%02d %02d:%02d:%02d.%03d", wtm.wYear, wtm.wMonth, wtm.wDay, wtm.wHour, wtm.wMinute, wtm.wSecond, wtm.wMilliseconds); } return (wtm.wSecond * 1000 + wtm.wMilliseconds); } //获取当前时间的字符串,格式自定义,用于做文件名或其它用途。 int _getTimeString(char * strTime) { SYSTEMTIME wtm; GetLocalTime(&wtm); if (strTime) { sprintf_s(strTime, 128, "%04d-%02d-%02d_%02d-%02d-%02d-%03d", wtm.wYear, wtm.wMonth, wtm.wDay, wtm.wHour, wtm.wMinute, wtm.wSecond, wtm.wMilliseconds); } return (wtm.wSecond * 1000 + wtm.wMilliseconds); } */ #pragma region AES_IMPL #define AES128_KEYLEN 16 //128 Bits #define AES192_KEYLEN 24 //192 Bits #define AES256_KEYLEN 32 //256 Bits //加密普通文本字串,加密后返回加密二进制的十六进制字串。 bool Encrypt_AES_CBC(string & key, string & srcData, string & encryptData) { int keyLen = key.length(); int aesKeyLen = keyLen; if (keyLen > AES192_KEYLEN) { aesKeyLen = AES256_KEYLEN; } else if (keyLen > AES128_KEYLEN && keyLen <= AES192_KEYLEN) { aesKeyLen = AES192_KEYLEN; } else if (keyLen > 0 && keyLen <= AES128_KEYLEN) { aesKeyLen = AES128_KEYLEN; } else { //LOGGER_ERROR("Input key length is error ."); printf("Input key length is error .\n"); return false; } if (srcData.length() < 1) { //LOGGER_ERROR("Input lenth error - SrcData:" << srcData.c_str()); printf("Input lenth error ...\n"); return false; } char tempKey[AES256_KEYLEN + 1] = {0}; strncpy_s(tempKey, AES256_KEYLEN + 1, key.c_str(), keyLen); tempKey[keyLen] = '\0'; char IV[AES_BLOCK_SIZE + 1] = { 0 }; strncpy_s(IV, AES_BLOCK_SIZE + 1, tempKey, AES_BLOCK_SIZE); int dataLen = ((srcData.length() + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE)*AES_BLOCK_SIZE; vector tempSrcData; vector tempEncryptData; AES_KEY AesKey; tempSrcData.resize(dataLen+1, '\0'); tempEncryptData.resize(dataLen+1, '\0'); strcpy_s(tempSrcData.data(), dataLen+1, srcData.c_str()); //set encryption key if (AES_set_encrypt_key((const unsigned char *)tempKey, aesKeyLen*8, &AesKey)<0) { //LOGGER_ERROR("Unable to set encryption key in AES..."); printf("Unable to set encryption key in AES...\n"); return false; } //encryption AES_cbc_encrypt((const unsigned char *)tempSrcData.data(), (unsigned char *)tempEncryptData.data(), dataLen, &AesKey, (unsigned char *)IV, AES_ENCRYPT); encryptData = string(""); for (int i = 0; i < dataLen; i++) { char tempBuf[3] = { 0 }; sprintf_s(tempBuf, 3, "%02x",(BYTE)tempEncryptData[i]); encryptData += tempBuf; } return true; } //解密十六进制的密文字串,返回加密之前的普通文本字串。 bool Decrypt_AES_CBC(string & key, string & srcData, string & decryptData) { int keyLen = key.length(); int aesKeyLen = keyLen; if (keyLen > AES192_KEYLEN) { aesKeyLen = AES256_KEYLEN; } else if (keyLen > AES128_KEYLEN && keyLen <= AES192_KEYLEN) { aesKeyLen = AES192_KEYLEN; } else if (keyLen > 0 && keyLen <= AES128_KEYLEN) { aesKeyLen = AES128_KEYLEN; } else { //LOGGER_ERROR("Input key length is error ."); printf("Input key length is error .\n"); return false; } if ((srcData.length() / AES_BLOCK_SIZE < 1) || (srcData.length() % AES_BLOCK_SIZE != 0)) { //LOGGER_ERROR("Input lenth error - SrcData:" << srcData.c_str()); printf("Input lenth error ...\n"); return false; } char tempKey[AES256_KEYLEN + 1] = {0}; strncpy_s(tempKey, AES256_KEYLEN + 1, key.c_str(), keyLen); tempKey[keyLen] = '\0'; char IV[AES_BLOCK_SIZE + 1] = { 0 }; strncpy_s(IV, AES_BLOCK_SIZE + 1, tempKey, AES_BLOCK_SIZE); int dataLen = srcData.length()/2; //Hex string to byte data vector tempSrcData; tempSrcData.resize(dataLen, '\0'); char * pstr = (char *)srcData.c_str(); for (int i = 0; i < dataLen; i++) { UINT tempValue = 0; sscanf_s(pstr + i * 2, "%02x", &tempValue); tempSrcData[i] = (byte)tempValue; } vector tempDecryptData; AES_KEY AesKey; tempDecryptData.resize(dataLen+1, '\0'); //set encryption key if (AES_set_decrypt_key((const unsigned char *)tempKey, aesKeyLen * 8, &AesKey)<0) { //LOGGER_ERROR("Unable to set encryption key in AES..."); printf("Unable to set encryption key in AES...\n"); return false; } //encryption AES_cbc_encrypt((const unsigned char *)tempSrcData.data(), (unsigned char *)tempDecryptData.data(), dataLen, &AesKey, (unsigned char *)IV, AES_DECRYPT); decryptData = string(tempDecryptData.data()); return true; } bool IsPathExist(const string & strPath) { int nRet = _access(strPath.c_str(), 0); return 0 == nRet || EACCES == nRet; } bool FileRename(const std::string &OldName, const std::string &NewName) { return (::MoveFileA(OldName.c_str(), NewName.c_str()) != FALSE); } /*函数名称:EncryFileEx *参数名称:filename --文件的全路径 *参数名称:drcfilename --输出文件的全路径 *功能说明:采用Aes加密算法加密文件内容 */ /* int EncryptFileEx(std::string filename) { int ires = 0; AES_KEY aes_key; unsigned char key[16] = { 0 }; unsigned char inbuf[16] = { 0 }; unsigned char outbuf[16] = { 0 }; unsigned char szHeader[256] = { 0 }; //create the rand key RAND_bytes(szHeader, 256); memcpy_s(key, 16, szHeader + 100, 16); FILE *pFile = nullptr; fopen_s(&pFile, filename.c_str(), "rb"); if (!pFile) { ires = 1; return ires; } //char *pBuf; fseek(pFile, 0, SEEK_END); int len = ftell(pFile); rewind(pFile); if (AES_set_encrypt_key(key, 128, &aes_key) == 0)//set encrpt key { std::string newfile = filename; newfile += "1"; ULONG count = len % 16 == 0 ? len / 16 : len / 16 + 1; memcpy_s(inbuf, 16, &len, sizeof(ULONG)); AES_encrypt(inbuf, outbuf, &aes_key); //put the file size at the first 16 bytes of szHeader memcpy_s(szHeader, 16, outbuf, 16); FILE *nf = nullptr; fopen_s(&nf, newfile.c_str(), "wb+"); if (!nf) { ires = 4; } else { //put szHeader at the first 256 bytes of file fwrite(szHeader, 1, 256, nf); for (ULONG k = 0; k < count; k++) { SecureZeroMemory(inbuf, 16); SecureZeroMemory(outbuf, 16); if (0 < fread(inbuf, 1, 16, pFile)) { AES_encrypt(inbuf, outbuf, &aes_key); fwrite(outbuf, 1, 16, nf); } } fclose(nf); } fclose(pFile); DeleteFileA(filename.c_str()); FileRename(newfile, filename); } else { fclose(pFile); } return ires; } */ /* *函数名称:DecryFileEx *参数名称:filename --文件的全路径 *参数名称:drcfilename --输出文件的全路径 *功能说明:采用Aes解密算法加密文件内容 */ /* int DecryptFileEx(std::string filename, bool bToTmpFile) { int ires = 0; AES_KEY aes_key; long long last, lastlen = 0; unsigned char key[16] = { 0 }; unsigned char inbuf[16] = { 0 }; unsigned char outbuf[16] = { 0 }; unsigned char szHeader[256] = { 0 }; FILE *pFile = nullptr; fopen_s(&pFile, filename.c_str(), "rb"); if (!pFile) { ires = 1; return ires; } //char *pBuf; fseek(pFile, 0, SEEK_END); //point the file end int len = ftell(pFile); rewind(pFile); //count the decrpt times of file ULONG count = (len - 256) / 16; if (count <= 0) { fclose(pFile); ires = 2; return ires; } //get key from file if (0 == fread(szHeader, 1, 256, pFile)) { fclose(pFile); ires = 2; return ires; } memcpy_s(key, 16, szHeader + 100, 16); //start to decrpt file if (AES_set_decrypt_key(key, 128, &aes_key) == 0)//set decrypt key { //computer the file size before encrpt memcpy_s(inbuf, 16, szHeader, 16); AES_decrypt(inbuf, outbuf, &aes_key); memcpy_s(&lastlen, sizeof(ULONG), outbuf, sizeof(ULONG)); last = lastlen % 16; //the part less 16 bytes before encprt //check file if the file is able to be decrpted or not bool ret = last == 0 ? lastlen == len - 256 : lastlen + 16 - last == len - 256; if (!ret) { fclose(pFile); ires = 3; return ires; } std::string newfile = filename; newfile += "1"; //create temp file FILE *nf = nullptr; fopen_s(&nf, newfile.c_str(), "wb+"); if (!nf) { ires = 4; } else { //decrpt file contents for (ULONG k = 0; k < count; k++) { SecureZeroMemory(inbuf, 16); SecureZeroMemory(outbuf, 16); if (0 < fread(inbuf, 1, 16, pFile))//read 16 bytes from file { AES_decrypt(inbuf, outbuf, &aes_key);//decrpt 16 bytes if (k == count - 1) { fwrite(outbuf, 1, last == 0 ? 16 : last, nf); } else { fwrite(outbuf, 1, 16, nf); } } } fclose(nf); } fclose(pFile); if (!bToTmpFile) { DeleteFileA(filename.c_str()); FileRename(newfile, filename); } } else { fclose(pFile); } return ires; } int GetAuthorizeConfigs(string filename, AuthorizeConfigs & configs) { int ires = 0; AES_KEY aes_key; long long last, lastlen = 0; unsigned char key[16] = { 0 }; unsigned char inbuf[16] = { 0 }; unsigned char outbuf[16] = { 0 }; unsigned char szHeader[256] = { 0 }; FILE *pFile = nullptr; fopen_s(&pFile, filename.c_str(), "rb"); if (!pFile) { ires = 1; std::cout << "GetAuthorizeConfigs Failed , ErrCode:" << ires << " ." << std::endl; return ires; } //char *pBuf; fseek(pFile, 0, SEEK_END); //point the file end int len = ftell(pFile); rewind(pFile); //count the decrpt times of file ULONG count = (len - 256) / 16; if (count <= 0) { fclose(pFile); ires = 2; std::cout << "GetAuthorizeConfigs Failed , ErrCode:" << ires << " ." << std::endl; return ires; } //get key from file if (0 == fread(szHeader, 1, 256, pFile)) { fclose(pFile); ires = 2; std::cout << "GetAuthorizeConfigs Failed , ErrCode:" << ires << " ." << std::endl; return ires; } memcpy_s(key, 16, szHeader + 100, 16); //start to decrpt file if (AES_set_decrypt_key(key, 128, &aes_key) == 0)//set decrypt key { //computer the file size before encrpt memcpy_s(inbuf, 16, szHeader, 16); AES_decrypt(inbuf, outbuf, &aes_key); memcpy_s(&lastlen, sizeof(ULONG), outbuf, sizeof(ULONG)); last = lastlen % 16; //the part less 16 bytes before encprt //check file if the file is able to be decrpted or not bool ret = last == 0 ? lastlen == len - 256 : lastlen + 16 - last == len - 256; if (!ret) { fclose(pFile); ires = 3; std::cout << "GetAuthorizeConfigs Failed , ErrCode:" << ires << " ." << std::endl; return ires; } //decrpt file contents stringstream tmpStram; for (ULONG k = 0; k < count; k++) { SecureZeroMemory(inbuf, 16); SecureZeroMemory(outbuf, 16); if (0 < fread(inbuf, 1, 16, pFile))//read 16 bytes from file { AES_decrypt(inbuf, outbuf, &aes_key);//decrpt 16 bytes if (k == count - 1) { tmpStram.write((char *)outbuf, last == 0 ? 16 : last); } else { tmpStram.write((char *)outbuf, 16); } } } //Get authorize configs { const int LINE_LENGTH = 256; char lineBuf[LINE_LENGTH]; tmpStram.getline(lineBuf, LINE_LENGTH); //Get file Type string tmpType(lineBuf); { if (tmpType[tmpType.length() - 1] == '\n') { tmpType[tmpType.length() - 1] = '\0'; } if (tmpType.length() < 1) { fclose(pFile); ires = 5; std::cout << "GetAuthorizeConfigs Failed , ErrCode:" << ires << " ." << std::endl; return ires; } if (tmpType != string("1") && tmpType != string("2") && tmpType != string("3")) { fclose(pFile); ires = 5; std::cout << "GetAuthorizeConfigs Failed , ErrCode:" << ires << " ." << std::endl; return ires; } configs._Type = tmpType; } //Get limit Time tmpStram.getline(lineBuf, LINE_LENGTH); string tmpTime(lineBuf); { if (tmpTime[tmpTime.length() - 1] == '\n') { tmpTime[tmpTime.length() - 1] = '\0'; } if (tmpTime.length() < 1) { fclose(pFile); ires = 6; std::cout << "GetAuthorizeConfigs Failed , ErrCode:" << ires << " ." << std::endl; return ires; } configs._LimitTime = tmpTime; } //Get package name tmpStram.getline(lineBuf, LINE_LENGTH); string tmpPackage(lineBuf); { if (tmpPackage[tmpPackage.length() - 1] == '\n') { tmpPackage[tmpPackage.length() - 1] = '\0'; } if (tmpPackage.length() < 1) { fclose(pFile); ires = 7; std::cout << "GetAuthorizeConfigs Failed , ErrCode:" << ires << " ." << std::endl; return ires; } configs._PackageName = tmpPackage; } //Get authorize Key tmpStram.getline(lineBuf, LINE_LENGTH); string tmpAuthorKey(lineBuf); { if (tmpAuthorKey[tmpAuthorKey.length() - 1] == '\n') { tmpAuthorKey[tmpAuthorKey.length() - 1] = '\0'; } if (tmpAuthorKey.length() < 1) { fclose(pFile); ires = 8; std::cout << "GetAuthorizeConfigs Failed , ErrCode:" << ires << " ." << std::endl; return ires; } configs._AuthorizeKey = tmpAuthorKey; } if (tmpType == string("3")) { //Get activate Url tmpStram.getline(lineBuf, LINE_LENGTH); string tmpActivateUrl(lineBuf); { if (tmpActivateUrl[tmpActivateUrl.length() - 1] == '\n') { tmpActivateUrl[tmpActivateUrl.length() - 1] = '\0'; } if (tmpActivateUrl.length() < 1) { fclose(pFile); ires = 9; std::cout << "GetAuthorizeConfigs Failed , ErrCode:" << ires << " ." << std::endl; return ires; } configs._ActivateUrl = tmpActivateUrl; } //Get activate local cipher tmpStram.getline(lineBuf, LINE_LENGTH); string tmpLocalCipher(lineBuf); { if (tmpLocalCipher[tmpLocalCipher.length() - 1] == '\n') { tmpLocalCipher[tmpLocalCipher.length() - 1] = '\0'; } if (tmpLocalCipher.length() < 1) { fclose(pFile); ires = 10; std::cout << "GetAuthorizeConfigs Failed , ErrCode:" << ires << " ." << std::endl; return ires; } configs._ActivateLocalCipher = tmpLocalCipher; } } else if (tmpType == string("2")) { //Get ToolKey tmpStram.getline(lineBuf, LINE_LENGTH); string tmpToolKey(lineBuf); { if (tmpToolKey[tmpToolKey.length() - 1] == '\n') { tmpToolKey[tmpToolKey.length() - 1] = '\0'; } if (tmpToolKey.length() < 1) { fclose(pFile); ires = 11; std::cout << "GetAuthorizeConfigs Failed , ErrCode:" << ires << " ." << std::endl; return ires; } configs._ToolKey = tmpToolKey; } while (tmpStram.getline(lineBuf, LINE_LENGTH)) { string tmpMacKey(lineBuf); if (tmpMacKey[tmpMacKey.length() - 1] == '\n') { tmpMacKey[tmpMacKey.length() - 1] = '\0'; } if (tmpMacKey.length() < 1) { continue; } if (tmpMacKey.length() != 45) { fclose(pFile); ires = 12; std::cout << "GetAuthorizeConfigs Failed , ErrCode:" << ires << " ." << std::endl; return ires; } Mac_Key tmpMac_Key; tmpMac_Key._Mac = tmpMacKey.substr(0, 12); tmpMac_Key._MacKey = tmpMacKey.substr(13, 32); configs._MacKeys.push_back(tmpMac_Key); } if (configs._MacKeys.size() < 1) { fclose(pFile); ires = 13; std::cout << "GetAuthorizeConfigs Failed , ErrCode:" << ires << " ." << std::endl; return ires; } } fclose(pFile); } } else { ires = 4; std::cout << "GetAuthorizeConfigs Failed , ErrCode:" << ires << " ." << std::endl; fclose(pFile); } return ires; } */ #pragma endregion AES_IMPL Request::Request(void) { //do nothing } Request::~Request(void) { //do nothing } int Request::post(string &url,string &data,int timeout) { int resultReturn = -1; CURL *curl; CURLM *multi_handle; int still_running; struct curl_httppost *formpost=NULL; struct curl_httppost *lastptr=NULL; struct curl_slist *headerlist=NULL; static const char buf[] = "Expect:"; Json::Reader reader; Json::Value value; if (!reader.parse(data, value, false)) { resultReturn = -1; return resultReturn; } Json::Value::Members member = value.getMemberNames(); for(Json::Value::Members::iterator iter = member.begin(); iter != member.end(); ++iter) { string hand = *iter; string val; try{ val = value[hand].asString(); } catch(...) { val = value[hand].toStyledString(); } curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, hand.c_str(), CURLFORM_COPYCONTENTS, val.c_str(), CURLFORM_END); } curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "submit", CURLFORM_COPYCONTENTS, "send", CURLFORM_END); curl = curl_easy_init(); multi_handle = curl_multi_init(); headerlist = curl_slist_append(headerlist, buf); if(curl && multi_handle) { curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist); curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); //访问Wanda盒子时不需要https,访问SnapCam时需要Https。 string urlFlag = url.substr(0, 5); std::transform(urlFlag.begin(), urlFlag.end(), urlFlag.begin(), ::tolower); if (urlFlag == string("https")) { curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);//设定为不验证证书和HOST curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); } curl_multi_add_handle(multi_handle, curl); curl_multi_perform(multi_handle, &still_running); do { struct timeval time_out; int rc; /* select() return code */ fd_set fdread; fd_set fdwrite; fd_set fdexcep; int maxfd = -1; long curl_timeo = timeout; FD_ZERO(&fdread); FD_ZERO(&fdwrite); FD_ZERO(&fdexcep); time_out.tv_sec = 1; time_out.tv_usec = 0; curl_multi_timeout(multi_handle, &curl_timeo); if(curl_timeo >= 0) { time_out.tv_sec = curl_timeo / 1000; if(time_out.tv_sec > 1) time_out.tv_sec = 1; else time_out.tv_usec = (curl_timeo % 1000) * 1000; } curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd); rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &time_out); switch(rc) { case -1: cout << "select error!" << endl; break; case 0: default: curl_multi_perform(multi_handle, &still_running); break; } } while(still_running); int msgs_left; CURLMsg *msg; msg = curl_multi_info_read(multi_handle, &msgs_left); resultReturn = msg->data.result; curl_multi_cleanup(multi_handle); curl_easy_cleanup(curl); curl_formfree(formpost); curl_slist_free_all (headerlist); } return resultReturn; } size_t write_func(void* data, size_t size, size_t nmemb, void* content) { long totalSize = size*nmemb; std::string* symbolBuffer = (std::string*)content; if (symbolBuffer) { symbolBuffer->append((char *)data, ((char*)data) + totalSize); } return totalSize; } int Request::post(string &url,string &data,string &files, string & strData,int timeout) { int resultReturn = -1; CURL *curl; struct curl_httppost *formpost=NULL; struct curl_httppost *lastptr=NULL; struct curl_slist *headerlist=NULL; static const char buf[] = "Expect:"; Json::Reader reader; Json::Value json_data; Json::Value json_files; if (!reader.parse(data, json_data, false)) { resultReturn = -1; return resultReturn; } Json::Value::Members data_member = json_data.getMemberNames(); for(Json::Value::Members::iterator iter = data_member.begin(); iter != data_member.end(); ++iter) { string hand = *iter; string val; try{ val = json_data[hand].asString(); } catch(...) { val = json_data[hand].toStyledString(); } curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, hand.c_str(), CURLFORM_COPYCONTENTS, val.c_str(), CURLFORM_END); } if (files.length() > 0) { if (!reader.parse(files, json_files, false)) { resultReturn = -1; return resultReturn; } Json::Value::Members files_member = json_files.getMemberNames(); for (Json::Value::Members::iterator iter = files_member.begin(); iter != files_member.end(); ++iter) { string hand = *iter; string val = json_files[hand].asString(); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, hand.c_str(), CURLFORM_FILE, val.c_str(), CURLFORM_END); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, hand.c_str(), CURLFORM_COPYCONTENTS, val.c_str(), CURLFORM_END); } } curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "submit", CURLFORM_COPYCONTENTS, "send", CURLFORM_END); curl = curl_easy_init(); headerlist = curl_slist_append(headerlist, buf); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist); curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); //访问Wanda盒子时不需要https,访问SnapCam时需要Https。 string urlFlag = url.substr(0, 5); std::transform(urlFlag.begin(), urlFlag.end(), urlFlag.begin(), ::tolower); if(urlFlag == string("https")) { curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);//设定为不验证证书和HOST curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); } curl_easy_setopt(curl, CURLOPT_TIMEOUT, 8);//接收数据时超时设置,如果3秒内数据未接收完,直接退出 curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 8);//连接超时,这个数值如果设置太短可能导致数据请求不到就断开了 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_func);// 设置回调函数 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&strData);//设置写数据 CURLcode code = curl_easy_perform(curl);//执行请求 if (code == CURLcode::CURLE_OK) { long responseCode = 0; curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode); if (responseCode > 0 && !strData.empty()) { resultReturn = 1;//表示已经获取到服务器端的返回信息 } } curl_easy_cleanup(curl); curl_formfree(formpost); curl_slist_free_all (headerlist); } return resultReturn; } size_t callbackfunction(void *ptr, size_t size, size_t nmemb, void* userdata) { FILE* stream = (FILE*)userdata; if (!stream) { printf("!!! No stream\n"); return 0; } size_t written = fwrite((FILE*)ptr, size, nmemb, stream); return written; } bool Request::downloadFile(string & fileUrl,string & fileName) { FILE* fp = NULL; fopen_s(&fp,fileName.c_str(), "wb"); if (!fp) { printf("!!! Failed to create file on the disk\n"); return false; } CURL* curlCtx = curl_easy_init(); curl_easy_setopt(curlCtx, CURLOPT_URL, fileUrl.c_str()); curl_easy_setopt(curlCtx, CURLOPT_WRITEDATA, fp); curl_easy_setopt(curlCtx, CURLOPT_WRITEFUNCTION, callbackfunction); curl_easy_setopt(curlCtx, CURLOPT_FOLLOWLOCATION, 1); //访问Wanda盒子时不需要https,访问SnapCam时需要Https。 string urlFlag = fileUrl.substr(0, 5); std::transform(urlFlag.begin(), urlFlag.end(), urlFlag.begin(), ::tolower); if (urlFlag == string("https")) { curl_easy_setopt(curlCtx, CURLOPT_SSL_VERIFYPEER, false);//设定为不验证证书和HOST curl_easy_setopt(curlCtx, CURLOPT_SSL_VERIFYHOST, false); } CURLcode rc = curl_easy_perform(curlCtx); if (rc) { printf("!!! Failed to download: %s\n", fileUrl.c_str()); fclose(fp); return false; } long res_code = 0; curl_easy_getinfo(curlCtx, CURLINFO_RESPONSE_CODE, &res_code); if (!((res_code == 200 || res_code == 201) && rc != CURLE_ABORTED_BY_CALLBACK)) { printf("!!! Response code: %d\n", res_code); fclose(fp); return false; } curl_easy_cleanup(curlCtx); fclose(fp); return true; }