23 #include "../shared/shared.h"
24 #include <SDL_thread.h>
38 bool HTTP_ExtractComponents (
const char* url,
char* scheme,
size_t schemeLength,
char* host,
size_t hostLength,
char* path,
size_t pathLength,
int*
port)
48 for (buf = buffer, c = scheme, i = 0; *buf !=
'\0' && *buf !=
':';) {
49 if (i >= schemeLength - 1) {
50 Com_Printf(
"HTTP_ExtractComponents: Scheme is too long\n");
63 }
else if (
Q_streq(
"https", scheme)) {
66 Com_Printf(
"HTTP_ExtractComponents: Not supported scheme: %s\n", scheme);
70 Com_Printf(
"HTTP_ExtractComponents: Not supported scheme\n");
76 for (c = host, i = 0; *buf !=
'\0' && *buf !=
':' && *buf !=
'/';) {
77 if (i >= hostLength - 1) {
78 Com_Printf(
"HTTP_ExtractComponents: Host name is too long\n");
88 Com_Printf(
"HTTP_ExtractComponents: Host name is missing\n");
96 for (c = portString, i = 0; *buf !=
'\0' && *buf !=
'/';) {
97 if (i >=
sizeof(portString) - 1) {
98 Com_Printf(
"HTTP_ExtractComponents: Port specification is too long\n");
103 Com_Printf(
"HTTP_ExtractComponents: Invalid characters in port specification\n");
109 *port = atoi(portString);
110 if (*port <= 0 || *port >= 65536) {
111 Com_Printf(
"HTTP_ExtractComponents: Port out of bounds\n");
128 char headerBuff[1024];
129 const size_t bytes = size * nmemb;
135 if (bytes <
sizeof(headerBuff))
138 len =
sizeof(headerBuff);
140 Q_strncpyz(headerBuff, (
const char*)ptr, len);
145 dl->
fileSize = strtoul(headerBuff + 16,
nullptr, 10);
156 const size_t bytes = size * nmemb;
160 dl->
fileSize = bytes > 131072 ? bytes : 131072;
194 if (!
HTTP_ExtractComponents(url, scheme,
sizeof(scheme), server,
sizeof(server), uriPath,
sizeof(uriPath), &port))
198 if (ipServer[0] !=
'\0')
199 Com_sprintf(buf, size,
"%s://%s:%i%s", scheme, ipServer, port, uriPath);
215 if (buf[0] ==
'\0') {
221 dl.
curl = curl_easy_init();
224 curl_easy_setopt(dl.
curl, CURLOPT_ENCODING,
"");
225 curl_easy_setopt(dl.
curl, CURLOPT_NOPROGRESS, 1);
226 curl_easy_setopt(dl.
curl, CURLOPT_FAILONERROR, 1);
228 curl_easy_setopt(dl.
curl, CURLOPT_WRITEDATA, file);
229 curl_easy_setopt(dl.
curl, CURLOPT_WRITEFUNCTION,
nullptr);
231 curl_easy_setopt(dl.
curl, CURLOPT_WRITEDATA, &dl);
235 curl_easy_setopt(dl.
curl, CURLOPT_FOLLOWLOCATION, 1);
236 curl_easy_setopt(dl.
curl, CURLOPT_MAXREDIRS, 5);
237 curl_easy_setopt(dl.
curl, CURLOPT_WRITEHEADER, &dl);
238 if (postfields !=
nullptr)
239 curl_easy_setopt(dl.
curl, CURLOPT_POSTFIELDS, postfields);
242 curl_easy_setopt(dl.
curl, CURLOPT_URL, dl.
URL);
243 curl_easy_setopt(dl.
curl, CURLOPT_NOSIGNAL, 1);
246 const CURLcode result = curl_easy_perform(dl.
curl);
247 if (result != CURLE_OK) {
248 if (result == CURLE_HTTP_RETURNED_ERROR) {
250 curl_easy_getinfo(dl.
curl, CURLINFO_RESPONSE_CODE, &httpCode);
251 Com_Printf(
"failed to fetch '%s': %s (%i)\n", url, curl_easy_strerror(result), (
int)httpCode);
253 Com_Printf(
"failed to fetch '%s': %s\n", url, curl_easy_strerror(result));
255 curl_easy_cleanup(dl.
curl);
260 curl_easy_cleanup(dl.
curl);
284 if (buf[0] ==
'\0') {
289 CURL* curl = curl_easy_init();
290 if (curl ==
nullptr) {
295 struct curl_httppost* post =
nullptr;
296 struct curl_httppost* last =
nullptr;
298 curl_formadd(&post, &last, CURLFORM_PTRNAME, params->
name, CURLFORM_PTRCONTENTS, params->
value, CURLFORM_END);
299 params = params->
next;
302 curl_formadd(&post, &last, CURLFORM_PTRNAME, formName, CURLFORM_FILE, fileName, CURLFORM_END);
306 curl_easy_setopt(curl, CURLOPT_HTTPPOST, post);
307 curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
308 curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
309 curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
311 curl_easy_setopt(curl, CURLOPT_URL, url);
312 curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
313 const CURLcode result = curl_easy_perform(curl);
314 if (result != CURLE_OK) {
315 if (result == CURLE_HTTP_RETURNED_ERROR) {
317 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
318 Com_Printf(
"failed to upload file '%s': %s (%i)\n", fileName, curl_easy_strerror(result), (
int)httpCode);
320 Com_Printf(
"failed to upload file '%s': %s\n", fileName, curl_easy_strerror(result));
322 curl_easy_cleanup(curl);
326 curl_easy_cleanup(curl);
354 CURL* curl = curl_easy_init();
355 char* encoded = curl_easy_escape(curl, url, 0);
356 if (encoded ==
nullptr) {
357 curl_easy_cleanup(curl);
361 const bool success = strlen(encoded) < outLength;
363 curl_easy_cleanup(curl);
385 if (callback !=
nullptr)
398 curl_global_cleanup();
402 void HTTP_PutFile(
const char* formName,
const char* fileName,
const char* url,
const upparam_t* params) {}
406 bool bool HTTP_ExtractComponents(
const char* url,
char* scheme,
size_t schemeLength,
char* host,
size_t hostLength,
char* path,
size_t pathLength,
int*
port) {
return false;}
bool Q_strnull(const char *string)
#define Mem_AllocTypeN(type, n)
size_t HTTP_Header(void *ptr, size_t size, size_t nmemb, void *stream)
libcurl callback to update header info.
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
void HTTP_Cleanup(void)
UFO is exiting or we're changing servers. Clean up.
static bool HTTP_GetURLInternal(dlhandle_t &dl, const char *url, FILE *file, const char *postfields)
Gets a specific url.
void Com_Printf(const char *const fmt,...)
size_t HTTP_Recv(void *ptr, size_t size, size_t nmemb, void *stream)
libcurl callback for HTTP_GetURL
bool HTTP_ExtractComponents(const char *url, char *scheme, size_t schemeLength, char *host, size_t hostLength, char *path, size_t pathLength, int *port)
Extract the servername, the port and the path part of the given url.
void(* http_callback_t)(const char *response, void *userdata)
void Com_Error(int code, const char *fmt,...)
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
#define Q_strncasecmp(s1, s2, n)
static void HTTP_ResolvURL(const char *url, char *buf, size_t size)
Converts the hostname into an ip to work around a bug in libcurl (resp. the resolver) that uses alarm...
bool HTTP_PutFile(const char *formName, const char *fileName, const char *url, const upparam_t *params)
bool HTTP_GetToFile(const char *url, FILE *file, const char *postfields)
Downloads the given url into the given file.
#define Q_strneq(a, b, n)
bool HTTP_Encode(const char *url, char *out, size_t outLength)
This function converts the given url to an URL encoded string. All input characters that are not a-z...
QGL_EXTERN GLuint GLchar GLuint * len
bool HTTP_GetURL(const char *url, http_callback_t callback, void *userdata, const char *postfields)
Downloads the given url and return the data to the callback (optional)
bool NET_ResolvNode(const char *node, char *buf, size_t bufLength)