Updated to libcurl 7.69.1 with HTTPS support.

Added UDP fallback from HTTP downloads and support for Q2Pro-style HTTP URLs.
Now allows downloading non-numerical pak files via flagging certain paks as protected.
Misc filesystem changes.
This commit is contained in:
Knightmare66 2020-04-30 02:10:27 -04:00
parent 02755e0181
commit 65b0c2281e
23 changed files with 1840 additions and 892 deletions

View file

@ -39,6 +39,26 @@ int precache_pak; // Knightmare added
byte *precache_model; // used for skin checking in alias models
#ifdef USE_CURL
qboolean precache_forceUDP = false; // force all downloads to UDP
qboolean filelistUseGamedir = false;
// HTTP Fallback handling
// First we're trying to download all files over HTTP with r1q2-style URLs.
// If we encountered errors, we reset the complete precacher state and retry with HTTP and q2pro-style URLs.
// If we still got errors we're falling back to UDP.
// Iteration 1: Initial state, R1Q2-style URLs.
// Iteration 2: Q2Pro-style URLs.
// Iteration 3: UDP downloads.
typedef enum {
ITER_HTTP_R1Q2 = 0,
ITER_HTTP_Q2PRO = 1,
ITER_UDP = 2,
} precacheIteration_t;
static precacheIteration_t precache_iteration = ITER_HTTP_R1Q2;
#endif // USE_CURL
#define PLAYER_MULT 5
// ENV_CNT is map load, ENV_CNT+1 is first env map
@ -105,8 +125,28 @@ void CL_RequestNextDownload (void)
texture_cnt = TEXTURE_CNT;
}
// YQ2 Q2pro download addition
#ifdef USE_CURL
if (precache_iteration == ITER_HTTP_R1Q2) {
CL_HTTP_SetDownloadGamedir (cl.gamedir);
}
else if (precache_iteration == ITER_HTTP_Q2PRO)
{
if (cl.gamedir[0] == '\0')
CL_HTTP_SetDownloadGamedir (BASEDIRNAME);
else
CL_HTTP_SetDownloadGamedir (cl.gamedir);
// try filelist again with a different path
filelistUseGamedir = true;
CL_HTTP_EnableGenericFilelist ();
}
else { // if (precache_iteration == ITER_UDP)
precache_forceUDP = true;
}
#endif // USE_CURL
// Skip to loading map if downloading disabled or on local server
if ( (Com_ServerState() || !allow_download->value) && precache_check < env_cnt)
if ( (Com_ServerState() || !allow_download->integer) && precache_check < env_cnt)
precache_check = env_cnt;
// Try downloading pk3 file for current map from server, hack by Jay Dolan
@ -122,22 +162,25 @@ void CL_RequestNextDownload (void)
// ZOID
if (precache_check == CS_MODELS) { // confirm map
precache_check = CS_MODELS+2; // 0 isn't used
if (allow_download_maps->value)
if (allow_download_maps->integer) {
if (!CL_CheckOrDownloadFile(cl.configstrings[CS_MODELS+1]))
return; // started a download
}
}
if (precache_check >= CS_MODELS && precache_check < CS_MODELS+max_models)
{
if (allow_download_models->value)
if (allow_download_models->integer)
{
while (precache_check < CS_MODELS+max_models &&
cl.configstrings[precache_check][0]) {
cl.configstrings[precache_check][0])
{
if (cl.configstrings[precache_check][0] == '*' ||
cl.configstrings[precache_check][0] == '#') {
precache_check++;
continue;
}
if (precache_model_skin == 0) {
if (precache_model_skin == 0)
{
if (!CL_CheckOrDownloadFile(cl.configstrings[precache_check])) {
precache_model_skin = 1;
return; // started a download
@ -147,14 +190,14 @@ void CL_RequestNextDownload (void)
#ifdef USE_CURL // HTTP downloading from R1Q2
// pending downloads (models), let's wait here before we can check skins.
if ( CL_PendingHTTPDownloads() )
if ( CL_PendingHTTPDownloads() ) {
return;
}
#endif // USE_CURL
// checking for skins in the model
if (!precache_model)
{
FS_LoadFile (cl.configstrings[precache_check], (void **)&precache_model);
if (!precache_model) {
precache_model_skin = 0;
@ -228,7 +271,8 @@ void CL_RequestNextDownload (void)
else if (strlen(skinname) > MAX_SKINNAME-1)
Com_Error (ERR_DROP, "Model %s has too long a skin path: %s", cl.configstrings[precache_check], skinname);
if (!CL_CheckOrDownloadFile(skinname)) {
if (!CL_CheckOrDownloadFile(skinname))
{
precache_model_skin++;
return; // started a download
}
@ -300,8 +344,7 @@ void CL_RequestNextDownload (void)
}
if (precache_check >= cs_sounds && precache_check < cs_sounds+max_sounds)
{
if (allow_download_sounds->value)
{
if (allow_download_sounds->integer) {
if (precache_check == cs_sounds)
precache_check++; // zero is blank
while (precache_check < cs_sounds+max_sounds &&
@ -317,13 +360,12 @@ void CL_RequestNextDownload (void)
}
precache_check = cs_images;
}
if (precache_check >= cs_images && precache_check < cs_images+max_images)
if (precache_check >= cs_images && precache_check < CS_IMAGES+max_images)
{
if (precache_check == cs_images)
precache_check++; // zero is blank
while (precache_check < cs_images+max_images &&
cl.configstrings[precache_check][0])
{
cl.configstrings[precache_check][0]) {
Com_sprintf(fn, sizeof(fn), "pics/%s.pcx", cl.configstrings[precache_check++]);
if (!CL_CheckOrDownloadFile(fn))
return; // started a download
@ -335,7 +377,7 @@ void CL_RequestNextDownload (void)
// so precache_check is now *3
if (precache_check >= cs_playerskins && precache_check < cs_playerskins + MAX_CLIENTS * PLAYER_MULT)
{
if (allow_download_players->value)
if (allow_download_players->integer)
{
while (precache_check < cs_playerskins + MAX_CLIENTS * PLAYER_MULT)
{
@ -427,8 +469,21 @@ void CL_RequestNextDownload (void)
#ifdef USE_CURL // HTTP downloading from R1Q2
// pending downloads (possibly the map), let's wait here.
if ( CL_PendingHTTPDownloads() )
if ( CL_PendingHTTPDownloads() ) {
return;
}
// YQ2 UDP fallback addition
if ( CL_CheckHTTPError() ) // Download errors detected, so start over with next iteration
{
precache_iteration++;
if (precache_iteration == ITER_HTTP_Q2PRO)
Com_Printf ("[HTTP] One or more HTTP downloads failed on R1Q2 path, falling back to Q2Pro path.\n");
else // if (precache_iteration == ITER_UDP)
Com_Printf ("[HTTP] One or more HTTP downloads failed on both R1Q2 and Q2Pro paths, falling back to UDP.\n");
CL_ResetPrecacheCheck ();
CL_RequestNextDownload ();
return;
}
#endif // USE_CURL
if (precache_check == env_cnt)
@ -449,7 +504,7 @@ void CL_RequestNextDownload (void)
if (precache_check > env_cnt && precache_check < texture_cnt)
{
if (allow_download->value && allow_download_maps->value)
if (allow_download->integer && allow_download_maps->integer)
{
while (precache_check < texture_cnt)
{
@ -472,14 +527,14 @@ void CL_RequestNextDownload (void)
precache_check = texture_cnt+1;
precache_tex = 0;
}
// confirm existance of .wal textures, download any that don't exist
if (precache_check == texture_cnt+1)
{
// from qcommon/cmodel.c
{ // from qcommon/cmodel.c
extern int numtexinfo;
extern mapsurface_t map_surfaces[];
if (allow_download->value && allow_download_maps->value)
if (allow_download->integer && allow_download_maps->integer)
{
while (precache_tex < numtexinfo)
{
@ -490,19 +545,19 @@ void CL_RequestNextDownload (void)
return; // started a download
}
}
//precache_check = texture_cnt+999;
// precache_check = texture_cnt+999;
precache_check = texture_cnt+2;
precache_tex = 0;
}
// confirm existance of .tga textures, try to download any that don't exist
if (precache_check == texture_cnt+2)
{
// from qcommon/cmodel.c
{ // from qcommon/cmodel.c
extern int numtexinfo;
extern mapsurface_t map_surfaces[];
if (allow_download->value && allow_download_maps->value && allow_download_textures_24bit->value)
if (allow_download->integer && allow_download_maps->integer
&& allow_download_textures_24bit->integer)
{
while (precache_tex < numtexinfo)
{
@ -524,7 +579,8 @@ void CL_RequestNextDownload (void)
extern int numtexinfo;
extern mapsurface_t map_surfaces[];
if (allow_download->value && allow_download_maps->value && allow_download_textures_24bit->value)
if (allow_download->integer && allow_download_maps->integer
&& allow_download_textures_24bit->integer)
{
while (precache_tex < numtexinfo)
{
@ -545,12 +601,12 @@ void CL_RequestNextDownload (void)
// confirm existance of .jpg textures, try to download any that don't exist
if (precache_check == texture_cnt+3)
#endif // PNG_SUPPORT
{
// from qcommon/cmodel.c
{ // from qcommon/cmodel.c
extern int numtexinfo;
extern mapsurface_t map_surfaces[];
if (allow_download->value && allow_download_maps->value && allow_download_textures_24bit->value)
if (allow_download->integer && allow_download_maps->integer
&& allow_download_textures_24bit->integer)
{
while (precache_tex < numtexinfo)
{
@ -563,12 +619,20 @@ void CL_RequestNextDownload (void)
}
precache_check = texture_cnt+999;
}
//ZOID
// ZOID
#ifdef USE_CURL // HTTP downloading from R1Q2
// pending downloads (possibly textures), let's wait here.
if ( CL_PendingHTTPDownloads() )
if ( CL_PendingHTTPDownloads() ) {
return;
}
// This map is done downloading, reset HTTP for next map
precache_forceUDP = false;
filelistUseGamedir = false;
precache_iteration = ITER_HTTP_R1Q2;
CL_HTTP_EnableGenericFilelist (); // re-enable generic filelists for next map
#endif // USE_CURL
CL_RegisterSounds ();
@ -582,12 +646,22 @@ void CL_RequestNextDownload (void)
//=============================================================================
void CL_DownloadFileName(char *dest, int destlen, char *fn)
/*
===============
CL_DownloadFileName
===============
*/
void CL_DownloadFileName (char *dest, int destlen, char *fn)
{
if (strncmp(fn, "players", 7) == 0)
Com_sprintf (dest, destlen, "%s/%s", BASEDIRNAME, fn);
if ( !stricmp(FS_Downloaddir(), FS_Gamedir()) ) // use basedir/gamedir if fs_downloaddir is the same as fs_gamedir
{
if (strncmp(fn, "players", 7) == 0)
Com_sprintf (dest, destlen, "%s/%s", BASEDIRNAME, fn);
else
Com_sprintf (dest, destlen, "%s/%s", FS_Gamedir(), fn); // was FS_Gamedir()
}
else
Com_sprintf (dest, destlen, "%s/%s", FS_Gamedir(), fn);
Com_sprintf (dest, destlen, "%s/%s", FS_Downloaddir(), fn);
}
@ -611,6 +685,7 @@ void CL_InitFailedDownloadList (void)
failedDlListIndex = 0;
}
/*
===============
CL_CheckDownloadFailed
@ -630,6 +705,7 @@ qboolean CL_CheckDownloadFailed (char *name)
return false;
}
/*
===============
CL_AddToFailedDownloadList
@ -639,7 +715,7 @@ void CL_AddToFailedDownloadList (char *name)
{
int i;
qboolean found = false;
qboolean added = false;
// qboolean added = false;
// check if this name is already in the table
for (i=0; i<NUM_FAIL_DLDS; i++)
@ -653,7 +729,8 @@ void CL_AddToFailedDownloadList (char *name)
// if it isn't already in the table, then we need to add it
if (!found)
{
Com_sprintf(lastfaileddownload[failedDlListIndex++], sizeof(lastfaileddownload[failedDlListIndex++]), "%s", name);
Com_sprintf(lastfaileddownload[failedDlListIndex], sizeof(lastfaileddownload[failedDlListIndex]), "%s", name);
failedDlListIndex++;
// wrap around to start of list
if (failedDlListIndex >= NUM_FAIL_DLDS)
@ -661,6 +738,7 @@ void CL_AddToFailedDownloadList (char *name)
}
}
/*
===============
CL_CheckOrDownloadFile
@ -671,11 +749,11 @@ to start a download from the server.
*/
qboolean CL_CheckOrDownloadFile (char *filename)
{
FILE *fp;
FILE *fp;
char name[MAX_OSPATH];
int len; // Knightmare added
char s[128];
//int i;
int len; // Knightmare added
char s[128];
//int i;
if (strstr (filename, ".."))
{
@ -694,7 +772,7 @@ qboolean CL_CheckOrDownloadFile (char *filename)
#ifdef PNG_SUPPORT
// don't download a .png texture which already has a .tga counterpart
len = strlen(filename);
len = (int)strlen(filename);
// strncpy(s, filename);
Q_strncpyz(s, filename, sizeof(s));
if (strstr(s, "textures/") && !strcmp(s+len-4, ".png")) // look if we have a .png texture
@ -705,9 +783,9 @@ qboolean CL_CheckOrDownloadFile (char *filename)
}
#endif // PNG_SUPPORT
// don't download a .jpg texture which already has a .tga counterpart
len = strlen(filename);
// strncpy(s,filename);
// don't download a .jpg texture which already has a .tga or .png counterpart
len = (int)strlen(filename);
// strncpy(s, filename);
Q_strncpyz(s, filename, sizeof(s));
if (strstr(s, "textures/") && !strcmp(s+len-4, ".jpg")) // look if we have a .jpg texture
{
@ -722,15 +800,32 @@ qboolean CL_CheckOrDownloadFile (char *filename)
}
#ifdef USE_CURL // HTTP downloading from R1Q2
if ( CL_QueueHTTPDownload(filename) )
if (!precache_forceUDP) // YQ2 UDP fallback additon
{
// We return true so that the precache check keeps feeding us more files.
// Since we have multiple HTTP connections we want to minimize latency
// and be constantly sending requests, not one at a time.
return true;
if ( CL_QueueHTTPDownload(filename, filelistUseGamedir) )
{
// We return true so that the precache check keeps feeding us more files.
// Since we have multiple HTTP connections we want to minimize latency
// and be constantly sending requests, not one at a time.
return true;
}
}
else
else // YQ2 UDP fallback additon
{
/* There are 2 cases that get us here:
1. forceUDP was set after a 404. In this case we want to retry that
single file over UDP and all later files over HTTP.
2. forceUDP was set after another error code. In that case the HTTP
code aborts all HTTP downloads and CL_QueueHTTPDownload() returns false.
*/
precache_forceUDP = false;
/* We might be connected to an r1q2-style HTTP server that missed just one file.
So reset the precacher iteration counter to start over.
*/
precache_iteration = ITER_HTTP_R1Q2;
}
// else
// {
#endif // USE_CURL
// strncpy (cls.downloadname, filename);
@ -746,12 +841,13 @@ qboolean CL_CheckOrDownloadFile (char *filename)
//ZOID
// check to see if we already have a tmp for this file, if so, try to resume
// open the file if not opened yet
CL_DownloadFileName(name, sizeof(name), cls.downloadtempname);
CL_DownloadFileName (name, sizeof(name), cls.downloadtempname);
// FS_CreatePath (name);
fp = fopen (name, "r+b");
if (fp) { // it exists
if (fp)
{ // it exists
int len;
fseek(fp, 0, SEEK_END);
len = ftell(fp);
@ -776,10 +872,11 @@ qboolean CL_CheckOrDownloadFile (char *filename)
return false;
#ifdef USE_CURL // HTTP downloading from R1Q2
}
// }
#endif // USE_CURL
}
/*
===============
CL_Download_f
@ -841,7 +938,7 @@ void CL_ParseDownload (void)
{
int size, percent;
char name[MAX_OSPATH];
int r;//, i;
int r; // i
// read the data
size = MSG_ReadShort (&net_message);
@ -868,7 +965,7 @@ void CL_ParseDownload (void)
{
CL_Download_Reset_KBps_counter (); // Knightmare- for KB/s counter
CL_DownloadFileName(name, sizeof(name), cls.downloadtempname);
CL_DownloadFileName (name, sizeof(name), cls.downloadtempname);
FS_CreatePath (name);
@ -909,13 +1006,13 @@ void CL_ParseDownload (void)
char oldn[MAX_OSPATH];
char newn[MAX_OSPATH];
// Com_Printf ("100%%\n");
// Com_Printf ("100%%\n");
fclose (cls.download);
// rename the temp file to it's final name
CL_DownloadFileName(oldn, sizeof(oldn), cls.downloadtempname);
CL_DownloadFileName(newn, sizeof(newn), cls.downloadname);
CL_DownloadFileName (oldn, sizeof(oldn), cls.downloadtempname);
CL_DownloadFileName (newn, sizeof(newn), cls.downloadname);
r = rename (oldn, newn);
if (r)
Com_Printf ("failed to rename.\n");
@ -925,7 +1022,7 @@ void CL_ParseDownload (void)
// add new pk3s to search paths, hack by Jay Dolan
if (strstr(newn, ".pk3"))
FS_AddPK3File (newn);
FS_AddPK3File (newn, false);
// get another file if needed

View file

@ -40,8 +40,11 @@ static int pendingCount = 0;
static int abortDownloads = HTTPDL_ABORT_NONE;
static qboolean downloading_pak = false;
static qboolean httpDown = false;
static qboolean thisMapAbort = false; // Knightmare- whether to fall back to UDP for this map
static int prevSize; // Knightmare- for KBps counter
static qboolean thisMapAbort = false; // Knightmare- whether to fall back to UDP for this map
static int prevSize; // Knightmare- for KBps counter
static qboolean downloadError = false; // YQ2 UDP fallback addition
static qboolean downloadFileList = true; // YQ2 addition for downloading filelist once
static char remoteGamedir[MAX_QPATH]; // YQ2 addition for Q2Pro downloads
/*
===============================
@ -162,11 +165,6 @@ static size_t /*EXPORT*/ CL_HTTP_Header (void *ptr, size_t size, size_t nmemb, v
return bytes;
}
/*void CL_RemoveHTTPDownload (const char *quakePath)
{
}*/
/*
===============
CL_EscapeHTTPPath
@ -205,8 +203,8 @@ static void CL_EscapeHTTPPath (const char *filePath, char *escaped)
}
p[0] = 0;
//using ./ in a url is legal, but all browsers condense the path and some IDS / request
//filtering systems act a bit funky if http requests come in with uncondensed paths.
// using ./ in a url is legal, but all browsers condense the path and some IDS / request
// filtering systems act a bit funky if http requests come in with uncondensed paths.
len = strlen(escaped);
p = escaped;
while ((p = strstr (p, "./")))
@ -272,6 +270,41 @@ int /*EXPORT*/ CL_CURL_Debug (CURL *c, curl_infotype type, char *data, size_t si
return 0;
}
/*void CL_RemoveHTTPDownload (const char *quakePath)
{
}*/
/*
===============
CL_RemoveDownloadFromQueue
Adapted from Yamagi Quake2.
Removes an entry from the download queue.
===============
*/
#if 1
qboolean CL_RemoveDownloadFromQueue (dlqueue_t *entry)
{
dlqueue_t *last = &cls.downloadQueue;
dlqueue_t *cur = last->next;
while (cur)
{
if (last->next == entry)
{
last->next = cur->next;
Z_Free (cur);
cur = NULL;
return true;
}
last = cur;
cur = cur->next;
}
return false;
}
#endif
/*
===============
CL_StartHTTPDownload
@ -283,11 +316,11 @@ handle.
static void CL_StartHTTPDownload (dlqueue_t *entry, dlhandle_t *dl)
{
size_t len;
char tempFile[MAX_OSPATH];
char remoteFilePath[MAX_OSPATH]; // Knightmare added
char escapedFilePath[MAX_QPATH*4];
//yet another hack to accomodate filelists, how i wish i could push :(
//NULL file handle indicates filelist.
// yet another hack to accomodate filelists, how i wish i could push :(
// NULL file handle indicates filelist.
len = strlen (entry->quakePath);
if (len > 9 && !strcmp (entry->quakePath + len - 9, ".filelist"))
{
@ -298,24 +331,31 @@ static void CL_StartHTTPDownload (dlqueue_t *entry, dlhandle_t *dl)
{
CL_HTTP_Reset_KBps_counter (); // Knightmare- for KB/s counter
Com_sprintf (dl->filePath, sizeof(dl->filePath), "%s/%s", FS_Gamedir(), entry->quakePath);
Com_sprintf (dl->filePath, sizeof(dl->filePath), "%s/%s", FS_Downloaddir(), entry->quakePath); // was FS_Gamedir()
// Com_sprintf (remoteFilePath, sizeof(remoteFilePath), "/%s/%s", cl.gamedir, entry->quakePath); // always use cl.gamedir (with leading slash) for remote server path
// YQ2 Q2pro download addition
// Use remoteGamedir for remote server path if set
if (remoteGamedir[0] == '\0')
Com_sprintf (remoteFilePath, sizeof(remoteFilePath), "/%s", entry->quakePath);
else
Com_sprintf (remoteFilePath, sizeof(remoteFilePath), "/%s/%s", remoteGamedir, entry->quakePath);
Com_sprintf (tempFile, sizeof(tempFile), "%s/%s", cl.gamedir, entry->quakePath);
CL_EscapeHTTPPath (dl->filePath, escapedFilePath);
// CL_EscapeHTTPPath (dl->filePath, escapedFilePath);
CL_EscapeHTTPPath (remoteFilePath, escapedFilePath);
// strncat (dl->filePath, ".tmp");
Q_strncatz (dl->filePath, ".tmp", sizeof(dl->filePath));
FS_CreatePath (dl->filePath);
//don't bother with http resume... too annoying if server doesn't support it.
// don't bother with http resume... too annoying if server doesn't support it.
dl->file = fopen (dl->filePath, "wb");
if (!dl->file)
{
Com_Printf ("CL_StartHTTPDownload: Couldn't open %s for writing.\n", dl->filePath);
entry->state = DLQ_STATE_DONE;
pendingCount--; // Knightmare- fix for curl_update limbo from [HCI]Maraa'kate
//CL_RemoveHTTPDownload (entry->quakePath);
// CL_RemoveHTTPDownload (entry->quakePath);
return;
}
}
@ -392,6 +432,8 @@ A new server is specified, so we nuke all our state.
void CL_SetHTTPServer (const char *URL)
{
dlqueue_t *q, *last;
char *fixedURL = NULL;
size_t URLlen;
CL_HTTP_Cleanup (false);
@ -422,10 +464,28 @@ void CL_SetHTTPServer (const char *URL)
abortDownloads = HTTPDL_ABORT_NONE;
handleCount = pendingCount = 0;
strncpy (cls.downloadServer, URL, sizeof(cls.downloadServer)-1);
// strncpy (cls.downloadServer, URL, sizeof(cls.downloadServer)-1);
// from YQ2: remove trailing '/' from URL
URLlen = strlen(URL);
fixedURL = strdup(URL);
if (fixedURL[URLlen-1] == '/') {
fixedURL[URLlen-1] = '\0';
}
// From Q2Pro- ignore non-HTTP DL server URLs
if ( (strncmp(fixedURL, "http://", 7) != 0) && (strncmp(fixedURL, "https://", 8) != 0) ) {
Com_Printf("[HTTP] Ignoring download server with non-HTTP protocol.\n");
return;
}
Q_strncpyz (cls.downloadServer, fixedURL, sizeof(cls.downloadServer));
free(fixedURL);
fixedURL = NULL;
// FS: Added because Whale's Weapons HTTP server rejects you after a lot of 404s. Then you lose HTTP until a hard reconnect.
cls.downloadServerRetry[0] = 0;
downloadError = false; // YQ2 UDP fallback addition- reset this for new server
}
/*
===============
@ -434,7 +494,6 @@ CL_CancelHTTPDownloads
Cancel all downloads and nuke the queue.
===============
*/
void CL_ResetPrecacheCheck (void);
void CL_CancelHTTPDownloads (qboolean permKill)
{
dlqueue_t *q;
@ -470,21 +529,24 @@ Called from the precache check to queue a download. Return value of
false will cause standard UDP downloading to be used instead.
===============
*/
qboolean CL_QueueHTTPDownload (const char *quakePath)
qboolean CL_QueueHTTPDownload (const char *quakePath, qboolean filelistUseGamedir)
{
size_t len;
dlqueue_t *q, *check, *last;
qboolean needList, isPak = false, isFilelist = false;
qboolean needList = false, isPak = false, isFilelist = false;
// no http server (or we got booted)
if (!cls.downloadServer[0] || abortDownloads || thisMapAbort || !cl_http_downloads->value)
if (!cls.downloadServer[0] || abortDownloads || thisMapAbort || !cl_http_downloads->integer)
return false;
needList = false;
// needList = false;
// first download queued, so we want the mod filelist
if (!cls.downloadQueue.next && cl_http_filelists->value)
// if ( !cls.downloadQueue.next && cl_http_filelists->integer ) {
if ( downloadFileList && cl_http_filelists->integer ) {
needList = true;
downloadFileList = false;
}
len = strlen (quakePath);
if (len > 4 && (!Q_stricmp((char *)quakePath + len - 4, ".pak") || !Q_stricmp((char *)quakePath + len - 4, ".pk3")) )
@ -542,8 +604,16 @@ qboolean CL_QueueHTTPDownload (const char *quakePath)
if (needList)
{
//grab the filelist
CL_QueueHTTPDownload (va("%s.filelist", cl.gamedir));
// grab the filelist
// CL_QueueHTTPDownload (va("%s.filelist", cl.gamedir));
// YQ2 Q2pro download addition
if (filelistUseGamedir) {
CL_QueueHTTPDownload (va("/%s/.filelist", remoteGamedir), false);
}
else {
// YQ2 uses /.filelist here instead of /<modname>.filelist, but I've found that doesn't work on R1Q2 servers
CL_QueueHTTPDownload (va("/%s.filelist", cl.gamedir), false); // YQ2 change- added leading slash
}
// this is a nasty hack to let the server know what we're doing so admins don't
// get confused by a ton of people stuck in CNCT state. it's assumed the server
@ -556,20 +626,26 @@ qboolean CL_QueueHTTPDownload (const char *quakePath)
MSG_WriteString (&cls.netchan.message, "download http\n");
}
// special case for map file lists, i really wanted a server-push mechanism for this, but oh well
// special case for map file lists, I really wanted a server-push mechanism for this, but oh well
len = strlen (quakePath);
if (cl_http_filelists->value && len > 4 && !Q_stricmp ((char *)(quakePath + len - 4), ".bsp"))
if (cl_http_filelists->integer && len > 4 && !Q_stricmp ((char *)(quakePath + len - 4), ".bsp"))
{
char listPath[MAX_OSPATH];
char filePath[MAX_OSPATH];
Com_sprintf (filePath, sizeof(filePath), "%s/%s", cl.gamedir, quakePath);
// Com_sprintf (filePath, sizeof(filePath), "%s/%s", cl.gamedir, quakePath);
// YQ2 Q2pro download addition
// Use remoteGamedir for remote server path if set
if (remoteGamedir[0] == '\0')
Com_sprintf (filePath, sizeof(filePath), "/%s", quakePath);
else
Com_sprintf (filePath, sizeof(filePath), "/%s/%s", remoteGamedir, quakePath);
COM_StripExtension (filePath, listPath, sizeof(listPath));
// strncat (listPath, ".filelist");
Q_strncatz (listPath, ".filelist", sizeof(listPath));
CL_QueueHTTPDownload (listPath);
CL_QueueHTTPDownload (listPath, false);
}
// if a download entry has made it this far, CL_FinishHTTPDownload is guaranteed to be called.
@ -689,11 +765,29 @@ static void CL_CheckAndQueueDownload (char *path)
if (pak)
{
Com_sprintf (gamePath, sizeof(gamePath),"%s/%s", FS_Gamedir(), path);
Com_sprintf (gamePath, sizeof(gamePath),"%s/%s", FS_Downloaddir(), path); // was FS_Gamedir()
f = fopen (gamePath, "rb");
if (!f)
{
exists = false;
if ( !stricmp(FS_Downloaddir(), FS_Gamedir()) ) // if fs_gamedir and fs_downloaddir are the same, don't bother trying fs_gamedir
{
exists = false;
}
else
{
Com_sprintf (gamePath, sizeof(gamePath),"%s/%s", FS_Gamedir(), path);
f = fopen (gamePath, "rb");
if (!f)
{
exists = false;
}
else
{
// Com_Printf ("[HTTP] NOTICE: pak file (%s) specified in filelist already exists\n", gamePath);
exists = true;
fclose (f);
}
}
}
else
{
@ -705,12 +799,12 @@ static void CL_CheckAndQueueDownload (char *path)
else
{
// exists = FS_ExistsInGameDir (path);
exists = FS_LocalFileExists (path);
exists = (FS_DownloadFileExists (path) || FS_LocalFileExists(path));
}
if (!exists)
{
if (CL_QueueHTTPDownload (path))
if (CL_QueueHTTPDownload (path, false))
{
// Paks get bumped to the top and HTTP switches to single downloading.
// This prevents someone on 28k dialup trying to do both the main .pak
@ -757,7 +851,7 @@ static void CL_ParseFileList (dlhandle_t *dl)
char *list;
char *p;
if (!cl_http_filelists->value)
if (!cl_http_filelists->integer)
return;
list = dl->tempBuffer;
@ -905,6 +999,7 @@ static void CL_FinishHTTPDownload (void)
double fileSize;
char tempName[MAX_OSPATH];
qboolean isFile;
size_t len;
do
{
@ -941,7 +1036,7 @@ static void CL_FinishHTTPDownload (void)
// attempts.
dl->queueEntry->state = DLQ_STATE_DONE;
//filelist processing is done on read
// filelist processing is done on read
if (dl->file)
isFile = true;
else
@ -953,11 +1048,11 @@ static void CL_FinishHTTPDownload (void)
dl->file = NULL;
}
//might be aborted
// might be aborted
if (pendingCount)
pendingCount--;
handleCount--;
//Com_Printf ("finished dl: hc = %d\n", LOG_GENERAL, handleCount);
// Com_Printf ("finished dl: hc = %d\n", LOG_GENERAL, handleCount);
cls.downloadname[0] = 0;
cls.downloadposition = 0;
@ -972,9 +1067,8 @@ static void CL_FinishHTTPDownload (void)
curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &responseCode);
if (responseCode == 404)
{
i = strlen (dl->queueEntry->quakePath);
if ( !strcmp (dl->queueEntry->quakePath + i - 4, ".pak")
|| !strcmp (dl->queueEntry->quakePath + i - 4, ".pk3") )
len = strlen (dl->queueEntry->quakePath);
if ( len > 4 && ( !strcmp (dl->queueEntry->quakePath + len - 4, ".pak") || !strcmp (dl->queueEntry->quakePath + len - 4, ".pk3")) )
downloading_pak = false;
if (isFile) {
@ -994,15 +1088,25 @@ static void CL_FinishHTTPDownload (void)
else */
{
curl_multi_remove_handle (multi, dl->curl);
// Knightmare- fall back to UDP download for this map if failure on .bsp
if ( !strncmp(dl->queueEntry->quakePath, "maps/", 5) && !strcmp(dl->queueEntry->quakePath + i - 4, ".bsp") )
// Fall back to UDP download for this map if failure on .bsp
/* if ( !strncmp(dl->queueEntry->quakePath, "maps/", 5) && !strcmp(dl->queueEntry->quakePath + i - 4, ".bsp") )
{
Com_Printf ("[HTTP] Failed to download %s, falling back to UDP until next map.\n", dl->queueEntry->quakePath);
Com_Printf ("[HTTP]: failed to download %s, falling back to UDP until next map.\n", dl->queueEntry->quakePath);
thisMapAbort = true;
CL_CancelHTTPDownloads (false);
CL_ResetPrecacheCheck ();
}
else { */
// Remove queue entry from CURL multihandle queue
CL_RemoveDownloadFromQueue (dl->queueEntry);
dl->queueEntry = NULL;
// }
// end Knightmare
// YQ2 UDP fallback addition
if (isFile) {
downloadError = true;
}
continue;
}
}
@ -1016,7 +1120,7 @@ static void CL_FinishHTTPDownload (void)
// every other code is treated as fatal, fallthrough here
Com_Printf ("[HTTP] Bad response code %d for %s, aborting HTTP downloading.\n", responseCode, dl->queueEntry->quakePath);
//fatal error, disable http
// fatal error, disable http
case CURLE_COULDNT_RESOLVE_HOST:
case CURLE_COULDNT_CONNECT:
case CURLE_COULDNT_RESOLVE_PROXY:
@ -1031,8 +1135,8 @@ static void CL_FinishHTTPDownload (void)
CL_CancelHTTPDownloads (true);
continue;
default:
i = strlen (dl->queueEntry->quakePath);
if ( !strcmp (dl->queueEntry->quakePath + i - 4, ".pak") || !strcmp (dl->queueEntry->quakePath + i - 4, ".pk3") )
len = strlen (dl->queueEntry->quakePath);
if (len > 4 && (!strcmp (dl->queueEntry->quakePath + len - 4, ".pak") || !strcmp (dl->queueEntry->quakePath + len - 4, ".pk3")) )
downloading_pak = false;
if (isFile) {
remove (dl->filePath);
@ -1045,8 +1149,8 @@ static void CL_FinishHTTPDownload (void)
if (isFile)
{
//rename the temp file
Com_sprintf (tempName, sizeof(tempName), "%s/%s", FS_Gamedir(), dl->queueEntry->quakePath);
// rename the temp file
Com_sprintf (tempName, sizeof(tempName), "%s/%s", FS_Downloaddir(), dl->queueEntry->quakePath); // was FS_Gamedir()
if (rename (dl->filePath, tempName))
Com_Printf ("[HTTP] Failed to rename %s for some odd reason...", dl->filePath);
@ -1057,30 +1161,31 @@ static void CL_FinishHTTPDownload (void)
{
// FS_FlushCache ();
// FS_ReloadPAKs ();
// Knightmare- just add the pk3/ pak file
// Knightmare- just add the pk3 / pak file
if (!strcmp (tempName + i - 4, ".pk3"))
FS_AddPK3File (tempName);
FS_AddPK3File (tempName, false);
else
FS_AddPAKFile (tempName);
FS_AddPAKFile (tempName, false);
CL_ReVerifyHTTPQueue ();
downloading_pak = false;
}
}
//show some stats
// show some stats
curl_easy_getinfo (curl, CURLINFO_TOTAL_TIME, &timeTaken);
curl_easy_getinfo (curl, CURLINFO_SIZE_DOWNLOAD, &fileSize);
//FIXME:
//technically i shouldn't need to do this as curl will auto reuse the
//existing handle when you change the URL. however, the handleCount goes
//all weird when reusing a download slot in this way. if you can figure
//out why, please let me know.
// FIXME:
// Technically i shouldn't need to do this as curl will auto reuse the
// existing handle when you change the URL. however, the handleCount goes
// all weird when reusing a download slot in this way. if you can figure
// out why, please let me know.
curl_multi_remove_handle (multi, dl->curl);
Com_Printf ("[HTTP] (%s): %.f bytes, %.2fkB/sec [%d remaining files]\n", dl->queueEntry->quakePath, fileSize, (fileSize / 1024.0) / timeTaken, pendingCount);
} while (msgs_in_queue > 0);
}
while (msgs_in_queue > 0);
// FS_FlushCache ();
@ -1161,6 +1266,58 @@ static void CL_StartNextHTTPDownload (void)
}
}
/*
===============
CL_CheckHTTPError
YQ2 UDP fallback addition
Checks if thre was an error.
Returns true if yes, false if no.
Resets flag if it was set.
===============
*/
qboolean CL_CheckHTTPError (void)
{
if (downloadError) {
downloadError = false;
return true;
}
else {
return false;
}
}
/*
===============
CL_HTTP_EnableGenericFilelist
YQ2 UDP fallback addition
Enables generic filelist download
starting with the next file.
===============
*/
void CL_HTTP_EnableGenericFilelist (void)
{
downloadFileList = true;
}
/*
===============
CL_HTTP_SetDownloadGamedir
YQ2 Q2pro download addition
Sets the gamedir to be used by the URL generator
to determine the remote file path.
===============
*/
void CL_HTTP_SetDownloadGamedir (const char *gamedir)
{
Q_strncpyz(remoteGamedir, gamedir, sizeof(remoteGamedir));
}
/*
===============
CL_RunHTTPDownloads
@ -1178,11 +1335,11 @@ void CL_RunHTTPDownloads (void)
if (!cls.downloadServer[0])
return;
//Com_Printf ("handle %d, pending %d\n", LOG_GENERAL, handleCount, pendingCount);
// Com_Printf ("handle %d, pending %d\n", LOG_GENERAL, handleCount, pendingCount);
//not enough downloads running, queue some more!
if (pendingCount && abortDownloads == HTTPDL_ABORT_NONE &&
!downloading_pak && handleCount < cl_http_max_connections->value)
// not enough downloads running, queue some more!
if (pendingCount && (abortDownloads == HTTPDL_ABORT_NONE) &&
!downloading_pak && (handleCount < cl_http_max_connections->integer) )
CL_StartNextHTTPDownload ();
do
@ -1190,8 +1347,8 @@ void CL_RunHTTPDownloads (void)
ret = curl_multi_perform (multi, &newHandleCount);
if (newHandleCount < handleCount)
{
//Com_Printf ("runnd dl: hc = %d, nc = %d\n", LOG_GENERAL, handleCount, newHandleCount);
//hmm, something either finished or errored out.
// Com_Printf ("runnd dl: hc = %d, nc = %d\n", LOG_GENERAL, handleCount, newHandleCount);
// hmm, something either finished or errored out.
CL_FinishHTTPDownload ();
handleCount = newHandleCount;
}
@ -1204,9 +1361,9 @@ void CL_RunHTTPDownloads (void)
CL_CancelHTTPDownloads (true);
}
//not enough downloads running, queue some more!
if (pendingCount && abortDownloads == HTTPDL_ABORT_NONE &&
!downloading_pak && handleCount < cl_http_max_connections->value)
// not enough downloads running, queue some more!
if (pendingCount && (abortDownloads == HTTPDL_ABORT_NONE) &&
!downloading_pak && (handleCount < cl_http_max_connections->integer) )
CL_StartNextHTTPDownload ();
}

View file

@ -125,12 +125,15 @@ extern int num_cl_weaponmodels;
void CL_CancelHTTPDownloads (qboolean permKill);
void CL_InitHTTPDownloads (void);
qboolean CL_QueueHTTPDownload (const char *quakePath);
qboolean CL_QueueHTTPDownload (const char *quakePath, qboolean filelistUseGamedir); // YQ2 Q2pro download addition
void CL_RunHTTPDownloads (void);
qboolean CL_PendingHTTPDownloads (void);
void CL_SetHTTPServer (const char *URL);
void CL_HTTP_Cleanup (qboolean fullShutdown);
void CL_HTTP_ResetMapAbort (void); // Knightmare added
qboolean CL_CheckHTTPError (void); // YQ2 UDP fallback addition
void CL_HTTP_EnableGenericFilelist (void); // YQ2 UDP fallback addition
void CL_HTTP_SetDownloadGamedir (const char *gamedir); // YQ2 Q2pro download addition
typedef enum
{
@ -853,6 +856,7 @@ void CL_ParseClientinfo (int player);
//
// cl_download.c
//
void CL_ResetPrecacheCheck (void);
void CL_RequestNextDownload (void);
qboolean CL_CheckOrDownloadFile (char *filename);
void CL_Download_f (void);

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
#ifndef __CURL_CURLVER_H
#define __CURL_CURLVER_H
#ifndef CURLINC_CURLVER_H
#define CURLINC_CURLVER_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@ -26,17 +26,17 @@
a script at release-time. This was made its own header file in 7.11.2 */
/* This is the global package copyright */
#define LIBCURL_COPYRIGHT "1996 - 2017 Daniel Stenberg, <daniel@haxx.se>."
#define LIBCURL_COPYRIGHT "1996 - 2020 Daniel Stenberg, <daniel@haxx.se>."
/* This is the version number of the libcurl package from which this header
file origins: */
#define LIBCURL_VERSION "7.57.0"
#define LIBCURL_VERSION "7.69.1"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
#define LIBCURL_VERSION_MINOR 57
#define LIBCURL_VERSION_PATCH 0
#define LIBCURL_VERSION_MINOR 69
#define LIBCURL_VERSION_PATCH 1
/* This is the numeric version of the libcurl version number, meant for easier
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
@ -57,7 +57,7 @@
CURL_VERSION_BITS() macro since curl's own configure script greps for it
and needs it to contain the full number.
*/
#define LIBCURL_VERSION_NUM 0x073900
#define LIBCURL_VERSION_NUM 0x074501
/*
* This is the date and time when the full source package was created. The
@ -68,10 +68,10 @@
*
* "2007-11-23"
*/
#define LIBCURL_TIMESTAMP "2017-11-29"
#define LIBCURL_TIMESTAMP "2020-03-11"
#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|z)
#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z))
#define CURL_AT_LEAST_VERSION(x,y,z) \
(LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z))
#endif /* __CURL_CURLVER_H */
#endif /* CURLINC_CURLVER_H */

View file

@ -1,5 +1,5 @@
#ifndef __CURL_EASY_H
#define __CURL_EASY_H
#ifndef CURLINC_EASY_H
#define CURLINC_EASY_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@ -95,6 +95,16 @@ CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen,
CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer,
size_t buflen, size_t *n);
/*
* NAME curl_easy_upkeep()
*
* DESCRIPTION
*
* Performs connection upkeep for the given session handle.
*/
CURL_EXTERN CURLcode curl_easy_upkeep(CURL *curl);
#ifdef __cplusplus
}
#endif

View file

@ -1,5 +1,5 @@
#ifndef __CURL_MPRINTF_H
#define __CURL_MPRINTF_H
#ifndef CURLINC_MPRINTF_H
#define CURLINC_MPRINTF_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@ -47,4 +47,4 @@ CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args);
}
#endif
#endif /* __CURL_MPRINTF_H */
#endif /* CURLINC_MPRINTF_H */

View file

@ -1,5 +1,5 @@
#ifndef __CURL_MULTI_H
#define __CURL_MULTI_H
#ifndef CURLINC_MULTI_H
#define CURLINC_MULTI_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@ -70,6 +70,10 @@ typedef enum {
CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was
attempted to get added - again */
CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a
callback */
CURLM_WAKEUP_FAILURE, /* wakeup is unavailable or failed */
CURLM_BAD_FUNCTION_ARGUMENT, /* function called with a bad parameter */
CURLM_LAST
} CURLMcode;
@ -171,6 +175,29 @@ CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle,
int timeout_ms,
int *ret);
/*
* Name: curl_multi_poll()
*
* Desc: Poll on all fds within a CURLM set as well as any
* additional fds passed to the function.
*
* Returns: CURLMcode type, general multi error code.
*/
CURL_EXTERN CURLMcode curl_multi_poll(CURLM *multi_handle,
struct curl_waitfd extra_fds[],
unsigned int extra_nfds,
int timeout_ms,
int *ret);
/*
* Name: curl_multi_wakeup()
*
* Desc: wakes up a sleeping curl_multi_poll call.
*
* Returns: CURLMcode type, general multi error code.
*/
CURL_EXTERN CURLMcode curl_multi_wakeup(CURLM *multi_handle);
/*
* Name: curl_multi_perform()
*
@ -184,8 +211,8 @@ CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle,
*
* Returns: CURLMcode type, general multi error code. *NOTE* that this only
* returns errors etc regarding the whole multi stack. There might
* still have occurred problems on invidual transfers even when this
* returns OK.
* still have occurred problems on individual transfers even when
* this returns OK.
*/
CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle,
int *running_handles);
@ -317,68 +344,58 @@ CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle,
CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle,
long *milliseconds);
#undef CINIT /* re-using the same name as in curl.h */
#ifdef CURL_ISOCPP
#define CINIT(name,type,num) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + num
#else
/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
#define LONG CURLOPTTYPE_LONG
#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT
#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
#define OFF_T CURLOPTTYPE_OFF_T
#define CINIT(name,type,number) CURLMOPT_/**/name = type + number
#endif
typedef enum {
/* This is the socket callback function pointer */
CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1),
CURLOPT(CURLMOPT_SOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 1),
/* This is the argument passed to the socket callback */
CINIT(SOCKETDATA, OBJECTPOINT, 2),
CURLOPT(CURLMOPT_SOCKETDATA, CURLOPTTYPE_OBJECTPOINT, 2),
/* set to 1 to enable pipelining for this multi handle */
CINIT(PIPELINING, LONG, 3),
CURLOPT(CURLMOPT_PIPELINING, CURLOPTTYPE_LONG, 3),
/* This is the timer callback function pointer */
CINIT(TIMERFUNCTION, FUNCTIONPOINT, 4),
CURLOPT(CURLMOPT_TIMERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 4),
/* This is the argument passed to the timer callback */
CINIT(TIMERDATA, OBJECTPOINT, 5),
CURLOPT(CURLMOPT_TIMERDATA, CURLOPTTYPE_OBJECTPOINT, 5),
/* maximum number of entries in the connection cache */
CINIT(MAXCONNECTS, LONG, 6),
CURLOPT(CURLMOPT_MAXCONNECTS, CURLOPTTYPE_LONG, 6),
/* maximum number of (pipelining) connections to one host */
CINIT(MAX_HOST_CONNECTIONS, LONG, 7),
CURLOPT(CURLMOPT_MAX_HOST_CONNECTIONS, CURLOPTTYPE_LONG, 7),
/* maximum number of requests in a pipeline */
CINIT(MAX_PIPELINE_LENGTH, LONG, 8),
CURLOPT(CURLMOPT_MAX_PIPELINE_LENGTH, CURLOPTTYPE_LONG, 8),
/* a connection with a content-length longer than this
will not be considered for pipelining */
CINIT(CONTENT_LENGTH_PENALTY_SIZE, OFF_T, 9),
CURLOPT(CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 9),
/* a connection with a chunk length longer than this
will not be considered for pipelining */
CINIT(CHUNK_LENGTH_PENALTY_SIZE, OFF_T, 10),
CURLOPT(CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 10),
/* a list of site names(+port) that are blacklisted from
pipelining */
CINIT(PIPELINING_SITE_BL, OBJECTPOINT, 11),
CURLOPT(CURLMOPT_PIPELINING_SITE_BL, CURLOPTTYPE_OBJECTPOINT, 11),
/* a list of server types that are blacklisted from
pipelining */
CINIT(PIPELINING_SERVER_BL, OBJECTPOINT, 12),
CURLOPT(CURLMOPT_PIPELINING_SERVER_BL, CURLOPTTYPE_OBJECTPOINT, 12),
/* maximum number of open connections in total */
CINIT(MAX_TOTAL_CONNECTIONS, LONG, 13),
CURLOPT(CURLMOPT_MAX_TOTAL_CONNECTIONS, CURLOPTTYPE_LONG, 13),
/* This is the server push callback function pointer */
CINIT(PUSHFUNCTION, FUNCTIONPOINT, 14),
CURLOPT(CURLMOPT_PUSHFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 14),
/* This is the argument passed to the server push callback */
CINIT(PUSHDATA, OBJECTPOINT, 15),
CURLOPT(CURLMOPT_PUSHDATA, CURLOPTTYPE_OBJECTPOINT, 15),
/* maximum number of concurrent streams to support on a connection */
CURLOPT(CURLMOPT_MAX_CONCURRENT_STREAMS, CURLOPTTYPE_LONG, 16),
CURLMOPT_LASTENTRY /* the last unused */
} CURLMoption;

View file

@ -1,5 +1,5 @@
#ifndef __STDC_HEADERS_H
#define __STDC_HEADERS_H
#ifndef CURLINC_STDCHEADERS_H
#define CURLINC_STDCHEADERS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@ -30,4 +30,4 @@ size_t fwrite(const void *, size_t, size_t, FILE *);
int strcasecmp(const char *, const char *);
int strncasecmp(const char *, const char *, size_t);
#endif /* __STDC_HEADERS_H */
#endif /* CURLINC_STDCHEADERS_H */

View file

@ -1,5 +1,5 @@
#ifndef __CURL_SYSTEM_H
#define __CURL_SYSTEM_H
#ifndef CURLINC_SYSTEM_H
#define CURLINC_SYSTEM_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@ -137,15 +137,26 @@
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__LCC__)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
# if defined(__e2k__) /* MCST eLbrus C Compiler */
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
# else /* Local (or Little) C Compiler */
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
# endif
#elif defined(__SYMBIAN32__)
# if defined(__EABI__) /* Treat all ARM compilers equally */
# if defined(__EABI__) /* Treat all ARM compilers equally */
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
@ -288,7 +299,6 @@
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__TINYC__) /* also known as tcc */
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
@ -298,9 +308,11 @@
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
#elif defined(__SUNPRO_C) /* Oracle Solaris Studio */
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* Oracle Solaris Studio */
# if !defined(__LP64) && (defined(__ILP32) || \
defined(__i386) || defined(__sparcv8))
defined(__i386) || \
defined(__sparcv8) || \
defined(__sparcv8plus))
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
@ -318,6 +330,24 @@
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
#elif defined(__xlc__) /* IBM xlc compiler */
# if !defined(_LP64)
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# else
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
/* ===================================== */
/* KEEP MSVC THE PENULTIMATE ENTRY */
/* ===================================== */
@ -342,13 +372,14 @@
/* KEEP GENERIC GCC THE LAST ENTRY */
/* ===================================== */
#elif defined(__GNUC__)
#elif defined(__GNUC__) && !defined(_SCO_DS)
# if !defined(__LP64__) && \
(defined(__ILP32__) || defined(__i386__) || defined(__hppa__) || \
defined(__ppc__) || defined(__powerpc__) || defined(__arm__) || \
defined(__sparc__) || defined(__mips__) || defined(__sh__) || \
defined(__XTENSA__) || \
(defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 4))
(defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 4) || \
(defined(__LONG_MAX__) && __LONG_MAX__ == 2147483647L))
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
@ -356,7 +387,9 @@
# define CURL_SUFFIX_CURL_OFF_TU ULL
# elif defined(__LP64__) || \
defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__) || \
(defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8)
defined(__e2k__) || \
(defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8) || \
(defined(__LONG_MAX__) && __LONG_MAX__ == 9223372036854775807L)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
@ -451,21 +484,21 @@
*/
#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551)
# define __CURL_OFF_T_C_HLPR2(x) x
# define __CURL_OFF_T_C_HLPR1(x) __CURL_OFF_T_C_HLPR2(x)
# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
__CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T)
# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
__CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU)
# define CURLINC_OFF_T_C_HLPR2(x) x
# define CURLINC_OFF_T_C_HLPR1(x) CURLINC_OFF_T_C_HLPR2(x)
# define CURL_OFF_T_C(Val) CURLINC_OFF_T_C_HLPR1(Val) ## \
CURLINC_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T)
# define CURL_OFF_TU_C(Val) CURLINC_OFF_T_C_HLPR1(Val) ## \
CURLINC_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU)
#else
# ifdef CURL_ISOCPP
# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix
# define CURLINC_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix
# else
# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix
# define CURLINC_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix
# endif
# define __CURL_OFF_T_C_HLPR1(Val,Suffix) __CURL_OFF_T_C_HLPR2(Val,Suffix)
# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T)
# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU)
# define CURLINC_OFF_T_C_HLPR1(Val,Suffix) CURLINC_OFF_T_C_HLPR2(Val,Suffix)
# define CURL_OFF_T_C(Val) CURLINC_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T)
# define CURL_OFF_TU_C(Val) CURLINC_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU)
#endif
#endif /* __CURL_SYSTEM_H */
#endif /* CURLINC_SYSTEM_H */

View file

@ -1,5 +1,5 @@
#ifndef __CURL_TYPECHECK_GCC_H
#define __CURL_TYPECHECK_GCC_H
#ifndef CURLINC_TYPECHECK_GCC_H
#define CURLINC_TYPECHECK_GCC_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@ -25,10 +25,10 @@
/* wraps curl_easy_setopt() with typechecking */
/* To add a new kind of warning, add an
* if(_curl_is_sometype_option(_curl_opt))
* if(!_curl_is_sometype(value))
* if(curlcheck_sometype_option(_curl_opt))
* if(!curlcheck_sometype(value))
* _curl_easy_setopt_err_sometype();
* block and define _curl_is_sometype_option, _curl_is_sometype and
* block and define curlcheck_sometype_option, curlcheck_sometype and
* _curl_easy_setopt_err_sometype below
*
* NOTE: We use two nested 'if' statements here instead of the && operator, in
@ -38,114 +38,115 @@
* To add an option that uses the same type as an existing option, you'll just
* need to extend the appropriate _curl_*_option macro
*/
#define curl_easy_setopt(handle, option, value) \
__extension__ ({ \
__typeof__(option) _curl_opt = option; \
if(__builtin_constant_p(_curl_opt)) { \
if(_curl_is_long_option(_curl_opt)) \
if(!_curl_is_long(value)) \
_curl_easy_setopt_err_long(); \
if(_curl_is_off_t_option(_curl_opt)) \
if(!_curl_is_off_t(value)) \
_curl_easy_setopt_err_curl_off_t(); \
if(_curl_is_string_option(_curl_opt)) \
if(!_curl_is_string(value)) \
_curl_easy_setopt_err_string(); \
if(_curl_is_write_cb_option(_curl_opt)) \
if(!_curl_is_write_cb(value)) \
_curl_easy_setopt_err_write_callback(); \
if((_curl_opt) == CURLOPT_READFUNCTION) \
if(!_curl_is_read_cb(value)) \
_curl_easy_setopt_err_read_cb(); \
if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \
if(!_curl_is_ioctl_cb(value)) \
_curl_easy_setopt_err_ioctl_cb(); \
if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \
if(!_curl_is_sockopt_cb(value)) \
_curl_easy_setopt_err_sockopt_cb(); \
if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \
if(!_curl_is_opensocket_cb(value)) \
_curl_easy_setopt_err_opensocket_cb(); \
if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \
if(!_curl_is_progress_cb(value)) \
_curl_easy_setopt_err_progress_cb(); \
if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \
if(!_curl_is_debug_cb(value)) \
_curl_easy_setopt_err_debug_cb(); \
if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \
if(!_curl_is_ssl_ctx_cb(value)) \
_curl_easy_setopt_err_ssl_ctx_cb(); \
if(_curl_is_conv_cb_option(_curl_opt)) \
if(!_curl_is_conv_cb(value)) \
_curl_easy_setopt_err_conv_cb(); \
if((_curl_opt) == CURLOPT_SEEKFUNCTION) \
if(!_curl_is_seek_cb(value)) \
_curl_easy_setopt_err_seek_cb(); \
if(_curl_is_cb_data_option(_curl_opt)) \
if(!_curl_is_cb_data(value)) \
_curl_easy_setopt_err_cb_data(); \
if((_curl_opt) == CURLOPT_ERRORBUFFER) \
if(!_curl_is_error_buffer(value)) \
_curl_easy_setopt_err_error_buffer(); \
if((_curl_opt) == CURLOPT_STDERR) \
if(!_curl_is_FILE(value)) \
_curl_easy_setopt_err_FILE(); \
if(_curl_is_postfields_option(_curl_opt)) \
if(!_curl_is_postfields(value)) \
_curl_easy_setopt_err_postfields(); \
if((_curl_opt) == CURLOPT_HTTPPOST) \
if(!_curl_is_arr((value), struct curl_httppost)) \
_curl_easy_setopt_err_curl_httpost(); \
if((_curl_opt) == CURLOPT_MIMEPOST) \
if(!_curl_is_ptr((value), curl_mime)) \
_curl_easy_setopt_err_curl_mimepost(); \
if(_curl_is_slist_option(_curl_opt)) \
if(!_curl_is_arr((value), struct curl_slist)) \
_curl_easy_setopt_err_curl_slist(); \
if((_curl_opt) == CURLOPT_SHARE) \
if(!_curl_is_ptr((value), CURLSH)) \
_curl_easy_setopt_err_CURLSH(); \
} \
curl_easy_setopt(handle, _curl_opt, value); \
})
#define curl_easy_setopt(handle, option, value) \
__extension__({ \
__typeof__(option) _curl_opt = option; \
if(__builtin_constant_p(_curl_opt)) { \
if(curlcheck_long_option(_curl_opt)) \
if(!curlcheck_long(value)) \
_curl_easy_setopt_err_long(); \
if(curlcheck_off_t_option(_curl_opt)) \
if(!curlcheck_off_t(value)) \
_curl_easy_setopt_err_curl_off_t(); \
if(curlcheck_string_option(_curl_opt)) \
if(!curlcheck_string(value)) \
_curl_easy_setopt_err_string(); \
if(curlcheck_write_cb_option(_curl_opt)) \
if(!curlcheck_write_cb(value)) \
_curl_easy_setopt_err_write_callback(); \
if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION) \
if(!curlcheck_resolver_start_callback(value)) \
_curl_easy_setopt_err_resolver_start_callback(); \
if((_curl_opt) == CURLOPT_READFUNCTION) \
if(!curlcheck_read_cb(value)) \
_curl_easy_setopt_err_read_cb(); \
if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \
if(!curlcheck_ioctl_cb(value)) \
_curl_easy_setopt_err_ioctl_cb(); \
if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \
if(!curlcheck_sockopt_cb(value)) \
_curl_easy_setopt_err_sockopt_cb(); \
if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \
if(!curlcheck_opensocket_cb(value)) \
_curl_easy_setopt_err_opensocket_cb(); \
if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \
if(!curlcheck_progress_cb(value)) \
_curl_easy_setopt_err_progress_cb(); \
if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \
if(!curlcheck_debug_cb(value)) \
_curl_easy_setopt_err_debug_cb(); \
if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \
if(!curlcheck_ssl_ctx_cb(value)) \
_curl_easy_setopt_err_ssl_ctx_cb(); \
if(curlcheck_conv_cb_option(_curl_opt)) \
if(!curlcheck_conv_cb(value)) \
_curl_easy_setopt_err_conv_cb(); \
if((_curl_opt) == CURLOPT_SEEKFUNCTION) \
if(!curlcheck_seek_cb(value)) \
_curl_easy_setopt_err_seek_cb(); \
if(curlcheck_cb_data_option(_curl_opt)) \
if(!curlcheck_cb_data(value)) \
_curl_easy_setopt_err_cb_data(); \
if((_curl_opt) == CURLOPT_ERRORBUFFER) \
if(!curlcheck_error_buffer(value)) \
_curl_easy_setopt_err_error_buffer(); \
if((_curl_opt) == CURLOPT_STDERR) \
if(!curlcheck_FILE(value)) \
_curl_easy_setopt_err_FILE(); \
if(curlcheck_postfields_option(_curl_opt)) \
if(!curlcheck_postfields(value)) \
_curl_easy_setopt_err_postfields(); \
if((_curl_opt) == CURLOPT_HTTPPOST) \
if(!curlcheck_arr((value), struct curl_httppost)) \
_curl_easy_setopt_err_curl_httpost(); \
if((_curl_opt) == CURLOPT_MIMEPOST) \
if(!curlcheck_ptr((value), curl_mime)) \
_curl_easy_setopt_err_curl_mimepost(); \
if(curlcheck_slist_option(_curl_opt)) \
if(!curlcheck_arr((value), struct curl_slist)) \
_curl_easy_setopt_err_curl_slist(); \
if((_curl_opt) == CURLOPT_SHARE) \
if(!curlcheck_ptr((value), CURLSH)) \
_curl_easy_setopt_err_CURLSH(); \
} \
curl_easy_setopt(handle, _curl_opt, value); \
})
/* wraps curl_easy_getinfo() with typechecking */
/* FIXME: don't allow const pointers */
#define curl_easy_getinfo(handle, info, arg) \
__extension__ ({ \
__typeof__(info) _curl_info = info; \
if(__builtin_constant_p(_curl_info)) { \
if(_curl_is_string_info(_curl_info)) \
if(!_curl_is_arr((arg), char *)) \
_curl_easy_getinfo_err_string(); \
if(_curl_is_long_info(_curl_info)) \
if(!_curl_is_arr((arg), long)) \
_curl_easy_getinfo_err_long(); \
if(_curl_is_double_info(_curl_info)) \
if(!_curl_is_arr((arg), double)) \
_curl_easy_getinfo_err_double(); \
if(_curl_is_slist_info(_curl_info)) \
if(!_curl_is_arr((arg), struct curl_slist *)) \
_curl_easy_getinfo_err_curl_slist(); \
if(_curl_is_tlssessioninfo_info(_curl_info)) \
if(!_curl_is_arr((arg), struct curl_tlssessioninfo *)) \
_curl_easy_getinfo_err_curl_tlssesssioninfo(); \
if(_curl_is_certinfo_info(_curl_info)) \
if(!_curl_is_arr((arg), struct curl_certinfo *)) \
_curl_easy_getinfo_err_curl_certinfo(); \
if(_curl_is_socket_info(_curl_info)) \
if(!_curl_is_arr((arg), curl_socket_t)) \
_curl_easy_getinfo_err_curl_socket(); \
if(_curl_is_off_t_info(_curl_info)) \
if(!_curl_is_arr((arg), curl_off_t)) \
_curl_easy_getinfo_err_curl_off_t(); \
} \
curl_easy_getinfo(handle, _curl_info, arg); \
})
#define curl_easy_getinfo(handle, info, arg) \
__extension__({ \
__typeof__(info) _curl_info = info; \
if(__builtin_constant_p(_curl_info)) { \
if(curlcheck_string_info(_curl_info)) \
if(!curlcheck_arr((arg), char *)) \
_curl_easy_getinfo_err_string(); \
if(curlcheck_long_info(_curl_info)) \
if(!curlcheck_arr((arg), long)) \
_curl_easy_getinfo_err_long(); \
if(curlcheck_double_info(_curl_info)) \
if(!curlcheck_arr((arg), double)) \
_curl_easy_getinfo_err_double(); \
if(curlcheck_slist_info(_curl_info)) \
if(!curlcheck_arr((arg), struct curl_slist *)) \
_curl_easy_getinfo_err_curl_slist(); \
if(curlcheck_tlssessioninfo_info(_curl_info)) \
if(!curlcheck_arr((arg), struct curl_tlssessioninfo *)) \
_curl_easy_getinfo_err_curl_tlssesssioninfo(); \
if(curlcheck_certinfo_info(_curl_info)) \
if(!curlcheck_arr((arg), struct curl_certinfo *)) \
_curl_easy_getinfo_err_curl_certinfo(); \
if(curlcheck_socket_info(_curl_info)) \
if(!curlcheck_arr((arg), curl_socket_t)) \
_curl_easy_getinfo_err_curl_socket(); \
if(curlcheck_off_t_info(_curl_info)) \
if(!curlcheck_arr((arg), curl_off_t)) \
_curl_easy_getinfo_err_curl_off_t(); \
} \
curl_easy_getinfo(handle, _curl_info, arg); \
})
/* TODO: typechecking for curl_share_setopt() and curl_multi_setopt(),
* for now just make sure that the functions are called with three
* arguments
/*
* For now, just make sure that the functions are called with three arguments
*/
#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
@ -155,79 +156,83 @@ __extension__ ({ \
* functions */
/* To define a new warning, use _CURL_WARNING(identifier, "message") */
#define _CURL_WARNING(id, message) \
static void __attribute__((__warning__(message))) \
__attribute__((__unused__)) __attribute__((__noinline__)) \
#define CURLWARNING(id, message) \
static void __attribute__((__warning__(message))) \
__attribute__((__unused__)) __attribute__((__noinline__)) \
id(void) { __asm__(""); }
_CURL_WARNING(_curl_easy_setopt_err_long,
CURLWARNING(_curl_easy_setopt_err_long,
"curl_easy_setopt expects a long argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_curl_off_t,
CURLWARNING(_curl_easy_setopt_err_curl_off_t,
"curl_easy_setopt expects a curl_off_t argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_string,
CURLWARNING(_curl_easy_setopt_err_string,
"curl_easy_setopt expects a "
"string ('char *' or char[]) argument for this option"
)
_CURL_WARNING(_curl_easy_setopt_err_write_callback,
CURLWARNING(_curl_easy_setopt_err_write_callback,
"curl_easy_setopt expects a curl_write_callback argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_read_cb,
CURLWARNING(_curl_easy_setopt_err_resolver_start_callback,
"curl_easy_setopt expects a "
"curl_resolver_start_callback argument for this option"
)
CURLWARNING(_curl_easy_setopt_err_read_cb,
"curl_easy_setopt expects a curl_read_callback argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_ioctl_cb,
CURLWARNING(_curl_easy_setopt_err_ioctl_cb,
"curl_easy_setopt expects a curl_ioctl_callback argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_sockopt_cb,
CURLWARNING(_curl_easy_setopt_err_sockopt_cb,
"curl_easy_setopt expects a curl_sockopt_callback argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_opensocket_cb,
CURLWARNING(_curl_easy_setopt_err_opensocket_cb,
"curl_easy_setopt expects a "
"curl_opensocket_callback argument for this option"
)
_CURL_WARNING(_curl_easy_setopt_err_progress_cb,
CURLWARNING(_curl_easy_setopt_err_progress_cb,
"curl_easy_setopt expects a curl_progress_callback argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_debug_cb,
CURLWARNING(_curl_easy_setopt_err_debug_cb,
"curl_easy_setopt expects a curl_debug_callback argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_ssl_ctx_cb,
CURLWARNING(_curl_easy_setopt_err_ssl_ctx_cb,
"curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_conv_cb,
CURLWARNING(_curl_easy_setopt_err_conv_cb,
"curl_easy_setopt expects a curl_conv_callback argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_seek_cb,
CURLWARNING(_curl_easy_setopt_err_seek_cb,
"curl_easy_setopt expects a curl_seek_callback argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_cb_data,
CURLWARNING(_curl_easy_setopt_err_cb_data,
"curl_easy_setopt expects a "
"private data pointer as argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_error_buffer,
CURLWARNING(_curl_easy_setopt_err_error_buffer,
"curl_easy_setopt expects a "
"char buffer of CURL_ERROR_SIZE as argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_FILE,
CURLWARNING(_curl_easy_setopt_err_FILE,
"curl_easy_setopt expects a 'FILE *' argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_postfields,
CURLWARNING(_curl_easy_setopt_err_postfields,
"curl_easy_setopt expects a 'void *' or 'char *' argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_curl_httpost,
CURLWARNING(_curl_easy_setopt_err_curl_httpost,
"curl_easy_setopt expects a 'struct curl_httppost *' "
"argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_curl_mimepost,
CURLWARNING(_curl_easy_setopt_err_curl_mimepost,
"curl_easy_setopt expects a 'curl_mime *' "
"argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_curl_slist,
CURLWARNING(_curl_easy_setopt_err_curl_slist,
"curl_easy_setopt expects a 'struct curl_slist *' argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_CURLSH,
CURLWARNING(_curl_easy_setopt_err_CURLSH,
"curl_easy_setopt expects a CURLSH* argument for this option")
_CURL_WARNING(_curl_easy_getinfo_err_string,
CURLWARNING(_curl_easy_getinfo_err_string,
"curl_easy_getinfo expects a pointer to 'char *' for this info")
_CURL_WARNING(_curl_easy_getinfo_err_long,
CURLWARNING(_curl_easy_getinfo_err_long,
"curl_easy_getinfo expects a pointer to long for this info")
_CURL_WARNING(_curl_easy_getinfo_err_double,
CURLWARNING(_curl_easy_getinfo_err_double,
"curl_easy_getinfo expects a pointer to double for this info")
_CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
CURLWARNING(_curl_easy_getinfo_err_curl_slist,
"curl_easy_getinfo expects a pointer to 'struct curl_slist *' for this info")
_CURL_WARNING(_curl_easy_getinfo_err_curl_tlssesssioninfo,
CURLWARNING(_curl_easy_getinfo_err_curl_tlssesssioninfo,
"curl_easy_getinfo expects a pointer to "
"'struct curl_tlssessioninfo *' for this info")
_CURL_WARNING(_curl_easy_getinfo_err_curl_certinfo,
CURLWARNING(_curl_easy_getinfo_err_curl_certinfo,
"curl_easy_getinfo expects a pointer to "
"'struct curl_certinfo *' for this info")
_CURL_WARNING(_curl_easy_getinfo_err_curl_socket,
CURLWARNING(_curl_easy_getinfo_err_curl_socket,
"curl_easy_getinfo expects a pointer to curl_socket_t for this info")
_CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
"curl_easy_getinfo expects a pointer to curl_off_t for this info")
/* groups of curl_easy_setops options that take the same type of argument */
@ -239,16 +244,17 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
*/
/* evaluates to true if option takes a long argument */
#define _curl_is_long_option(option) \
#define curlcheck_long_option(option) \
(0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT)
#define _curl_is_off_t_option(option) \
#define curlcheck_off_t_option(option) \
((option) > CURLOPTTYPE_OFF_T)
/* evaluates to true if option takes a char* argument */
#define _curl_is_string_option(option) \
#define curlcheck_string_option(option) \
((option) == CURLOPT_ABSTRACT_UNIX_SOCKET || \
(option) == CURLOPT_ACCEPT_ENCODING || \
(option) == CURLOPT_ALTSVC || \
(option) == CURLOPT_CAINFO || \
(option) == CURLOPT_CAPATH || \
(option) == CURLOPT_COOKIE || \
@ -262,6 +268,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_DNS_LOCAL_IP4 || \
(option) == CURLOPT_DNS_LOCAL_IP6 || \
(option) == CURLOPT_DNS_SERVERS || \
(option) == CURLOPT_DOH_URL || \
(option) == CURLOPT_EGDSOCKET || \
(option) == CURLOPT_FTPPORT || \
(option) == CURLOPT_FTP_ACCOUNT || \
@ -293,15 +300,18 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_PROXY_SSLKEY || \
(option) == CURLOPT_PROXY_SSLKEYTYPE || \
(option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \
(option) == CURLOPT_PROXY_TLS13_CIPHERS || \
(option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \
(option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \
(option) == CURLOPT_PROXY_TLSAUTH_TYPE || \
(option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \
(option) == CURLOPT_RANDOM_FILE || \
(option) == CURLOPT_RANGE || \
(option) == CURLOPT_REFERER || \
(option) == CURLOPT_REQUEST_TARGET || \
(option) == CURLOPT_RTSP_SESSION_ID || \
(option) == CURLOPT_RTSP_STREAM_URI || \
(option) == CURLOPT_RTSP_TRANSPORT || \
(option) == CURLOPT_SASL_AUTHZID || \
(option) == CURLOPT_SERVICE_NAME || \
(option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \
(option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \
@ -314,6 +324,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_SSLKEY || \
(option) == CURLOPT_SSLKEYTYPE || \
(option) == CURLOPT_SSL_CIPHER_LIST || \
(option) == CURLOPT_TLS13_CIPHERS || \
(option) == CURLOPT_TLSAUTH_PASSWORD || \
(option) == CURLOPT_TLSAUTH_TYPE || \
(option) == CURLOPT_TLSAUTH_USERNAME || \
@ -326,18 +337,18 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
0)
/* evaluates to true if option takes a curl_write_callback argument */
#define _curl_is_write_cb_option(option) \
((option) == CURLOPT_HEADERFUNCTION || \
#define curlcheck_write_cb_option(option) \
((option) == CURLOPT_HEADERFUNCTION || \
(option) == CURLOPT_WRITEFUNCTION)
/* evaluates to true if option takes a curl_conv_callback argument */
#define _curl_is_conv_cb_option(option) \
((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \
(option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \
#define curlcheck_conv_cb_option(option) \
((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \
(option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \
(option) == CURLOPT_CONV_FROM_UTF8_FUNCTION)
/* evaluates to true if option takes a data argument to pass to a callback */
#define _curl_is_cb_data_option(option) \
#define curlcheck_cb_data_option(option) \
((option) == CURLOPT_CHUNK_DATA || \
(option) == CURLOPT_CLOSESOCKETDATA || \
(option) == CURLOPT_DEBUGDATA || \
@ -354,16 +365,18 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_SSH_KEYDATA || \
(option) == CURLOPT_SSL_CTX_DATA || \
(option) == CURLOPT_WRITEDATA || \
(option) == CURLOPT_RESOLVER_START_DATA || \
(option) == CURLOPT_TRAILERDATA || \
0)
/* evaluates to true if option takes a POST data argument (void* or char*) */
#define _curl_is_postfields_option(option) \
#define curlcheck_postfields_option(option) \
((option) == CURLOPT_POSTFIELDS || \
(option) == CURLOPT_COPYPOSTFIELDS || \
0)
/* evaluates to true if option takes a struct curl_slist * argument */
#define _curl_is_slist_option(option) \
#define curlcheck_slist_option(option) \
((option) == CURLOPT_HTTP200ALIASES || \
(option) == CURLOPT_HTTPHEADER || \
(option) == CURLOPT_MAIL_RCPT || \
@ -373,45 +386,46 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_QUOTE || \
(option) == CURLOPT_RESOLVE || \
(option) == CURLOPT_TELNETOPTIONS || \
(option) == CURLOPT_CONNECT_TO || \
0)
/* groups of curl_easy_getinfo infos that take the same type of argument */
/* evaluates to true if info expects a pointer to char * argument */
#define _curl_is_string_info(info) \
#define curlcheck_string_info(info) \
(CURLINFO_STRING < (info) && (info) < CURLINFO_LONG)
/* evaluates to true if info expects a pointer to long argument */
#define _curl_is_long_info(info) \
#define curlcheck_long_info(info) \
(CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE)
/* evaluates to true if info expects a pointer to double argument */
#define _curl_is_double_info(info) \
#define curlcheck_double_info(info) \
(CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
/* true if info expects a pointer to struct curl_slist * argument */
#define _curl_is_slist_info(info) \
#define curlcheck_slist_info(info) \
(((info) == CURLINFO_SSL_ENGINES) || ((info) == CURLINFO_COOKIELIST))
/* true if info expects a pointer to struct curl_tlssessioninfo * argument */
#define _curl_is_tlssessioninfo_info(info) \
#define curlcheck_tlssessioninfo_info(info) \
(((info) == CURLINFO_TLS_SSL_PTR) || ((info) == CURLINFO_TLS_SESSION))
/* true if info expects a pointer to struct curl_certinfo * argument */
#define _curl_is_certinfo_info(info) ((info) == CURLINFO_CERTINFO)
#define curlcheck_certinfo_info(info) ((info) == CURLINFO_CERTINFO)
/* true if info expects a pointer to struct curl_socket_t argument */
#define _curl_is_socket_info(info) \
#define curlcheck_socket_info(info) \
(CURLINFO_SOCKET < (info) && (info) < CURLINFO_OFF_T)
/* true if info expects a pointer to curl_off_t argument */
#define _curl_is_off_t_info(info) \
#define curlcheck_off_t_info(info) \
(CURLINFO_OFF_T < (info))
/* typecheck helpers -- check whether given expression has requested type*/
/* For pointers, you can use the _curl_is_ptr/_curl_is_arr macros,
/* For pointers, you can use the curlcheck_ptr/curlcheck_arr macros,
* otherwise define a new macro. Search for __builtin_types_compatible_p
* in the GCC manual.
* NOTE: these macros MUST NOT EVALUATE their arguments! The argument is
@ -420,36 +434,36 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
* == or whatsoever.
*/
/* XXX: should evaluate to true iff expr is a pointer */
#define _curl_is_any_ptr(expr) \
/* XXX: should evaluate to true if expr is a pointer */
#define curlcheck_any_ptr(expr) \
(sizeof(expr) == sizeof(void *))
/* evaluates to true if expr is NULL */
/* XXX: must not evaluate expr, so this check is not accurate */
#define _curl_is_NULL(expr) \
#define curlcheck_NULL(expr) \
(__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL)))
/* evaluates to true if expr is type*, const type* or NULL */
#define _curl_is_ptr(expr, type) \
(_curl_is_NULL(expr) || \
__builtin_types_compatible_p(__typeof__(expr), type *) || \
#define curlcheck_ptr(expr, type) \
(curlcheck_NULL(expr) || \
__builtin_types_compatible_p(__typeof__(expr), type *) || \
__builtin_types_compatible_p(__typeof__(expr), const type *))
/* evaluates to true if expr is one of type[], type*, NULL or const type* */
#define _curl_is_arr(expr, type) \
(_curl_is_ptr((expr), type) || \
#define curlcheck_arr(expr, type) \
(curlcheck_ptr((expr), type) || \
__builtin_types_compatible_p(__typeof__(expr), type []))
/* evaluates to true if expr is a string */
#define _curl_is_string(expr) \
(_curl_is_arr((expr), char) || \
_curl_is_arr((expr), signed char) || \
_curl_is_arr((expr), unsigned char))
#define curlcheck_string(expr) \
(curlcheck_arr((expr), char) || \
curlcheck_arr((expr), signed char) || \
curlcheck_arr((expr), unsigned char))
/* evaluates to true if expr is a long (no matter the signedness)
* XXX: for now, int is also accepted (and therefore short and char, which
* are promoted to int when passed to a variadic function) */
#define _curl_is_long(expr) \
#define curlcheck_long(expr) \
(__builtin_types_compatible_p(__typeof__(expr), long) || \
__builtin_types_compatible_p(__typeof__(expr), signed long) || \
__builtin_types_compatible_p(__typeof__(expr), unsigned long) || \
@ -464,57 +478,59 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
__builtin_types_compatible_p(__typeof__(expr), unsigned char))
/* evaluates to true if expr is of type curl_off_t */
#define _curl_is_off_t(expr) \
#define curlcheck_off_t(expr) \
(__builtin_types_compatible_p(__typeof__(expr), curl_off_t))
/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */
/* XXX: also check size of an char[] array? */
#define _curl_is_error_buffer(expr) \
(_curl_is_NULL(expr) || \
__builtin_types_compatible_p(__typeof__(expr), char *) || \
#define curlcheck_error_buffer(expr) \
(curlcheck_NULL(expr) || \
__builtin_types_compatible_p(__typeof__(expr), char *) || \
__builtin_types_compatible_p(__typeof__(expr), char[]))
/* evaluates to true if expr is of type (const) void* or (const) FILE* */
#if 0
#define _curl_is_cb_data(expr) \
(_curl_is_ptr((expr), void) || \
_curl_is_ptr((expr), FILE))
#define curlcheck_cb_data(expr) \
(curlcheck_ptr((expr), void) || \
curlcheck_ptr((expr), FILE))
#else /* be less strict */
#define _curl_is_cb_data(expr) \
_curl_is_any_ptr(expr)
#define curlcheck_cb_data(expr) \
curlcheck_any_ptr(expr)
#endif
/* evaluates to true if expr is of type FILE* */
#define _curl_is_FILE(expr) \
(_curl_is_NULL(expr) || \
#define curlcheck_FILE(expr) \
(curlcheck_NULL(expr) || \
(__builtin_types_compatible_p(__typeof__(expr), FILE *)))
/* evaluates to true if expr can be passed as POST data (void* or char*) */
#define _curl_is_postfields(expr) \
(_curl_is_ptr((expr), void) || \
_curl_is_arr((expr), char))
#define curlcheck_postfields(expr) \
(curlcheck_ptr((expr), void) || \
curlcheck_arr((expr), char) || \
curlcheck_arr((expr), unsigned char))
/* FIXME: the whole callback checking is messy...
* The idea is to tolerate char vs. void and const vs. not const
* pointers in arguments at least
*/
/* helper: __builtin_types_compatible_p distinguishes between functions and
* function pointers, hide it */
#define _curl_callback_compatible(func, type) \
(__builtin_types_compatible_p(__typeof__(func), type) || \
#define curlcheck_cb_compatible(func, type) \
(__builtin_types_compatible_p(__typeof__(func), type) || \
__builtin_types_compatible_p(__typeof__(func) *, type))
/* evaluates to true if expr is of type curl_resolver_start_callback */
#define curlcheck_resolver_start_callback(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_resolver_start_callback))
/* evaluates to true if expr is of type curl_read_callback or "similar" */
#define _curl_is_read_cb(expr) \
(_curl_is_NULL(expr) || \
_curl_callback_compatible((expr), __typeof__(fread) *) || \
_curl_callback_compatible((expr), curl_read_callback) || \
_curl_callback_compatible((expr), _curl_read_callback1) || \
_curl_callback_compatible((expr), _curl_read_callback2) || \
_curl_callback_compatible((expr), _curl_read_callback3) || \
_curl_callback_compatible((expr), _curl_read_callback4) || \
_curl_callback_compatible((expr), _curl_read_callback5) || \
_curl_callback_compatible((expr), _curl_read_callback6))
#define curlcheck_read_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), __typeof__(fread) *) || \
curlcheck_cb_compatible((expr), curl_read_callback) || \
curlcheck_cb_compatible((expr), _curl_read_callback1) || \
curlcheck_cb_compatible((expr), _curl_read_callback2) || \
curlcheck_cb_compatible((expr), _curl_read_callback3) || \
curlcheck_cb_compatible((expr), _curl_read_callback4) || \
curlcheck_cb_compatible((expr), _curl_read_callback5) || \
curlcheck_cb_compatible((expr), _curl_read_callback6))
typedef size_t (*_curl_read_callback1)(char *, size_t, size_t, void *);
typedef size_t (*_curl_read_callback2)(char *, size_t, size_t, const void *);
typedef size_t (*_curl_read_callback3)(char *, size_t, size_t, FILE *);
@ -523,16 +539,16 @@ typedef size_t (*_curl_read_callback5)(void *, size_t, size_t, const void *);
typedef size_t (*_curl_read_callback6)(void *, size_t, size_t, FILE *);
/* evaluates to true if expr is of type curl_write_callback or "similar" */
#define _curl_is_write_cb(expr) \
(_curl_is_read_cb(expr) || \
_curl_callback_compatible((expr), __typeof__(fwrite) *) || \
_curl_callback_compatible((expr), curl_write_callback) || \
_curl_callback_compatible((expr), _curl_write_callback1) || \
_curl_callback_compatible((expr), _curl_write_callback2) || \
_curl_callback_compatible((expr), _curl_write_callback3) || \
_curl_callback_compatible((expr), _curl_write_callback4) || \
_curl_callback_compatible((expr), _curl_write_callback5) || \
_curl_callback_compatible((expr), _curl_write_callback6))
#define curlcheck_write_cb(expr) \
(curlcheck_read_cb(expr) || \
curlcheck_cb_compatible((expr), __typeof__(fwrite) *) || \
curlcheck_cb_compatible((expr), curl_write_callback) || \
curlcheck_cb_compatible((expr), _curl_write_callback1) || \
curlcheck_cb_compatible((expr), _curl_write_callback2) || \
curlcheck_cb_compatible((expr), _curl_write_callback3) || \
curlcheck_cb_compatible((expr), _curl_write_callback4) || \
curlcheck_cb_compatible((expr), _curl_write_callback5) || \
curlcheck_cb_compatible((expr), _curl_write_callback6))
typedef size_t (*_curl_write_callback1)(const char *, size_t, size_t, void *);
typedef size_t (*_curl_write_callback2)(const char *, size_t, size_t,
const void *);
@ -543,37 +559,37 @@ typedef size_t (*_curl_write_callback5)(const void *, size_t, size_t,
typedef size_t (*_curl_write_callback6)(const void *, size_t, size_t, FILE *);
/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */
#define _curl_is_ioctl_cb(expr) \
(_curl_is_NULL(expr) || \
_curl_callback_compatible((expr), curl_ioctl_callback) || \
_curl_callback_compatible((expr), _curl_ioctl_callback1) || \
_curl_callback_compatible((expr), _curl_ioctl_callback2) || \
_curl_callback_compatible((expr), _curl_ioctl_callback3) || \
_curl_callback_compatible((expr), _curl_ioctl_callback4))
#define curlcheck_ioctl_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_ioctl_callback) || \
curlcheck_cb_compatible((expr), _curl_ioctl_callback1) || \
curlcheck_cb_compatible((expr), _curl_ioctl_callback2) || \
curlcheck_cb_compatible((expr), _curl_ioctl_callback3) || \
curlcheck_cb_compatible((expr), _curl_ioctl_callback4))
typedef curlioerr (*_curl_ioctl_callback1)(CURL *, int, void *);
typedef curlioerr (*_curl_ioctl_callback2)(CURL *, int, const void *);
typedef curlioerr (*_curl_ioctl_callback3)(CURL *, curliocmd, void *);
typedef curlioerr (*_curl_ioctl_callback4)(CURL *, curliocmd, const void *);
/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */
#define _curl_is_sockopt_cb(expr) \
(_curl_is_NULL(expr) || \
_curl_callback_compatible((expr), curl_sockopt_callback) || \
_curl_callback_compatible((expr), _curl_sockopt_callback1) || \
_curl_callback_compatible((expr), _curl_sockopt_callback2))
#define curlcheck_sockopt_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_sockopt_callback) || \
curlcheck_cb_compatible((expr), _curl_sockopt_callback1) || \
curlcheck_cb_compatible((expr), _curl_sockopt_callback2))
typedef int (*_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
typedef int (*_curl_sockopt_callback2)(const void *, curl_socket_t,
curlsocktype);
/* evaluates to true if expr is of type curl_opensocket_callback or
"similar" */
#define _curl_is_opensocket_cb(expr) \
(_curl_is_NULL(expr) || \
_curl_callback_compatible((expr), curl_opensocket_callback) || \
_curl_callback_compatible((expr), _curl_opensocket_callback1) || \
_curl_callback_compatible((expr), _curl_opensocket_callback2) || \
_curl_callback_compatible((expr), _curl_opensocket_callback3) || \
_curl_callback_compatible((expr), _curl_opensocket_callback4))
#define curlcheck_opensocket_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_opensocket_callback) || \
curlcheck_cb_compatible((expr), _curl_opensocket_callback1) || \
curlcheck_cb_compatible((expr), _curl_opensocket_callback2) || \
curlcheck_cb_compatible((expr), _curl_opensocket_callback3) || \
curlcheck_cb_compatible((expr), _curl_opensocket_callback4))
typedef curl_socket_t (*_curl_opensocket_callback1)
(void *, curlsocktype, struct curl_sockaddr *);
typedef curl_socket_t (*_curl_opensocket_callback2)
@ -584,28 +600,28 @@ typedef curl_socket_t (*_curl_opensocket_callback4)
(const void *, curlsocktype, const struct curl_sockaddr *);
/* evaluates to true if expr is of type curl_progress_callback or "similar" */
#define _curl_is_progress_cb(expr) \
(_curl_is_NULL(expr) || \
_curl_callback_compatible((expr), curl_progress_callback) || \
_curl_callback_compatible((expr), _curl_progress_callback1) || \
_curl_callback_compatible((expr), _curl_progress_callback2))
#define curlcheck_progress_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_progress_callback) || \
curlcheck_cb_compatible((expr), _curl_progress_callback1) || \
curlcheck_cb_compatible((expr), _curl_progress_callback2))
typedef int (*_curl_progress_callback1)(void *,
double, double, double, double);
typedef int (*_curl_progress_callback2)(const void *,
double, double, double, double);
/* evaluates to true if expr is of type curl_debug_callback or "similar" */
#define _curl_is_debug_cb(expr) \
(_curl_is_NULL(expr) || \
_curl_callback_compatible((expr), curl_debug_callback) || \
_curl_callback_compatible((expr), _curl_debug_callback1) || \
_curl_callback_compatible((expr), _curl_debug_callback2) || \
_curl_callback_compatible((expr), _curl_debug_callback3) || \
_curl_callback_compatible((expr), _curl_debug_callback4) || \
_curl_callback_compatible((expr), _curl_debug_callback5) || \
_curl_callback_compatible((expr), _curl_debug_callback6) || \
_curl_callback_compatible((expr), _curl_debug_callback7) || \
_curl_callback_compatible((expr), _curl_debug_callback8))
#define curlcheck_debug_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_debug_callback) || \
curlcheck_cb_compatible((expr), _curl_debug_callback1) || \
curlcheck_cb_compatible((expr), _curl_debug_callback2) || \
curlcheck_cb_compatible((expr), _curl_debug_callback3) || \
curlcheck_cb_compatible((expr), _curl_debug_callback4) || \
curlcheck_cb_compatible((expr), _curl_debug_callback5) || \
curlcheck_cb_compatible((expr), _curl_debug_callback6) || \
curlcheck_cb_compatible((expr), _curl_debug_callback7) || \
curlcheck_cb_compatible((expr), _curl_debug_callback8))
typedef int (*_curl_debug_callback1) (CURL *,
curl_infotype, char *, size_t, void *);
typedef int (*_curl_debug_callback2) (CURL *,
@ -625,17 +641,17 @@ typedef int (*_curl_debug_callback8) (CURL *,
/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */
/* this is getting even messier... */
#define _curl_is_ssl_ctx_cb(expr) \
(_curl_is_NULL(expr) || \
_curl_callback_compatible((expr), curl_ssl_ctx_callback) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback1) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback2) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback3) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback4) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback5) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback6) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback7) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback8))
#define curlcheck_ssl_ctx_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_ssl_ctx_callback) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback1) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback2) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback3) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback4) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback5) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback6) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback7) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback8))
typedef CURLcode (*_curl_ssl_ctx_callback1)(CURL *, void *, void *);
typedef CURLcode (*_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
typedef CURLcode (*_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
@ -658,26 +674,26 @@ typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8;
#endif
/* evaluates to true if expr is of type curl_conv_callback or "similar" */
#define _curl_is_conv_cb(expr) \
(_curl_is_NULL(expr) || \
_curl_callback_compatible((expr), curl_conv_callback) || \
_curl_callback_compatible((expr), _curl_conv_callback1) || \
_curl_callback_compatible((expr), _curl_conv_callback2) || \
_curl_callback_compatible((expr), _curl_conv_callback3) || \
_curl_callback_compatible((expr), _curl_conv_callback4))
#define curlcheck_conv_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_conv_callback) || \
curlcheck_cb_compatible((expr), _curl_conv_callback1) || \
curlcheck_cb_compatible((expr), _curl_conv_callback2) || \
curlcheck_cb_compatible((expr), _curl_conv_callback3) || \
curlcheck_cb_compatible((expr), _curl_conv_callback4))
typedef CURLcode (*_curl_conv_callback1)(char *, size_t length);
typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length);
typedef CURLcode (*_curl_conv_callback3)(void *, size_t length);
typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length);
/* evaluates to true if expr is of type curl_seek_callback or "similar" */
#define _curl_is_seek_cb(expr) \
(_curl_is_NULL(expr) || \
_curl_callback_compatible((expr), curl_seek_callback) || \
_curl_callback_compatible((expr), _curl_seek_callback1) || \
_curl_callback_compatible((expr), _curl_seek_callback2))
#define curlcheck_seek_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_seek_callback) || \
curlcheck_cb_compatible((expr), _curl_seek_callback1) || \
curlcheck_cb_compatible((expr), _curl_seek_callback2))
typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int);
typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int);
#endif /* __CURL_TYPECHECK_GCC_H */
#endif /* CURLINC_TYPECHECK_GCC_H */

125
include/curl/urlapi.h Normal file
View file

@ -0,0 +1,125 @@
#ifndef CURLINC_URLAPI_H
#define CURLINC_URLAPI_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2018 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include "curl.h"
#ifdef __cplusplus
extern "C" {
#endif
/* the error codes for the URL API */
typedef enum {
CURLUE_OK,
CURLUE_BAD_HANDLE, /* 1 */
CURLUE_BAD_PARTPOINTER, /* 2 */
CURLUE_MALFORMED_INPUT, /* 3 */
CURLUE_BAD_PORT_NUMBER, /* 4 */
CURLUE_UNSUPPORTED_SCHEME, /* 5 */
CURLUE_URLDECODE, /* 6 */
CURLUE_OUT_OF_MEMORY, /* 7 */
CURLUE_USER_NOT_ALLOWED, /* 8 */
CURLUE_UNKNOWN_PART, /* 9 */
CURLUE_NO_SCHEME, /* 10 */
CURLUE_NO_USER, /* 11 */
CURLUE_NO_PASSWORD, /* 12 */
CURLUE_NO_OPTIONS, /* 13 */
CURLUE_NO_HOST, /* 14 */
CURLUE_NO_PORT, /* 15 */
CURLUE_NO_QUERY, /* 16 */
CURLUE_NO_FRAGMENT /* 17 */
} CURLUcode;
typedef enum {
CURLUPART_URL,
CURLUPART_SCHEME,
CURLUPART_USER,
CURLUPART_PASSWORD,
CURLUPART_OPTIONS,
CURLUPART_HOST,
CURLUPART_PORT,
CURLUPART_PATH,
CURLUPART_QUERY,
CURLUPART_FRAGMENT,
CURLUPART_ZONEID /* added in 7.65.0 */
} CURLUPart;
#define CURLU_DEFAULT_PORT (1<<0) /* return default port number */
#define CURLU_NO_DEFAULT_PORT (1<<1) /* act as if no port number was set,
if the port number matches the
default for the scheme */
#define CURLU_DEFAULT_SCHEME (1<<2) /* return default scheme if
missing */
#define CURLU_NON_SUPPORT_SCHEME (1<<3) /* allow non-supported scheme */
#define CURLU_PATH_AS_IS (1<<4) /* leave dot sequences */
#define CURLU_DISALLOW_USER (1<<5) /* no user+password allowed */
#define CURLU_URLDECODE (1<<6) /* URL decode on get */
#define CURLU_URLENCODE (1<<7) /* URL encode on set */
#define CURLU_APPENDQUERY (1<<8) /* append a form style part */
#define CURLU_GUESS_SCHEME (1<<9) /* legacy curl-style guessing */
#define CURLU_NO_AUTHORITY (1<<10) /* Allow empty authority when the
scheme is unknown. */
typedef struct Curl_URL CURLU;
/*
* curl_url() creates a new CURLU handle and returns a pointer to it.
* Must be freed with curl_url_cleanup().
*/
CURL_EXTERN CURLU *curl_url(void);
/*
* curl_url_cleanup() frees the CURLU handle and related resources used for
* the URL parsing. It will not free strings previously returned with the URL
* API.
*/
CURL_EXTERN void curl_url_cleanup(CURLU *handle);
/*
* curl_url_dup() duplicates a CURLU handle and returns a new copy. The new
* handle must also be freed with curl_url_cleanup().
*/
CURL_EXTERN CURLU *curl_url_dup(CURLU *in);
/*
* curl_url_get() extracts a specific part of the URL from a CURLU
* handle. Returns error code. The returned pointer MUST be freed with
* curl_free() afterwards.
*/
CURL_EXTERN CURLUcode curl_url_get(CURLU *handle, CURLUPart what,
char **part, unsigned int flags);
/*
* curl_url_set() sets a specific part of the URL in a CURLU handle. Returns
* error code. The passed in string will be copied. Passing a NULL instead of
* a part string, clears that part.
*/
CURL_EXTERN CURLUcode curl_url_set(CURLU *handle, CURLUPart what,
const char *part, unsigned int flags);
#ifdef __cplusplus
} /* end of extern "C" */
#endif
#endif /* CURLINC_URLAPI_H */

View file

@ -62,7 +62,7 @@ Menu screen by MDK
Load screen by Christopher "Sherpa" Owen
Weapon glow skins in kmquake2_extras.pk3 by Odium and Kman
Weapon glow skins in kmquake2_extras.pk3 by Odium and Kman and from Quake2XP
Uses Zlib compression library, (c) 1995-2002 Jean-loup Gailly and Mark Adler

View file

@ -13,6 +13,8 @@ Changes as of v0.20 update 8:
- Added Windows DPI scaling detection from Yamagi Quake2.
- Added UDP fallback from HTTP downloads and support for Q2Pro-style HTTP URLs.
- Added support for quake2:// URLs.
- Added cel shading support. Uses cvars r_celshading to enable, and r_celshading_width for line width (1-10).

View file

@ -72,7 +72,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="wsock32.lib winmm.lib libjpeg_d.lib zlib_d.lib libogg_d.lib libvorbisfile_d.lib libpng_d.lib libcurl_r.lib glu32.lib"
AdditionalDependencies="wsock32.lib winmm.lib libjpeg_d.lib zlib_d.lib libogg_d.lib libvorbisfile_d.lib libpng_d.lib libcurl_d.lib glu32.lib"
OutputFile="./kmquake2.exe"
LinkIncremental="1"
SuppressStartupBanner="true"

View file

@ -73,7 +73,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="wsock32.lib winmm.lib glu32.lib libjpeg_d.lib zlib_d.lib libogg_d.lib libvorbisfile_d.lib libpng_d.lib libcurl_r.lib"
AdditionalDependencies="wsock32.lib winmm.lib glu32.lib libjpeg_d.lib zlib_d.lib libogg_d.lib libvorbisfile_d.lib libpng_d.lib libcurl_d.lib"
OutputFile="./kmquake2.exe"
LinkIncremental="1"
SuppressStartupBanner="true"

View file

@ -114,6 +114,7 @@ typedef struct {
int numFiles;
fsPackFile_t *files;
unsigned int contentFlags;
qboolean isProtectedPak; // from Yamagi Q2
} fsPack_t;
typedef struct fsSearchPath_s {
@ -128,11 +129,14 @@ fsSearchPath_t *fs_searchPaths;
fsSearchPath_t *fs_baseSearchPaths;
char fs_gamedir[MAX_OSPATH];
char fs_savegamedir[MAX_OSPATH];
char fs_downloaddir[MAX_OSPATH];
static char fs_currentGame[MAX_QPATH];
static char fs_fileInPath[MAX_OSPATH];
static qboolean fs_fileInPack;
int file_from_protected_pak; // This is set by FS_FOpenFile, from Yamagi Q2
int file_from_pak = 0; // This is set by FS_FOpenFile
int file_from_pk3 = 0; // This is set by FS_FOpenFile
char last_pk3_name[MAX_QPATH]; // This is set by FS_FOpenFile
@ -354,9 +358,50 @@ char *FS_GameDir (void)
return fs_gamedir;
}
char *FS_Gamedir (void)
/*char *FS_Gamedir (void)
{
return fs_gamedir;
}*/
/*
=================
FS_SaveGameDir
Called to find where to write and read save games.
Either fs_savegamedir (which results in Sys_PrefDir()/<gamedir>) or FS_Gamedir()
=================
*/
char *FS_SaveGameDir (void)
{
return (strlen(fs_savegamedir) > 0) ? fs_savegamedir : FS_GameDir();
}
/*
=================
FS_DownloadDir
Called to find where to download game content.
Either fs_downloaddir (which results in Sys_DownloadDir()/<gamedir>) or FS_Gamedir()
=================
*/
char *FS_DownloadDir (void)
{
return (strlen(fs_downloaddir) > 0) ? fs_downloaddir : FS_GameDir();
}
/*
=================
FS_HomePath
Called to find game root path
=================
*/
char *FS_HomePath (void)
{
return fs_homepath->string;
}
@ -507,7 +552,12 @@ int FS_FOpenFileAppend (fsHandle_t *handle)
{
char path[MAX_OSPATH];
FS_CreatePath(handle->name);
// FS_CreatePath(handle->name);
// include game path, but check for leading /
if (handle->name[0] == '/')
FS_CreatePath (va("%s%s", fs_gamedir, handle->name));
else
FS_CreatePath (va("%s/%s", fs_gamedir, handle->name));
Com_sprintf(path, sizeof(path), "%s/%s", fs_gamedir, handle->name);
@ -538,7 +588,12 @@ int FS_FOpenFileWrite (fsHandle_t *handle)
{
char path[MAX_OSPATH];
FS_CreatePath(handle->name);
// FS_CreatePath(handle->name);
// include game path, but check for leading /
if (handle->name[0] == '/')
FS_CreatePath (va("%s%s", fs_gamedir, handle->name));
else
FS_CreatePath (va("%s/%s", fs_gamedir, handle->name));
Com_sprintf(path, sizeof(path), "%s/%s", fs_gamedir, handle->name);
@ -576,6 +631,7 @@ int FS_FOpenFileRead (fsHandle_t *handle)
unsigned int typeFlag;
// Knightmare- hack global vars for autodownloads
file_from_protected_pak = 0; // from Yamagi Q2
file_from_pak = 0;
file_from_pk3 = 0;
Com_sprintf(last_pk3_name, sizeof(last_pk3_name), "\0");
@ -621,6 +677,7 @@ int FS_FOpenFileRead (fsHandle_t *handle)
if (pack->pak)
{ // PAK
file_from_pak = 1; // Knightmare added
file_from_protected_pak = pack->isProtectedPak ? 1 : 0; // from Yamagi Q2
handle->file = fopen(pack->name, "rb");
handle->pakFile = &pack->files[i]; // set pakfile pointer
if (handle->file)
@ -633,6 +690,7 @@ int FS_FOpenFileRead (fsHandle_t *handle)
else if (pack->pk3)
{ // PK3
file_from_pk3 = 1; // Knightmare added
file_from_protected_pak = pack->isProtectedPak ? 1 : 0; // from Yamagi Q2
Com_sprintf(last_pk3_name, sizeof(last_pk3_name), strrchr(pack->name, '/')+1); // Knightmare added
handle->zip = unzOpen(pack->name);
if (handle->zip)
@ -1579,6 +1637,43 @@ qboolean FS_LocalFileExists (char *path)
return false;
}
/*
=================
FS_SaveFileExists
================
*/
qboolean FS_SaveFileExists (char *path)
{
char realPath[MAX_OSPATH];
FILE *f;
Com_sprintf (realPath, sizeof(realPath), "%s/%s", FS_SaveGameDir(), path); // was FS_GameDir()
f = fopen (realPath, "rb");
if (f) {
fclose(f);
return true;
}
return false;
}
/*
=================
FS_DownloadFileExists
================
*/
qboolean FS_DownloadFileExists (char *path)
{
char realPath[MAX_OSPATH];
FILE *f;
Com_sprintf (realPath, sizeof(realPath), "%s/%s", FS_DownloadDir(), path);
f = fopen (realPath, "rb");
if (f) {
fclose(f);
return true;
}
return false;
}
/*
================
FS_CopyFile
@ -1894,7 +1989,7 @@ FS_AddPAKFile
Adds a Pak file to the searchpath
=================
*/
void FS_AddPAKFile (const char *packPath)
void FS_AddPAKFile (const char *packPath, qboolean isProtected)
{
fsSearchPath_t *search;
fsPack_t *pack;
@ -1902,6 +1997,7 @@ void FS_AddPAKFile (const char *packPath)
pack = FS_LoadPAK (packPath);
if (!pack)
return;
pack->isProtectedPak = isProtected; // From Yamagi Q2
search = Z_Malloc (sizeof(fsSearchPath_t));
search->pack = pack;
search->next = fs_searchPaths;
@ -2035,7 +2131,7 @@ FS_AddPK3File
Adds a Pk3 file to the searchpath
=================
*/
void FS_AddPK3File (const char *packPath)
void FS_AddPK3File (const char *packPath, qboolean isProtected)
{
fsSearchPath_t *search;
fsPack_t *pack;
@ -2043,6 +2139,7 @@ void FS_AddPK3File (const char *packPath)
pack = FS_LoadPK3 (packPath);
if (!pack)
return;
pack->isProtectedPak = isProtected; // From Yamagi Q2
search = Z_Malloc (sizeof(fsSearchPath_t));
search->pack = pack;
search->next = fs_searchPaths;
@ -2051,48 +2148,32 @@ void FS_AddPK3File (const char *packPath)
/*
=================
FS_AddGameDirectory
FS_AddPaksInDirectory
Sets fs_gameDir, adds the directory to the head of the path, then loads
and adds all the pack files found (in alphabetical order).
Used by FS_AddGameDirectory() and FS_AddDownloadDirectory().
Loads and adds all the pack files found
(first numerically 0-99 and then in alphabetical order).
PK3 files are loaded later so they override PAK files.
=================
*/
void FS_AddGameDirectory (const char *dir)
void FS_AddPaksInDirectory (const char *dir)
{
fsSearchPath_t *search;
// fsPack_t *pack;
char packPath[MAX_OSPATH];
int i, j;
char packPath[MAX_OSPATH];
int i, j;
// VoiD -S- *.pak support
char *path = NULL;
char findname[1024];
char **dirnames;
int ndirs;
char *tmp;
char findname[1024];
char **dirnames;
int ndirs;
char *tmp;
// VoiD -E- *.pak support
// strncpy(fs_gamedir, dir);
Q_strncpyz(fs_gamedir, dir, sizeof(fs_gamedir));
//
// Add the directory to the search path
//
search = Z_Malloc(sizeof(fsSearchPath_t));
// strncpy(search->path, dir);
Q_strncpyz(search->path, dir, sizeof(search->path));
search->path[sizeof(search->path)-1] = 0;
search->next = fs_searchPaths;
fs_searchPaths = search;
//
// add any pak files in the format pak0.pak pak1.pak, ...
//
for (i=0; i<100; i++) // Pooy - paks can now go up to 100
{
Com_sprintf (packPath, sizeof(packPath), "%s/pak%i.pak", dir, i);
FS_AddPAKFile (packPath);
FS_AddPAKFile (packPath, ((i<10) ? true : false)); // pak0.pak is protected
}
//
// NeVo - pak3's!
@ -2101,7 +2182,7 @@ void FS_AddGameDirectory (const char *dir)
for (i=0; i<100; i++) // Pooy - paks can now go up to 100
{
Com_sprintf (packPath, sizeof(packPath), "%s/pak%i.pk3", dir, i);
FS_AddPK3File (packPath);
FS_AddPK3File (packPath, false);
}
for (i=0; i<2; i++)
@ -2146,10 +2227,10 @@ void FS_AddGameDirectory (const char *dir)
continue;
if ( strrchr( dirnames[j], '/' ) )
{
if (i==1)
FS_AddPK3File (dirnames[j]);
if (i == 1)
FS_AddPK3File (dirnames[j], false);
else
FS_AddPAKFile (dirnames[j]);
FS_AddPAKFile (dirnames[j], false);
}
free( dirnames[j] );
}
@ -2159,6 +2240,116 @@ void FS_AddGameDirectory (const char *dir)
}
}
/*
=================
FS_AddGameDirectory
Sets fs_gamedir, adds the directory to the head of the path,
then loads any pack files in that path by calling FS_AddPaksInDirectory().
=================
*/
void FS_AddGameDirectory (const char *dir)
{
fsSearchPath_t *search;
Q_strncpyz(fs_gamedir, dir, sizeof(fs_gamedir));
//
// Add the directory to the search path
//
search = Z_Malloc(sizeof(fsSearchPath_t));
Q_strncpyz(search->path, dir, sizeof(search->path));
search->path[sizeof(search->path)-1] = 0;
search->next = fs_searchPaths;
fs_searchPaths = search;
//
// Load pack files
//
FS_AddPaksInDirectory (dir);
}
#ifdef USE_SAVEGAMEDIR
/*
=================
FS_AddSaveGameDirectory
Adds the savegame directory to the head of the path.
Should only be called after the final FS_AddGameDirectory() call.
Sets fs_savegamedir, not fs_gamedir, and does not load any pack files.
=================
*/
void FS_AddSaveGameDirectory (char *dir)
{
fsSearchPath_t *search;
if (!dir)
return;
if (strlen(dir) < 1) // catch 0-length string
return;
Com_sprintf (fs_savegamedir, sizeof(fs_savegamedir), "%s/%s", Sys_PrefDir(), dir);
if (!stricmp(fs_savegamedir, fs_gamedir)) // only add if different from fs_gamedir
return;
FS_CreatePath (va("%s/", fs_savegamedir)); // create savegamedir if it doesn't yet exist
//
// Add the directory to the search path
//
search = Z_Malloc(sizeof(fsSearchPath_t));
Q_strncpyz(search->path, fs_savegamedir, sizeof(search->path));
search->path[sizeof(search->path)-1] = 0;
search->next = fs_searchPaths;
fs_searchPaths = search;
}
/*
=================
FS_AddDownloadDirectory
Adds the download directory to the head of the path.
Should only be called after the final FS_AddGameDirectory() call.
Sets fs_downloaddir, not fs_gamedir, and loads any pack files
in that path by calling FS_AddPaksInDirectory().
=================
*/
void FS_AddDownloadDirectory (char *dir)
{
fsSearchPath_t *search;
if (!dir)
return;
if (strlen(dir) < 1) // catch 0-length string
return;
Com_sprintf (fs_downloaddir, sizeof(fs_downloaddir), "%s/%s", Sys_DownloadDir(), dir);
if (!stricmp(fs_downloaddir, fs_gamedir)) // only add if different from fs_gamedir
return;
FS_CreatePath (va("%s/", fs_downloaddir)); // create downloaddir if it doesn't yet exist
//
// Add the directory to the search path
//
search = Z_Malloc(sizeof(fsSearchPath_t));
Q_strncpyz(search->path, fs_downloaddir, sizeof(search->path));
search->path[sizeof(search->path)-1] = 0;
search->next = fs_searchPaths;
fs_searchPaths = search;
//
// Load pack files
//
FS_AddPaksInDirectory (dir);
}
#endif // USE_SAVEGAMEDIR
/*
=================
FS_NextPath
@ -2189,6 +2380,44 @@ char *FS_NextPath (char *prevPath)
}
/*
=================
FS_NextGamePath
Allows enumerating all of the directories in the search path
Only called from Sys_GetGameAPI
Skips fs_savegamedir and fs_downloaddir,
so as not to load game library from there.
=================
*/
char *FS_NextGamePath (char *prevPath)
{
fsSearchPath_t *search;
char *prev;
if (!prevPath)
return fs_gamedir;
prev = fs_gamedir;
for (search = fs_searchPaths; search; search = search->next)
{
if (search->pack)
continue;
// explicitly skip fs_savegamedir and fs_downloaddir
if ( (strlen(search->path) > 0) &&
((Q_stricmp(search->path, fs_savegamedir) == 0) || (Q_stricmp(search->path, fs_downloaddir) == 0)) )
continue;
if (prevPath == prev)
return search->path;
prev = search->path;
}
return NULL;
}
/*
=================
FS_Path_f
@ -2214,7 +2443,12 @@ void FS_Path_f (void)
Com_Printf("%s\n", search->path);
}
//Com_Printf("\n");
// Com_Printf("\n");
Com_Printf("Current game dir: %s\n", fs_gamedir);
#ifdef USE_SAVEGAMEDIR
Com_Printf("Current savegame dir: %s\n", fs_savegamedir);
Com_Printf("Current download dir: %s\n", fs_downloaddir);
#endif
for (i = 0, handle = fs_handles; i < MAX_HANDLES; i++, handle++)
{
@ -2237,6 +2471,7 @@ FS_Startup
TODO: close open files for game dir
=================
*/
#if 0
void FS_Startup (void)
{
if (strstr(fs_gamedirvar->string, "..") || strstr(fs_gamedirvar->string, ".")
@ -2289,6 +2524,61 @@ void FS_Startup (void)
FS_Path_f();
}
#endif
#ifdef USE_SAVEGAMEDIR
/*
=================
FS_CopyConfigsToSavegameDir
=================
*/
void FS_CopyConfigsToSavegameDir (void)
{
FILE *kmq2ConfigFile;
char cfgPattern[MAX_OSPATH];
char *srcCfgPath;
char dstCfgPath[MAX_OSPATH];
char *cfgName;
// check if fs_savegamedir and fs_gamedir are the same, so we don't try to copy the files over each other
if (!stricmp(FS_SaveGameDir(), fs_gamedir))
return;
// check if kmq2config.cfg exists in FS_SaveGameDir() so we can skip copying
kmq2ConfigFile = fopen(va("%s/kmq2config.cfg", FS_SaveGameDir()), "rb");
if (kmq2ConfigFile != NULL)
{
fclose(kmq2ConfigFile);
return;
}
// create savegamedir if it doesn't yet exist
FS_CreatePath (va("%s/", fs_savegamedir));
Com_sprintf (cfgPattern, sizeof(cfgPattern), "%s/*.cfg", fs_gamedir);
for (srcCfgPath = Sys_FindFirst(cfgPattern, 0, SFF_SUBDIR|SFF_HIDDEN|SFF_SYSTEM);
srcCfgPath != NULL;
srcCfgPath = Sys_FindNext (0, SFF_SUBDIR|SFF_HIDDEN|SFF_SYSTEM))
{
cfgName = strrchr(srcCfgPath, '/');
if (cfgName == NULL) {
continue;
}
++cfgName; // move to after the '/'
// don't copy configs written by other engines
// TODO: keep this up to date!
// config.cfg, aprconfig.cfg, bqconfig.cfg, eglcfg.cfg, maxconfig.cfg, q2config.cfg, q2b_config.cfg, q2econfig.cfg, xpconfig.cfg, yq2.cfg
if ( (strstr(cfgName, "config.cfg") && stricmp(cfgName, "kmq2config.cfg")) || !stricmp(cfgName, "eglcfg.cfg") || !stricmp(cfgName, "yq2.cfg") ) {
continue;
}
Com_sprintf (dstCfgPath, sizeof(dstCfgPath), "%s/%s", FS_SaveGameDir(), cfgName);
FS_CopyFile (srcCfgPath, dstCfgPath);
}
Sys_FindClose();
}
#endif // USE_SAVEGAMEDIR
/*
=================
@ -2301,6 +2591,10 @@ char *Sys_GetCurrentDirectory (void);
void FS_InitFilesystem (void)
{
// init savegame/download dirs as null string
fs_savegamedir[0] = '\0';
fs_downloaddir[0] = '\0';
// Register our commands and cvars
Cmd_AddCommand("path", FS_Path_f);
Cmd_AddCommand("link", FS_Link_f);
@ -2347,10 +2641,26 @@ void FS_InitFilesystem (void)
Sys_InitPrefDir (); // set up pref dir now instead of calling a function every time it's needed
#endif
// set our savegame/download dirs with Sys_PrefDir() and baseq2
#ifdef USE_SAVEGAMEDIR
FS_AddDownloadDirectory (BASEDIRNAME);
FS_AddSaveGameDirectory (BASEDIRNAME);
// Com_sprintf (fs_savegamedir, sizeof(fs_savegamedir), "%s/%s", Sys_PrefDir(), BASEDIRNAME);
// Com_sprintf (fs_downloaddir, sizeof(fs_downloaddir), "%s/%s", Sys_DownloadDir(), BASEDIRNAME);
#else
Q_strncpyz(fs_savegamedir, fs_gamedir, sizeof(fs_savegamedir));
Q_strncpyz(fs_downloaddir, fs_gamedir, sizeof(fs_downloaddir));
#endif // USE_SAVEGAMEDIR
// check and load game directory
if (fs_gamedirvar->string[0])
FS_SetGamedir (fs_gamedirvar->string);
#ifdef USE_SAVEGAMEDIR
// copy over configs from gamedir to savegamedir if it's empty
FS_CopyConfigsToSavegameDir ();
#endif // USE_SAVEGAMEDIR
FS_Path_f(); // output path data
}
@ -2508,6 +2818,16 @@ void FS_SetGamedir (char *dir)
{
Cvar_FullSet ("gamedir", "", CVAR_SERVERINFO|CVAR_NOSET);
Cvar_FullSet ("game", "", CVAR_LATCH|CVAR_SERVERINFO);
// set our savegame/download dirs with Sys_PrefDir() and baseq2
#ifdef USE_SAVEGAMEDIR
FS_AddDownloadDirectory (BASEDIRNAME);
FS_AddSaveGameDirectory (BASEDIRNAME);
// Com_sprintf (fs_savegamedir, sizeof(fs_savegamedir), "%s/%s", Sys_PrefDir(), BASEDIRNAME);
// Com_sprintf (fs_downloaddir, sizeof(fs_downloaddir), "%s/%s", Sys_DownloadDir(), BASEDIRNAME);
#else
Q_strncpyz(fs_savegamedir, fs_gamedir, sizeof(fs_savegamedir));
Q_strncpyz(fs_downloaddir, fs_gamedir, sizeof(fs_downloaddir));
#endif // USE_SAVEGAMEDIR
}
else
{
@ -2544,6 +2864,17 @@ void FS_SetGamedir (char *dir)
if (fs_cddir->string[0])
FS_AddGameDirectory (va("%s/%s", fs_cddir->string, dir) );
FS_AddGameDirectory (va("%s/%s", fs_basedir->string, dir) );
// set our savegame/download dirs with Sys_PrefDir() and baseq2
#ifdef USE_SAVEGAMEDIR
FS_AddDownloadDirectory (dir);
FS_AddSaveGameDirectory (dir);
// Com_sprintf (fs_savegamedir, sizeof(fs_savegamedir), "%s/%s", Sys_PrefDir(), dir);
// Com_sprintf (fs_downloaddir, sizeof(fs_downloaddir), "%s/%s", Sys_DownloadDir(), dir);
#else
Q_strncpyz(fs_savegamedir, fs_gamedir, sizeof(fs_savegamedir));
Q_strncpyz(fs_downloaddir, fs_gamedir, sizeof(fs_downloaddir));
#endif // USE_SAVEGAMEDIR
}
}

View file

@ -790,6 +790,9 @@ FILESYSTEM
==============================================================
*/
#define FS_Gamedir FS_GameDir
#define FS_Savegamedir FS_SaveGameDir
#define FS_Downloaddir FS_DownloadDir
typedef int fileHandle_t;
@ -811,6 +814,7 @@ typedef enum {
FS_SEARCH_FULL_PATH
} fsSearchType_t;
extern int file_from_protected_pak; // from Yamagi Q2
extern int file_from_pak;
extern int file_from_pk3;
extern char last_pk3_name[MAX_QPATH];
@ -834,14 +838,20 @@ int FS_FTell (fileHandle_t f);
int FS_Tell (fileHandle_t f);
qboolean FS_FileExists (char *path);
qboolean FS_LocalFileExists (char *path);
qboolean FS_SaveFileExists (char *path);
qboolean FS_DownloadFileExists (char *path);
void FS_CopyFile (char *src, char *dst);
void FS_RenameFile (const char *oldPath, const char *newPath);
void FS_DeleteFile (const char *path);
char *FS_GameDir (void);
char *FS_SaveGameDir (void);
char *FS_DownloadDir (void);
char *FS_HomePath (void);
void FS_CreatePath (char *path);
void FS_DeletePath (char *path);
char *FS_NextPath (char *prevPath);
char *FS_NextGamePath (char *prevPath);
char **FS_ListFiles (char *findname, int *numfiles, unsigned musthave, unsigned canthave);
void FS_FreeFileList (char **list, int n);
qboolean FS_ItemInList (char *check, int num, char **list);
@ -851,8 +861,8 @@ void FS_Dir_f (void);
void FS_ExecAutoexec (void);
int FS_LoadFile (char *path, void **buffer);
void FS_AddPAKFile (const char *packPath); // add pak file function
void FS_AddPK3File (const char *packPath); // add pk3 file function
void FS_AddPAKFile (const char *packPath, qboolean isProtected); // add pak file function
void FS_AddPK3File (const char *packPath, qboolean isProtected); // add pk3 file function
char **FS_ListPak (char *find, int *num); // pak list function
char **FS_GetFileList (const char *path, const char *extension, int *num);
void FS_SetGamedir (char *dir);

View file

@ -192,7 +192,7 @@ void SV_SpawnServer (char *server, char *spawnpoint, server_state_t serverstate,
{
int i;
unsigned checksum;
fileHandle_t f;
// fileHandle_t f;
if (attractloop)
Cvar_Set ("paused", "0");
@ -260,10 +260,14 @@ void SV_SpawnServer (char *server, char *spawnpoint, server_state_t serverstate,
"maps/%s.bsp", server);
// resolve CS_PAKFILE, hack by Jay Dolan
FS_FOpenFile(sv.configstrings[CS_MODELS + 1], &f, FS_READ);
// strncpy(sv.configstrings[CS_PAKFILE], (last_pk3_name ? last_pk3_name : ""));
Q_strncpyz(sv.configstrings[CS_PAKFILE], (last_pk3_name ? last_pk3_name : ""), sizeof(sv.configstrings[CS_PAKFILE]));
FS_FCloseFile(f);
// FS_FOpenFile(sv.configstrings[CS_MODELS + 1], &f, FS_READ);
FS_FileExists (sv.configstrings[CS_MODELS + 1]);
if (!file_from_protected_pak) { // protected pak check from Yamagi Q2
// strncpy(sv.configstrings[CS_PAKFILE], (last_pk3_name ? last_pk3_name : ""));
Q_strncpyz(sv.configstrings[CS_PAKFILE], ((strlen(last_pk3_name) > 0) ? last_pk3_name : ""), sizeof(sv.configstrings[CS_PAKFILE]));
// Com_Printf ("SV_SpawnServer: CS_PAKFILE set to %s\n", last_pk3_name);
// FS_FCloseFile(f);
}
sv.models[1] = CM_LoadMap (sv.configstrings[CS_MODELS+1], false, &checksum);
}

View file

@ -488,7 +488,8 @@ void SV_BeginDownload_f(void)
sv_client->downloadcount = sv_client->downloadsize;
// ZOID- special check for maps, if it came from a pak file, don't allow download
if (!sv_client->download || (strncmp(name, "maps/", 5) == 0 && file_from_pak))
// if (!sv_client->download || (strncmp(name, "maps/", 5) == 0 && file_from_pak))
if (!sv_client->download || (strncmp(name, "maps/", 5) == 0 && file_from_protected_pak)) // protected pak check from Yamagi Q2
{
Com_DPrintf ("Couldn't download %s to %s\n", name, sv_client->name);
if (sv_client->download)

Binary file not shown.

BIN
win32/lib/libcurl_d.lib Normal file

Binary file not shown.

Binary file not shown.