C++ 自定义url下载数据类
url下载文件类
主要是常见代码做个整理
AutoString iutiltools 都是自定义的类型.和本类无关.
code
.h
#pragma once
#include "IUtileTools.h"
#include <UrlMon.h>//download file URLDownloadToFile
#pragma comment(lib, "urlmon.lib")
#pragma comment(lib,"Wininet.lib")
//URLDownloadToFile(NULL, url, filename, 0, NULL);//download with the second way
class CUrls : public IUtileTools
{
public :
CUrls();
~CUrls();
public:
bool downloadToMemory(AutoString Url, OUT char*& ptrData, OUT int& ptrdata_size);
/*
参数1: 下载的url
参数2: 下载到的文件路径 给全路径 如: c:\xxx\temp\abc 那么下载的数据就是此文件
*/
bool downloadToFile(wstring url, wstring fileName);
//解密数据并且写入到指定文件中
bool WriteFileToSpecialFilePath(
AutoString FileName,
void* writeBuffer,
int buffersize,
bool isEntry);
private:
//下载到文件
/*
参数1: 要下载的url链接
参数2: 下载到哪里,给一个全路径的文件名。
*/
bool download(AutoString Url, AutoString filename);
bool downloadToFileByWinapi(wstring url, wstring fileName);
//下载到内存
/*
参数1,要下载数据的url
参数2,下载的数据内存,数据下载好之后会存放到内存中.
*/
bool downloadToBuffer(AutoString Url, OUT char*& ptrData, OUT int& ptrdata_size);
bool downloadToFileStream(wstring Url, OUT char*& ptrData, OUT int& ptrdata_size);
};
.cpp
#include "CUrls.h"
#include <Windows.h>
#include <wininet.h>
#include <iostream>
#include "base64.h"
#include <fstream>
#include <Urlmon.h>
//#pragma comment(lib,"Winhttp.lib")
#pragma comment(lib, "Urlmon.lib")
using namespace std;
CUrls::CUrls()
{
}
CUrls::~CUrls()
{
}
bool CUrls::downloadToBuffer(AutoString Url,OUT char *&ptrData,OUT int &ptrdata_size)
{
byte Temp[4096];
memset(Temp, 0, 4096);
ULONG Number = 1;
int BufferSize = 0;
char* recvdata = nullptr;
memset(recvdata, 0, BufferSize);
//INTERNET_FLAG_ASYNC
//INTERNET_FLAG_FROM_CACHE
HINTERNET hSession = InternetOpen(TEXT("RookIE/1.0"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
HINTERNET handle2 = nullptr;
if (hSession != NULL)
{
handle2 = InternetOpenUrl(hSession, Url.c_str(), NULL, 0, INTERNET_FLAG_DONT_CACHE, 0);
if (handle2 != NULL)
{
vector<char*> Memary;
while (Number > 0)
{
char* TempBuffer = new char[4096]();
InternetReadFile(handle2, TempBuffer, 4096, &Number);
Memary.push_back(TempBuffer);
}
//合并内存
DWORD MmearySize = Memary.size();
DWORD AllocSize = MmearySize * 4096;
recvdata = (char*)VirtualAlloc(0, AllocSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (recvdata != nullptr)
{
char* pstart = recvdata;
for (DWORD i = 0; i < Memary.size(); i++)
{
if (recvdata != 0)
{
memcpy(recvdata, Memary[i], 4096);
}
recvdata += 4096;
}
//释放内存
for (DWORD i = 0; i < Memary.size(); i++)
{
delete[] Memary[i];
}
ptrData = pstart;
ptrdata_size = AllocSize;
}
}
else
{
goto ERROR_OPT;
}
}
else
{
goto ERROR_OPT;
}
if (handle2 != NULL)
{
InternetCloseHandle(handle2);
handle2 = NULL;
}
else
{
handle2 = NULL;
}
if (hSession != NULL)
{
InternetCloseHandle(hSession);
hSession = NULL;
}
else
{
hSession = NULL;
}
return true;
ERROR_OPT:
if (handle2 != NULL)
{
InternetCloseHandle(handle2);
handle2 = NULL;
}
else
{
handle2 = NULL;
}
if (hSession != NULL)
{
InternetCloseHandle(hSession);
hSession = NULL;
}
else
{
hSession = NULL;
}
return false;
}
bool CUrls::download(AutoString Url, AutoString filename)
{
/*
每次下载之前判断是否下载过了.或者说删除cfg文件来达到命令只执行一次
*/
byte Temp[1024];
ULONG Number = 1;
FILE* stream;
HINTERNET hSession = InternetOpen(TEXT("RookIE/1.0"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
HINTERNET handle2 = nullptr;
if (hSession != NULL)
{
handle2 = InternetOpenUrl(hSession, Url.c_str(), NULL, 0, INTERNET_FLAG_DONT_CACHE, 0);
if (handle2 != NULL)
{
#ifdef _UNICODE
if ((stream = _wfopen(filename.c_str(), TEXT("wb"))) != NULL)
#else
if ((stream = fopen(filename.c_str(), "wb")) != NULL)
#endif
{
while (Number > 0)
{
InternetReadFile(handle2, Temp, 1024, &Number); //每次读取1024个字节并且写入到文件
fwrite(Temp, sizeof(char), Number, stream);
}
fclose(stream);
}
}
else
{
goto ERROR_OPT;
}
}
else
{
goto ERROR_OPT;
}
if (handle2 != NULL)
{
InternetCloseHandle(handle2);
handle2 = NULL;
}
else
{
handle2 = NULL;
}
if (hSession != NULL)
{
InternetCloseHandle(hSession);
hSession = NULL;
}
else
{
hSession = NULL;
}
return true;
ERROR_OPT:
if (handle2 != NULL)
{
InternetCloseHandle(handle2);
handle2 = NULL;
}
else
{
handle2 = NULL;
}
if (hSession != NULL)
{
InternetCloseHandle(hSession);
hSession = NULL;
}
else
{
hSession = NULL;
}
return false;
}
bool CUrls::downloadToFileByWinapi(wstring url, wstring fileName)
{
HRESULT ret = URLDownloadToFileW(
nullptr,
url.c_str(),
fileName.c_str(),
0,
nullptr
);
if (ret != S_OK)
return false;
return true;
}
bool CUrls::downloadToMemory(AutoString Url, OUT char*& ptrData, OUT int& ptrdata_size)
{
bool bRet = false;
char* pdata = nullptr;
int pdatasize = 0;
bRet = downloadToFileStream(Url, ptrData, ptrdata_size);
if (bRet)
{
return true;
}
bRet = downloadToBuffer(Url, ptrData, ptrdata_size);
if (bRet)
{
return true;
}
return false;
}
bool CUrls::downloadToFile(wstring url,wstring fileName)
{
bool bRet = false;
bRet = downloadToFileByWinapi(url,fileName);
if (bRet != false)
{
return true;
}
bRet = this->download(url, fileName);
if (bRet != false)
{
return true;
}
return false;
}
bool CUrls::downloadToFileStream(wstring Url, OUT char*& ptrData, OUT int& ptrdata_size)
{
IStream* stream; // 存后面的流
HRESULT ret = URLOpenBlockingStreamW(
nullptr,
Url.c_str(),
&stream,
0,
nullptr
);
if (ret != S_OK)
return false;
char buffer[4096] = { 0 };
vector<char*> ptr_vec;
DWORD readBytes = 0;
do
{
stream->Read( // 读取流中的数据
buffer, // 缓冲区
4096, // 缓冲区大小
&readBytes // 用来存储读取到的字节数。
);
char* ReadBuffer = new char[4096]();
RtlCopyMemory(ReadBuffer, buffer, 4096);
ptr_vec.push_back(ReadBuffer);
} while (readBytes > 0); // 直到读取完毕(读取字节数为 0)
DWORD Memorysize = ptr_vec.size();
DWORD allocSize = Memorysize * 4096;
char* ptrReadData = (char *)VirtualAlloc(0, allocSize, MEM_COMMIT, PAGE_READWRITE);
char* pStart = nullptr;
if (ptrReadData != nullptr)
{
pStart = ptrReadData; // 记录起始位置
}
for (DWORD i = 0; i < Memorysize; i++)
{
RtlCopyMemory(ptrReadData, ptr_vec[i], 4096);
ptrReadData += 4096;
}
//释放掉ptr_vec的内存.拷贝过的内存不需要了.
for (DWORD i = 0; i < Memorysize; i++)
{
if (ptr_vec[i] != nullptr)
{
delete[] ptr_vec[i];
ptr_vec[i] = 0;
}
}
stream->Release(); // 释放掉
ptrData = pStart;
ptrdata_size = allocSize;
return true;
}
bool CUrls::WriteFileToSpecialFilePath(
AutoString FileName,
void* writeBuffer,
int buffersize,
bool isEntry)
{
if (isEntry)
{
//解密数据写入到本地
int outlen = 0;
unsigned char *decryptBuffer = base64_decode((const char *)writeBuffer, buffersize, &outlen);
FILE* pFile = NULL;
#ifdef _UNICODE
_wfopen_s(&pFile, FileName.c_str(), L"wb");
#else
fopen_s(&pFile, FileName.c_str(), "wb");
#endif
if (pFile != NULL)
{
fwrite(decryptBuffer, outlen, 1, pFile);
if (pFile != NULL)
{
fclose(pFile);
pFile = NULL;
if (decryptBuffer != NULL)
{
free(decryptBuffer);
decryptBuffer = NULL;
}
return true;
}
if (decryptBuffer != NULL)
{
free(decryptBuffer);
decryptBuffer = NULL;
}
return false;
}
}
return false;
}
作者:IBinary
坚持两字,简单,轻便,但是真正的执行起来确实需要很长很长时间.当你把坚持两字当做你要走的路,那么你总会成功. 想学习,有问题请加群.群号:725864912(收费)群名称: 逆向学习小分队 群里有大量学习资源. 以及定期直播答疑.有一个良好的学习氛围. 涉及到外挂反外挂病毒 司法取证加解密 驱动过保护 VT 等技术,期待你的进入。
详情请点击链接查看置顶博客 https://www.cnblogs.com/iBinary/p/7572603.html
本文来自博客园,作者:iBinary,未经允许禁止转载 转载前可联系本人.对于爬虫人员来说如果发现保留起诉权力.https://www.cnblogs.com/iBinary/p/15428628.html
欢迎大家关注我的微信公众号.不定期的更新文章.更新技术. 关注公众号后请大家养成 不白嫖的习惯.欢迎大家赞赏. 也希望在看完公众号文章之后 不忘 点击 收藏 转发 以及点击在看功能. QQ群: