#include "precomp.h" #include #include #include "download.h" #include "uniconv.h" #include "except.h" #ifdef _WIN32 #include #include #else #include #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 internet_ptr(WinHttpOpen(L"ANSCENTER Licensing SDK", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0L), WinHttpCloseHandle); if (!internet_ptr) { result = GetLastError(); break; } unique_ptr 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 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 }