Files

212 lines
4.6 KiB
C++
Raw Permalink Normal View History

2026-03-28 16:54:11 +11:00
#include "precomp.h"
#include <iostream>
#include <string>
#include "download.h"
#include "uniconv.h"
#include "except.h"
#ifdef _WIN32
#include <winhttp.h>
#include <malloc.h>
#else
#include <curl/curl.h>
#endif
#ifndef _WIN32
class CurlWriteBuffer
{
public:
CurlWriteBuffer(void * buffer, size_t size)
{
this->buffer = (char *)buffer;
this->size = size;
offset = 0;
}
int Append(void * buffer, size_t size)
{
if (this->offset + size > this->size)
size = this->size - offset;
if (size > 0)
{
memcpy(this->buffer + offset, buffer, size);
offset += size;
}
return size;
}
static size_t
Callback(void *contents, size_t size, size_t nmemb, void *userp)
{
return ((CurlWriteBuffer *)userp)->Append(contents, size * nmemb);
}
size_t offset;
size_t size;
char * buffer;
};
#endif
void UrlDownloadToString(const char * url, char * buffer, int * len)
{
#ifndef LICENSING_NO_NETWORKING
#ifdef _WIN32
HRESULT result = ERROR_SUCCESS;
URL_COMPONENTS urlComponents;
do {
ZeroMemory(&urlComponents, sizeof(urlComponents));
urlComponents.dwStructSize = sizeof(urlComponents);
urlComponents.dwHostNameLength = (DWORD)-1;
urlComponents.dwUrlPathLength = (DWORD)-1;
auto urlw = s2w(url);
if (!WinHttpCrackUrl(urlw.c_str(), urlw.size(), 0L, &urlComponents))
{
result = GetLastError();
break;
}
wstring hostName(urlComponents.lpszHostName, urlComponents.dwHostNameLength);
unique_ptr<VOID, decltype(&WinHttpCloseHandle)> internet_ptr(WinHttpOpen(L"ANSCENTER Licensing SDK", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0L), WinHttpCloseHandle);
if (!internet_ptr)
{
result = GetLastError();
break;
}
unique_ptr<VOID, decltype(&WinHttpCloseHandle)> connection_ptr(WinHttpConnect(internet_ptr.get(), hostName.c_str(), urlComponents.nPort, 0L), WinHttpCloseHandle);
if (connection_ptr == NULL)
{
result = GetLastError();
break;
}
wstring objectPath(urlComponents.lpszUrlPath, urlComponents.dwUrlPathLength);
DWORD requestFlags = WINHTTP_FLAG_BYPASS_PROXY_CACHE;
if (urlComponents.nScheme == INTERNET_SCHEME_HTTPS)
requestFlags |= WINHTTP_FLAG_SECURE;
unique_ptr<VOID, decltype(&WinHttpCloseHandle)> request_ptr(WinHttpOpenRequest(connection_ptr.get(), L"GET", objectPath.c_str(), NULL, NULL, NULL, requestFlags), WinHttpCloseHandle);
if (!request_ptr)
{
result = GetLastError();
break;
}
if (!WinHttpSendRequest(request_ptr.get(), NULL, 0L, NULL, 0, 0L, NULL))
{
result = GetLastError();
break;
}
if (!WinHttpReceiveResponse(request_ptr.get(), NULL))
{
result = GetLastError();
break;
}
DWORD status;
DWORD statusSize = sizeof(DWORD);
if (!WinHttpQueryHeaders(request_ptr.get(), WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, &status, &statusSize, WINHTTP_NO_HEADER_INDEX))
{
result = GetLastError();
break;
}
if (status != HTTP_STATUS_OK)
{
WCHAR buffer[1024];
DWORD bufferSize = 1024;
if (!WinHttpQueryHeaders(request_ptr.get(), WINHTTP_QUERY_STATUS_TEXT, WINHTTP_HEADER_NAME_BY_INDEX, buffer, &bufferSize, WINHTTP_NO_HEADER_INDEX))
{
result = GetLastError();
break;
}
result = ERROR_WINHTTP_INVALID_URL;
break;
}
if (status != HTTP_STATUS_OK)
{
result = GetLastError();
break;
}
DWORD offset = 0, count;
char lbuf[0x100];
do {
if (WinHttpReadData(request_ptr.get(), lbuf, 0x100, &count))
{
if (count == 0)
{
*len = offset;
break;
}
if (offset + count > *len)
{
result = ERROR_INSUFFICIENT_BUFFER;
break;
}
memcpy(buffer + offset, lbuf, count);
offset += count;
} else
{
result = GetLastError();
break;
}
} while (true);
} while (false);
if (result != ERROR_SUCCESS)
throw new LicensingException(result, "networking error while downloading url contents");
#else
CURL *curl;
CURLcode res;
if ((curl = curl_easy_init()) == NULL)
throw new LicensingException(STATUS_NET_ERROR, "cURL initalization failed");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
CurlWriteBuffer curlBuffer(buffer, *len);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteBuffer::Callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &curlBuffer);
res = curl_easy_perform(curl);
if(res != CURLE_OK)
{
curl_easy_cleanup(curl);
throw new LicensingException(STATUS_NET_ERROR, curl_easy_strerror(res));
}
*len = curlBuffer.offset;
curl_easy_cleanup(curl);
#endif
#else // !LICENSING_NO_NETWORKING
throw new LicensingException(STATUS_GENERIC_ERROR, "networking support not built in");
#endif
}