mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Tier2: implement cURL upload file utility
This commit is contained in:
parent
0f89a4e3db
commit
9f935ec4b4
@ -12,14 +12,15 @@ struct CURLProgress
|
||||
|
||||
CURL* curl;
|
||||
const char* name;
|
||||
void* cust; // custom pointer to anything.
|
||||
void* cust; // custom pointer to anything, todo(amos): rename to 'user'.
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct CURLParams
|
||||
{
|
||||
CURLParams()
|
||||
: writeFunction(nullptr)
|
||||
: readFunction(nullptr)
|
||||
, writeFunction(nullptr)
|
||||
, statusFunction(nullptr)
|
||||
, timeout(0)
|
||||
, verifyPeer(false)
|
||||
@ -27,6 +28,7 @@ struct CURLParams
|
||||
, verbose(false)
|
||||
{}
|
||||
|
||||
void* readFunction;
|
||||
void* writeFunction;
|
||||
void* statusFunction;
|
||||
|
||||
@ -36,9 +38,14 @@ struct CURLParams
|
||||
bool verbose;
|
||||
};
|
||||
|
||||
size_t CURLReadFileCallback(void* data, const size_t size, const size_t nmemb, FILE* stream);
|
||||
size_t CURLWriteFileCallback(void* data, const size_t size, const size_t nmemb, FILE* stream);
|
||||
size_t CURLWriteStringCallback(char* contents, const size_t size, const size_t nmemb, string* userp);
|
||||
size_t CURLWriteFileCallback(void* data, const size_t size, const size_t nmemb, FILE* userp);
|
||||
|
||||
curl_slist* CURLSlistAppend(curl_slist* slist, const char* string);
|
||||
|
||||
bool CURLUploadFile(const char* remote, const char* filePath, const char* options,
|
||||
void* customPointer, const bool usePost, const curl_slist* slist, const CURLParams& params);
|
||||
bool CURLDownloadFile(const char* remote, const char* savePath, const char* fileName,
|
||||
const char* options, curl_off_t dataSize, void* customPointer, const CURLParams& params);
|
||||
|
||||
|
@ -6,20 +6,27 @@
|
||||
#include "tier1/cvar.h"
|
||||
#include "tier2/curlutils.h"
|
||||
|
||||
size_t CURLReadFileCallback(void* data, const size_t size, const size_t nmemb, FILE* stream)
|
||||
{
|
||||
const size_t numBytesRead = fread(data, size, nmemb, stream);
|
||||
return numBytesRead;
|
||||
}
|
||||
|
||||
size_t CURLWriteFileCallback(void* data, const size_t size, const size_t nmemb, FILE* stream)
|
||||
{
|
||||
const size_t numBytesWritten = fwrite(data, size, nmemb, stream);
|
||||
return numBytesWritten;
|
||||
}
|
||||
|
||||
size_t CURLWriteStringCallback(char* data, const size_t size, const size_t nmemb, string* userp)
|
||||
{
|
||||
userp->append(data, size * nmemb);
|
||||
return size * nmemb;
|
||||
}
|
||||
|
||||
size_t CURLWriteFileCallback(void* data, const size_t size, const size_t nmemb, FILE* userp)
|
||||
{
|
||||
const size_t numBytesWritten = fwrite(data, size, nmemb, userp);
|
||||
return numBytesWritten;
|
||||
}
|
||||
|
||||
void CURLInitCommonOptions(CURL* curl, const char* remote,
|
||||
const void* writeData, const CURLParams& params)
|
||||
const void* readData, const void* writeData,
|
||||
const CURLParams& params, const CURLProgress* progressData)
|
||||
{
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, params.timeout);
|
||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, params.verbose);
|
||||
@ -29,17 +36,146 @@ void CURLInitCommonOptions(CURL* curl, const char* remote,
|
||||
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
|
||||
curl_easy_setopt(curl, CURLOPT_URL, remote);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, writeData);
|
||||
curl_easy_setopt(curl, CURLOPT_READDATA, readData);
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, "R5R HTTPS/1.0");
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, params.writeFunction);
|
||||
curl_easy_setopt(curl, CURLOPT_READFUNCTION, params.readFunction);
|
||||
|
||||
if (params.statusFunction)
|
||||
{
|
||||
Assert(progressData);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0l);
|
||||
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &progressData);
|
||||
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, params.statusFunction);
|
||||
}
|
||||
}
|
||||
|
||||
bool CURLDownloadFile(const char* remote, const char* savePath, const char* fileName,
|
||||
const char* options, curl_off_t dataSize, void* customPointer, const CURLParams& params)
|
||||
static CURL* EasyInit()
|
||||
{
|
||||
CURL* curl = curl_easy_init();
|
||||
if (!curl)
|
||||
{
|
||||
Error(eDLL_T::COMMON, NO_ERROR, "CURL: %s\n", "Easy init failed");
|
||||
}
|
||||
|
||||
return curl;
|
||||
}
|
||||
|
||||
static FILE* OpenFile(const char* filePath, const char* options)
|
||||
{
|
||||
FILE* file = fopen(filePath, options);
|
||||
if (!file)
|
||||
{
|
||||
Error(eDLL_T::COMMON, NO_ERROR, "CURL: %s\n", "Open file failed");
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
static bool FileStat(const char* fileName, struct _stat64& stat)
|
||||
{
|
||||
if (_stat64(fileName, &stat) != 0)
|
||||
{
|
||||
Error(eDLL_T::COMMON, NO_ERROR, "CURL: %s\n", "File status query failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
curl_slist* CURLSlistAppend(curl_slist* slist, const char* string)
|
||||
{
|
||||
slist = curl_slist_append(slist, string);
|
||||
if (!slist)
|
||||
{
|
||||
Error(eDLL_T::COMMON, NO_ERROR, "CURL: %s\n", "Slist append failed");
|
||||
}
|
||||
|
||||
return slist;
|
||||
}
|
||||
|
||||
bool CURLUploadFile(const char* remote, const char* filePath,
|
||||
const char* options, void* customPointer, const bool usePost,
|
||||
const curl_slist* slist, const CURLParams& params)
|
||||
{
|
||||
CURL* curl = EasyInit();
|
||||
if (!curl)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE* file = OpenFile(filePath, options);
|
||||
if (!file)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
struct _stat64 fileStatus;
|
||||
if (!FileStat(filePath, fileStatus))
|
||||
{
|
||||
fclose(file);
|
||||
return false;
|
||||
}
|
||||
|
||||
CURLProgress progressData;
|
||||
|
||||
progressData.curl = curl;
|
||||
progressData.name = filePath;
|
||||
progressData.cust = customPointer;
|
||||
progressData.size = fileStatus.st_size;
|
||||
|
||||
string response;
|
||||
CURLInitCommonOptions(curl, remote, file, &response, params, &progressData);
|
||||
|
||||
if (slist)
|
||||
{
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
|
||||
}
|
||||
|
||||
const bool largeFile = fileStatus.st_size > INT_MAX;
|
||||
CURLoption fileSizeOption;
|
||||
|
||||
if (usePost)
|
||||
{
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
|
||||
fileSizeOption = largeFile
|
||||
? CURLOPT_POSTFIELDSIZE_LARGE
|
||||
: CURLOPT_POSTFIELDSIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
|
||||
|
||||
fileSizeOption = largeFile
|
||||
? CURLOPT_INFILESIZE_LARGE
|
||||
: CURLOPT_INFILESIZE;
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl, fileSizeOption, (curl_off_t)fileStatus.st_size);
|
||||
|
||||
CURLcode res = curl_easy_perform(curl);
|
||||
const bool success = res == CURLE_OK;
|
||||
|
||||
if (!success)
|
||||
{
|
||||
Error(eDLL_T::COMMON, NO_ERROR, "CURL: Upload of file '%s' failed; %s\n",
|
||||
filePath, curl_easy_strerror(res));
|
||||
}
|
||||
|
||||
curl_easy_cleanup(curl);
|
||||
fclose(file);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool CURLDownloadFile(const char* remote, const char* savePath, const char* fileName,
|
||||
const char* options, curl_off_t dataSize, void* customPointer, const CURLParams& params)
|
||||
{
|
||||
CURL* curl = EasyInit();
|
||||
if (!curl)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -48,12 +184,10 @@ bool CURLDownloadFile(const char* remote, const char* savePath, const char* file
|
||||
AppendSlash(filePath);
|
||||
filePath.append(fileName);
|
||||
|
||||
FILE* file = fopen(filePath.c_str(), options);
|
||||
FILE* file = OpenFile(filePath.c_str(), options);
|
||||
if (!file)
|
||||
{
|
||||
Error(eDLL_T::COMMON, NO_ERROR, "CURL: %s\n", "Open file failed");
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -64,14 +198,7 @@ bool CURLDownloadFile(const char* remote, const char* savePath, const char* file
|
||||
progressData.cust = customPointer;
|
||||
progressData.size = dataSize;
|
||||
|
||||
CURLInitCommonOptions(curl, remote, file, params);
|
||||
|
||||
if (params.statusFunction)
|
||||
{
|
||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0l);
|
||||
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &progressData);
|
||||
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, params.statusFunction);
|
||||
}
|
||||
CURLInitCommonOptions(curl, remote, nullptr, file, params, &progressData);
|
||||
|
||||
CURLcode res = curl_easy_perform(curl);
|
||||
|
||||
@ -95,33 +222,25 @@ bool CURLDownloadFile(const char* remote, const char* savePath, const char* file
|
||||
CURL* CURLInitRequest(const char* remote, const char* request,
|
||||
string& outResponse, curl_slist*& slist, const CURLParams& params)
|
||||
{
|
||||
std::function<void(const char*)> fnError = [&](const char* errorMsg)
|
||||
{
|
||||
Error(eDLL_T::COMMON, NO_ERROR, "CURL: %s\n", errorMsg);
|
||||
curl_slist_free_all(slist);
|
||||
};
|
||||
|
||||
slist = curl_slist_append(slist, "Content-Type: application/json");
|
||||
slist = CURLSlistAppend(slist, "Content-Type: application/json");
|
||||
if (!slist)
|
||||
{
|
||||
fnError("Slist init failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CURL* curl = curl_easy_init();
|
||||
CURL* curl = EasyInit();
|
||||
if (!curl)
|
||||
{
|
||||
fnError("Easy init failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CURLInitCommonOptions(curl, remote, &outResponse, params);
|
||||
CURLInitCommonOptions(curl, remote, nullptr, &outResponse, params, nullptr);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
|
||||
if (request)
|
||||
{
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request);
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request);
|
||||
}
|
||||
|
||||
return curl;
|
||||
|
Loading…
x
Reference in New Issue
Block a user