47#define CURL_GLOBAL_NOTHING 0
48#define CURL_GLOBAL_SSL 1
49#define CURL_GLOBAL_WIN32 2
50#define CURLOPTTYPE_LONG 0
51#define CURLOPTTYPE_OBJECTPOINT 10000
52#define CURLOPTTYPE_FUNCTIONPOINT 20000
53#define CURLOPTTYPE_OFF_T 30000
54#define CINIT(name,type,number) CURLOPT_ ## name = CURLOPTTYPE_ ## type + number
57 CINIT(WRITEDATA, OBJECTPOINT, 1),
58 CINIT(URL, OBJECTPOINT, 2),
59 CINIT(ERRORBUFFER, OBJECTPOINT, 10),
60 CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11),
61 CINIT(POSTFIELDS, OBJECTPOINT, 15),
62 CINIT(REFERER, OBJECTPOINT, 16),
63 CINIT(USERAGENT, OBJECTPOINT, 18),
64 CINIT(LOW_SPEED_LIMIT, LONG , 19),
65 CINIT(LOW_SPEED_TIME, LONG, 20),
66 CINIT(RESUME_FROM, LONG, 21),
67 CINIT(HTTPHEADER, OBJECTPOINT, 23),
68 CINIT(VERBOSE, LONG, 41),
69 CINIT(POST, LONG, 47),
70 CINIT(FOLLOWLOCATION, LONG, 52),
71 CINIT(POSTFIELDSIZE, LONG, 60),
72 CINIT(PRIVATE, OBJECTPOINT, 103),
73 CINIT(PROTOCOLS, LONG, 181),
74 CINIT(REDIR_PROTOCOLS, LONG, 182)
77#define CURLPROTO_HTTP (1<<0)
78#define CURLPROTO_HTTPS (1<<1)
79#define CURLPROTO_FTP (1<<2)
92#define CURLINFO_STRING 0x100000
93#define CURLINFO_LONG 0x200000
94#define CURLINFO_DOUBLE 0x300000
95#define CURLINFO_SLIST 0x400000
96#define CURLINFO_MASK 0x0fffff
97#define CURLINFO_TYPEMASK 0xf00000
159static const char * (*qcurl_easy_strerror) (
CURLcode);
166static CURLMsg * (*qcurl_multi_info_read) (
CURLM *multi_handle,
int *msgs_in_queue);
168static const char * (*qcurl_multi_strerror) (
CURLcode);
198#define LOADTYPE_NONE 0
199#define LOADTYPE_PAK 1
200#define LOADTYPE_CACHEPIC 2
201#define LOADTYPE_SKINFRAME 3
205typedef struct downloadinfo_s
364 const char* dllnames [] =
419 size_t bytes =
size * nmemb;
495 if(!strcmp(content_type,
"image/jpeg"))
497 else if(!strcmp(content_type,
"image/png"))
499 else if(filesize >= 7 && !strncmp((
char *)
data,
"\xFF\xD8", 7))
501 else if(filesize >= 7 && !strncmp((
char *)
data,
"\x89PNG\x0D\x0A\x1A\x0A", 7))
504 Con_Printf(
"Did not detect content type: %s\n", content_type);
520static qbool Curl_Begin(
const char *URL,
const char *extraheaders,
double maxspeed,
const char *
name,
int loadtype,
qbool forthismap,
const char *post_content_type,
const unsigned char *postbuf,
size_t postbufsize,
unsigned char *
buf,
size_t bufsize,
curl_callback_t callback,
void *cbdata);
523 char content_type[64];
556 dp_strlcpy(content_type, content_type_,
sizeof(content_type));
577#define CLEAR_AND_RETRY() \
580 di->stream = FS_OpenRealFile(di->filename, "wb", false); \
581 FS_Close(di->stream); \
582 if(di->startpos && !di->callback) \
584 Curl_Begin(di->url, di->extraheaders, di->maxspeed, di->filename, di->loadtype, di->forthismap, di->post_content_type, di->postbuf, di->postbufsize, NULL, 0, NULL, NULL); \
585 di->forthismap = false; \
603 if(!strncmp(p,
"dlcache/", 8))
620 if(!strncmp(p,
"dlcache/", 8))
651static const char *
CleanURL(
const char *url,
char *urlbuf,
size_t urlbuflength)
653 const char *p, *q, *
r;
656 p = strstr(url,
"://");
659 q = strchr(p + 3,
'@');
662 r = strchr(p + 3,
'/');
665 dpsnprintf(urlbuf, urlbuflength,
"%.*s%s", (
int)(p - url + 3), url, q + 1);
727#ifdef HTTP_USER_AGENT
735 ua =
va(vabuf,
sizeof(vabuf),
"%s%s%s",
737 (ua[0] && ua[
strlen(ua)-1] !=
' ')
758 Con_Printf(
"^1WARNING:^7 for security reasons, please upgrade to libcurl 7.19.4 or above. In a later version of DarkPlaces, HTTP redirect support will be disabled for this libcurl version.\n");
761 if(di->post_content_type)
766 di->slist =
qcurl_slist_append(di->slist,
va(vabuf,
sizeof(vabuf),
"Content-Type: %s", di->post_content_type));
771 h = di->extraheaders;
774 const char *hh = strchr(h,
'\n');
778 memcpy(
buf, h, hh - h);
858 if(!strcasecmp(di->
filename, filename))
886static qbool Curl_Begin(
const char *URL,
const char *extraheaders,
double maxspeed,
const char *
name,
int loadtype,
qbool forthismap,
const char *post_content_type,
const unsigned char *postbuf,
size_t postbufsize,
unsigned char *
buf,
size_t bufsize,
curl_callback_t callback,
void *cbdata)
890 Host_Error(
"Curl_Begin: loadtype and buffer are both set");
905 p = strchr(URL,
':');
908 if(!strncmp(p,
":///", 4) || !strncmp(p,
"://:", 4))
910 char addressstring[128];
913 q = strchr(addressstring,
':');
915 q = addressstring +
strlen(addressstring);
918 dpsnprintf(urlbuf,
sizeof(urlbuf),
"%.*s://%.*s%s", (
int) (p - URL), URL, (
int) (q - addressstring), addressstring, URL + (p - URL) + 3);
962 p = strrchr(
name,
'/');
963 p = p ? (p+1) :
name;
978 if(existingdownloadinfo)
980 Con_Printf(
"Can't download %s, already getting it from %s!\n", fn,
CleanURL(existingdownloadinfo->
url, urlbuf,
sizeof(urlbuf)));
983 if(forthismap && !existingdownloadinfo->
forthismap)
1000 qbool already_loaded;
1001 if(
FS_AddPack(fn, &already_loaded,
true,
true))
1003 Con_DPrintf(
"%s already exists, not downloading!\n", fn);
1026 if(memcmp(
b,
"PK\x03\x04", 4) && memcmp(
b,
"PACK", 4))
1028 Con_DPrintf(
"Detected non-PAK %s, clearing and NOT resuming.\n", fn);
1054 if(strncmp(URL,
"http://", 7) && strncmp(URL,
"ftp://", 6) && strncmp(URL,
"https://", 8))
1056 Con_Printf(
"Curl_Begin(\"%s\"): nasty URL scheme rejected\n", URL);
1080 if(callback ==
NULL)
1091 if(post_content_type)
1115 return Curl_Begin(URL,
NULL, maxspeed,
name, loadtype, forthismap,
NULL,
NULL, 0,
NULL, 0,
NULL,
NULL);
1119 return Curl_Begin(URL,
NULL, maxspeed,
NULL,
false,
false,
NULL,
NULL, 0,
buf, bufsize, callback, cbdata);
1123 return Curl_Begin(URL, extraheaders, maxspeed,
NULL,
false,
false, post_content_type, postbuf, postbufsize,
buf, bufsize, callback, cbdata);
1194 const char *ct =
NULL;
1234 if(di->
maxspeed < maxspeed || maxspeed <= 0)
1378 Con_Print(
"Currently running downloads:\n");
1381 double speed, percent;
1386 Con_Printf(
"(%.1f%% @ %.1f KiB/s)\n", percent, speed / 1024.0);
1426 double maxspeed = 0;
1430 qbool forthismap =
false;
1432 const char *
name = 0;
1436 Con_Print(
"libcurl DLL not found, this command is inactive.\n");
1442 Con_Print(
"curl support not enabled. Set cl_curl_enabled to 1 to enable.\n");
1448 Con_Print(
"usage:\ncurl --info, curl --cancel [filename], curl url\n");
1455 for(
i = 1;
i != end; ++
i)
1458 if(!strcmp(
a,
"--info"))
1463 else if(!strcmp(
a,
"--cancel"))
1477 else if(!strcmp(
a,
"--pak"))
1481 else if(!strcmp(
a,
"--cachepic"))
1485 else if(!strcmp(
a,
"--skinframe"))
1489 else if(!strcmp(
a,
"--for"))
1491 for(
i =
i + 1;
i != end - 1; ++
i)
1499 else if(!strcmp(
a,
"--forthismap"))
1503 else if(!strcmp(
a,
"--as"))
1511 else if(!strcmp(
a,
"--clear_autodownload"))
1518 else if(!strcmp(
a,
"--finish_autodownload"))
1522 char donecommand[256];
1540 else if(!strncmp(
a,
"--maxspeed=", 11))
1542 maxspeed = atof(
a + 11);
1622 *additional_info =
NULL;
1662 dpsnprintf(addinfo, addinfolength,
"(will enter the game when done)");
1665 *additional_info = addinfo;
1668 *additional_info =
NULL;
1703 static char foundurl[1024];
1723 if(pattern && url && patternend)
1743 if(pattern && !patternend)
1745 else if(url && !urlend)
1751 else if(pattern && patternend && !url)
1763typedef struct requirement_s
1821 const char *packurl;
1823 if(!thispack || !*thispack)
1826 p = strrchr(thispack,
'/');
1832 if(packurl && *packurl && strcmp(packurl,
"-"))
1835 dp_strlcat(sendbuffer,
"curl --clear_autodownload\n", sendbuffer_len);
1837 dp_strlcat(sendbuffer,
"curl --pak --forthismap --as ", sendbuffer_len);
1838 dp_strlcat(sendbuffer, thispack, sendbuffer_len);
1841 dp_strlcat(sendbuffer,
" --for ", sendbuffer_len);
1842 dp_strlcat(sendbuffer, filename, sendbuffer_len);
1844 dp_strlcat(sendbuffer, packurl, sendbuffer_len);
1845 dp_strlcat(sendbuffer, thispack, sendbuffer_len);
1846 dp_strlcat(sendbuffer,
"\n", sendbuffer_len);
1856 char sendbuffer[4096] =
"";
1858 qbool foundone =
false;
1869 dp_strlcat(sendbuffer,
"curl --finish_autodownload\n",
sizeof(sendbuffer));
1871 if(
strlen(sendbuffer) + 1 <
sizeof(sendbuffer))
1874 Con_Printf(
"Could not initiate autodownload due to URL buffer overflow\n");
void Cbuf_AddText(cmd_state_t *cmd, const char *text)
void Cmd_AddCommand(unsigned flags, const char *cmd_name, xcommand_t function, const char *description)
called by the init functions of other parts of the program to register commands and functions to call...
cmd_state_t * cmd_local
command interpreter for local commands injected by SVQC, CSQC, MQC, server or client engine code uses...
#define CF_SERVER
cvar/command that only the server can change/execute
static int Cmd_Argc(cmd_state_t *cmd)
static const char * Cmd_Argv(cmd_state_t *cmd, int arg)
Cmd_Argv(cmd, ) will return an empty string (not a NULL) if arg > argc, so string operations are alwa...
#define CF_CLIENT
cvar/command that only the client can change/execute
#define CF_CLIENT_FROM_SERVER
command that the server is allowed to execute on the client
#define CF_ARCHIVE
cvar should have its set value saved to config.cfg and persist across sessions
size_t InfoString_GetValue(const char *buffer, const char *key, char *value, size_t valuesize)
Returns the number of bytes written to *value excluding the \0 terminator.
static void List_Add(llist_t *node, llist_t *head)
#define List_First_Entry(ptr, type, member)
static void List_Delete(llist_t *node)
#define List_For_Each_Entry_Safe(pos, n, head, type, member)
#define List_For_Each_Entry(pos, head, type, member)
static qbool List_Is_Empty(const llist_t *list)
char com_token[MAX_INPUTLINE]
char * va(char *buf, size_t buflen, const char *format,...)
qbool COM_ParseToken_Simple(const char **datapointer, qbool returnnewline, qbool parsebackslash, qbool parsecomments)
int dpsnprintf(char *buffer, size_t buffersize, const char *format,...)
Returns the number of printed characters, excluding the final '\0' or returns -1 if the buffer isn't ...
#define dp_strlcat(dst, src, dsize)
#define dp_strlcpy(dst, src, dsize)
void Con_Print(const char *msg)
Prints to all appropriate console targets, and adds timestamps.
void Con_DPrintf(const char *fmt,...)
A Con_Printf that only shows up if the "developer" cvar is set.
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
void Cvar_RegisterVariable(cvar_t *variable)
registers a cvar that already has the name, string, and optionally the archive elements set.
void Cvar_RegisterVirtual(cvar_t *variable, const char *name)
char engineversion[128]
version string for the corner of the console, crash messages, status command, etc
cachepic_t * Draw_NewPic(const char *picname, int width, int height, unsigned char *pixels, textype_t textype, int texflags)
int matchpattern(const char *in, const char *pattern, int caseinsensitive)
fs_offset_t FS_Read(qfile_t *file, void *buffer, size_t buffersize)
fs_offset_t FS_Write(qfile_t *file, const void *data, size_t datasize)
unsigned char * FS_LoadFile(const char *path, mempool_t *pool, qbool quiet, fs_offset_t *filesizepointer)
fs_offset_t FS_Tell(qfile_t *file)
int FS_Seek(qfile_t *file, fs_offset_t offset, int whence)
qfile_t * FS_OpenRealFile(const char *filepath, const char *mode, qbool quiet)
qbool FS_AddPack(const char *pakfile, qbool *already_loaded, qbool keep_plain_dirs, qbool dlcache)
int FS_Close(qfile_t *file)
const char * FS_WhichPack(const char *filename)
const char * FS_FileExists(const char *filename)
Look for a file in the packages and in the filesystem Returns its canonical name (same case as used i...
skinframe_t * R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, int comparewidth, int compareheight, int comparecrc, qbool sRGB)
GLsizei const GLchar ** string
GLenum GLuint GLenum GLsizei length
GLsizeiptr const GLvoid * data
GLint GLenum GLenum GLvoid * pixels
GLenum GLuint GLenum GLsizei const GLchar * buf
void Host_Error(const char *error,...)
unsigned char * PNG_LoadImage_BGRA(const unsigned char *raw, int filesize, int *miplevel)
unsigned char * JPEG_LoadImage_BGRA(const unsigned char *f, int filesize, int *miplevel)
static void curl_default_callback(int status, size_t length_received, unsigned char *buffer, void *cbdata)
static CURLMcode(* qcurl_multi_wait)(CURLM *multi_handle, void *, unsigned int extra_nfds, int timeout_ms, int *ret)
static dllhandle_t curl_dll
static cvar_t curl_useragent
static const char *(* qcurl_multi_strerror)(CURLcode)
static void CURL_CloseLibrary(void)
static cvar_t curl_enabled
static char command_when_error[256]
static int numdownloads_success
void Curl_Register_predownload(void)
static int numdownloads_fail
static void Curl_Curl_f(cmd_state_t *cmd)
void Curl_Init_Commands(void)
static const char *(* qcurl_easy_strerror)(CURLcode)
static double bytes_received
void Curl_SendRequirements(void)
void Curl_Clear_forthismap(void)
bool Curl_Select(int timeout_ms)
struct curl_slist curl_slist
static const char * Curl_FindPackURL(const char *filename)
static qbool CURL_OpenLibrary(void)
Curl_downloadinfo_t * Curl_GetDownloadInfo(int *nDownloads, const char **additional_info, char *addinfo, size_t addinfolength)
static void(* qcurl_global_cleanup)(void)
qbool Curl_Have_forthismap(void)
static double Curl_GetDownloadAmount(downloadinfo *di)
static size_t CURL_fwrite(void *data, size_t size, size_t nmemb, void *vdi)
static void CheckPendingDownloads(void)
static CURL *(* qcurl_easy_init)(void)
static void(* qcurl_global_init)(long flags)
@ CURL_DOWNLOAD_SERVERERROR
static void Curl_CommandWhenDone(const char *cmd)
static downloadinfo * Curl_Find(const char *filename)
static cvar_t sv_curl_serverpackages
static const char * CleanURL(const char *url, char *urlbuf, size_t urlbuflength)
static void Curl_EndDownload(downloadinfo *di, CurlStatus status, CURLcode error, const char *content_type_)
static double Curl_GetDownloadSpeed(downloadinfo *di)
static qbool Curl_SendRequirement(const char *filename, qbool foundone, char *sendbuffer, size_t sendbuffer_len)
#define CINIT(name, type, number)
static requirement * requirements
static CURLMcode(* qcurl_multi_add_handle)(CURLM *multi_handle, CURL *easy_handle)
static void Curl_CommandWhenError(const char *cmd)
static void(* qcurl_easy_cleanup)(CURL *handle)
void Curl_ClearRequirements(void)
static CURLMcode(* qcurl_multi_perform)(CURLM *multi_handle, int *running_handles)
qbool Curl_Begin_ToFile(const char *URL, double maxspeed, const char *name, int loadtype, qbool forthismap)
static curl_slist *(* qcurl_slist_append)(curl_slist *list, const char *string)
qbool Curl_Begin_ToMemory_POST(const char *URL, const char *extraheaders, double maxspeed, const char *post_content_type, const unsigned char *postbuf, size_t postbufsize, unsigned char *buf, size_t bufsize, curl_callback_t callback, void *cbdata)
#define CLEAR_AND_RETRY()
static void Curl_CheckCommandWhenDone(void)
static cvar_t curl_useragent_append
qbool Curl_Available(void)
@ CURLM_CALL_MULTI_PERFORM
static CURLcode(* qcurl_easy_getinfo)(CURL *handle, CURLINFO info,...)
static CURLcode(* qcurl_easy_setopt)(CURL *handle, CURLoption option,...)
static int numdownloads_added
static CURLMcode(* qcurl_multi_remove_handle)(CURLM *multi_handle, CURL *easy_handle)
qbool Curl_Begin_ToMemory(const char *URL, double maxspeed, unsigned char *buf, size_t bufsize, curl_callback_t callback, void *cbdata)
static cvar_t curl_maxdownloads
void Curl_CancelAll(void)
@ CURLINFO_HTTPAUTH_AVAIL
@ CURLINFO_SSL_VERIFYRESULT
@ CURLINFO_PRETRANSFER_TIME
@ CURLINFO_CONTENT_LENGTH_UPLOAD
@ CURLINFO_PROXYAUTH_AVAIL
@ CURLINFO_NAMELOOKUP_TIME
@ CURLINFO_REDIRECT_COUNT
@ CURLINFO_HTTP_CONNECTCODE
@ CURLINFO_CONTENT_LENGTH_DOWNLOAD
@ CURLINFO_SPEED_DOWNLOAD
@ CURLINFO_STARTTRANSFER_TIME
static void curl_quiet_callback(int status, size_t length_received, unsigned char *buffer, void *cbdata)
static char command_when_done[256]
static unsigned char * decode_image(downloadinfo *di, const char *content_type)
static CURLM *(* qcurl_multi_init)(void)
void Curl_RequireFile(const char *filename)
static cvar_t sv_curl_maxspeed
static qbool Curl_Begin(const char *URL, const char *extraheaders, double maxspeed, const char *name, int loadtype, qbool forthismap, const char *post_content_type, const unsigned char *postbuf, size_t postbufsize, unsigned char *buf, size_t bufsize, curl_callback_t callback, void *cbdata)
static dllfunction_t curlfuncs[]
static void(* qcurl_slist_free_all)(curl_slist *list)
static void(* qcurl_multi_cleanup)(CURLM *)
void Curl_Cancel_ToMemory(curl_callback_t callback, void *cbdata)
static CURLMsg *(* qcurl_multi_info_read)(CURLM *multi_handle, int *msgs_in_queue)
static void Curl_Info_f(cmd_state_t *cmd)
static cvar_t developer_curl
#define LOADTYPE_CACHEPIC
static cvar_t curl_maxspeed
static cvar_t sv_curl_defaulturl
#define LOADTYPE_SKINFRAME
@ CURLCBSTATUS_SERVERERROR
void(* curl_callback_t)(int status, size_t length_received, unsigned char *buffer, void *cbdata)
#define MAX_OSPATH
max length of a filesystem pathname
#define TEXF_FORCE_RELOAD
void SV_ClientCommands(const char *fmt,...) DP_FUNC_PRINTF(1)
char userinfo[MAX_USERINFO_STRING]
command interpreter state - the tokenizing and execution of commands, as well as pointers to which cv...
char filename[MAX_OSPATH]
double bytes_received_curl
const char * extraheaders
const char * post_content_type
const unsigned char * postbuf
double realtime
the accumulated mainloop time since application started (with filtering), without any slowmo or clamp...
char filename[MAX_OSPATH]
struct requirement_s * next
qbool Sys_LoadDependency(const char **dllnames, dllhandle_t *handle, const dllfunction_t *fcts)
void Sys_FreeLibrary(dllhandle_t *handle)
#define Thread_DestroyMutex(m)
qbool Thread_HasThreads(void)
#define Thread_CreateMutex()
#define Thread_LockMutex(m)
#define Thread_UnlockMutex(m)
#define Mem_Alloc(pool, size)