Add file uri support, requires a '-allowfileurl' commandline argument.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6318 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
cdcb3c3950
commit
503162aefe
12 changed files with 250 additions and 67 deletions
|
@ -6174,12 +6174,15 @@ done:
|
||||||
qboolean Host_RunFile(const char *fname, int nlen, vfsfile_t *file)
|
qboolean Host_RunFile(const char *fname, int nlen, vfsfile_t *file)
|
||||||
{
|
{
|
||||||
hrf_t *f;
|
hrf_t *f;
|
||||||
#if defined(_WIN32) && !defined(FTE_SDL) && !defined(WINRT) && !defined(_XBOX)
|
#if defined(FTE_TARGET_WEB)
|
||||||
//win32 file urls are basically fucked, so defer to the windows api.
|
if (nlen >= 8 && !strncmp(fname, "file:///", 8))
|
||||||
|
{ //just here so we don't get confused by the arbitrary scheme check below.
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
//file urls need special handling, if only for percent-encoding.
|
||||||
char utf8[MAX_OSPATH*3];
|
char utf8[MAX_OSPATH*3];
|
||||||
if (nlen >= 7 && !strncmp(fname, "file://", 7))
|
if (nlen >= 5 && !strncmp(fname, "file:", 5))
|
||||||
{
|
{
|
||||||
qboolean Sys_ResolveFileURL(const char *inurl, int inlen, char *out, int outlen);
|
|
||||||
if (!Sys_ResolveFileURL(fname, nlen, utf8, sizeof(utf8)))
|
if (!Sys_ResolveFileURL(fname, nlen, utf8, sizeof(utf8)))
|
||||||
{
|
{
|
||||||
Con_Printf("Cannot resolve file url\n");
|
Con_Printf("Cannot resolve file url\n");
|
||||||
|
@ -6188,17 +6191,6 @@ qboolean Host_RunFile(const char *fname, int nlen, vfsfile_t *file)
|
||||||
fname = utf8;
|
fname = utf8;
|
||||||
nlen = strlen(fname);
|
nlen = strlen(fname);
|
||||||
}
|
}
|
||||||
#elif defined(FTE_TARGET_WEB)
|
|
||||||
if (nlen >= 8 && !strncmp(fname, "file:///", 8))
|
|
||||||
{ //just here so we don't get confused by the arbitrary scheme check below.
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
//unix file urls are fairly consistant - must be an absolute path.
|
|
||||||
if (nlen >= 8 && !strncmp(fname, "file:///", 8))
|
|
||||||
{
|
|
||||||
fname += 7;
|
|
||||||
nlen -= 7;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
else if((nlen >= 7 && !strncmp(fname, "http://", 7)) ||
|
else if((nlen >= 7 && !strncmp(fname, "http://", 7)) ||
|
||||||
(nlen >= 8 && !strncmp(fname, "https://", 8)))
|
(nlen >= 8 && !strncmp(fname, "https://", 8)))
|
||||||
|
|
|
@ -1313,7 +1313,7 @@ void VARGS Con_ThrottlePrintf (float *timer, int developerlevel, const char *fmt
|
||||||
|
|
||||||
if (*timer > now)
|
if (*timer > now)
|
||||||
; //in the future? zomg
|
; //in the future? zomg
|
||||||
else if (*timer > now-1)
|
else if (*timer >= now-1)
|
||||||
return; //within the last second
|
return; //within the last second
|
||||||
*timer = now; //in the future? zomg
|
*timer = now; //in the future? zomg
|
||||||
|
|
||||||
|
|
|
@ -13706,6 +13706,7 @@ qboolean Image_LocateHighResTexture(image_t *tex, flocation_t *bestloc, char *be
|
||||||
char *altname;
|
char *altname;
|
||||||
char *nextalt;
|
char *nextalt;
|
||||||
qboolean exactext = !!(tex->flags & IF_EXACTEXTENSION);
|
qboolean exactext = !!(tex->flags & IF_EXACTEXTENSION);
|
||||||
|
qboolean exactpath = false;
|
||||||
|
|
||||||
int locflags = FSLF_DEPTH_INEXPLICIT|FSLF_DEEPONFAILURE;
|
int locflags = FSLF_DEPTH_INEXPLICIT|FSLF_DEEPONFAILURE;
|
||||||
int bestdepth = 0x7fffffff, depth;
|
int bestdepth = 0x7fffffff, depth;
|
||||||
|
@ -13716,7 +13717,13 @@ qboolean Image_LocateHighResTexture(image_t *tex, flocation_t *bestloc, char *be
|
||||||
if (strncmp(tex->ident, "http:", 5) && strncmp(tex->ident, "https:", 6))
|
if (strncmp(tex->ident, "http:", 5) && strncmp(tex->ident, "https:", 6))
|
||||||
for(altname = tex->ident;altname;altname = nextalt)
|
for(altname = tex->ident;altname;altname = nextalt)
|
||||||
{
|
{
|
||||||
nextalt = strchr(altname, ':');
|
if (!strncmp(altname, "file:", 5))
|
||||||
|
{
|
||||||
|
nextalt = strchr(altname+5, ':');
|
||||||
|
exactpath = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
nextalt = strchr(altname, ':');
|
||||||
if (nextalt)
|
if (nextalt)
|
||||||
{
|
{
|
||||||
nextalt++;
|
nextalt++;
|
||||||
|
@ -13754,18 +13761,21 @@ qboolean Image_LocateHighResTexture(image_t *tex, flocation_t *bestloc, char *be
|
||||||
if (!tex->fallbackdata || (gl_load24bit.ival && !(tex->flags & IF_NOREPLACE)))
|
if (!tex->fallbackdata || (gl_load24bit.ival && !(tex->flags & IF_NOREPLACE)))
|
||||||
{
|
{
|
||||||
#ifdef IMAGEFMT_DDS
|
#ifdef IMAGEFMT_DDS
|
||||||
Q_snprintfz(fname, sizeof(fname), "dds/%s.dds", nicename);
|
if (!exactpath)
|
||||||
depth = FS_FLocateFile(fname, locflags, &loc);
|
|
||||||
if (depth < bestdepth)
|
|
||||||
{
|
{
|
||||||
Q_strncpyz(bestname, fname, bestnamesize);
|
Q_snprintfz(fname, sizeof(fname), "dds/%s.dds", nicename);
|
||||||
bestdepth = depth;
|
depth = FS_FLocateFile(fname, locflags, &loc);
|
||||||
*bestloc = loc;
|
if (depth < bestdepth)
|
||||||
*bestflags = 0;
|
{
|
||||||
|
Q_strncpyz(bestname, fname, bestnamesize);
|
||||||
|
bestdepth = depth;
|
||||||
|
*bestloc = loc;
|
||||||
|
*bestflags = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (strchr(nicename, '/') || strchr(nicename, '\\')) //never look in a root dir for the pic
|
if (exactpath || strchr(nicename, '/') || strchr(nicename, '\\')) //never look in a root dir for the pic
|
||||||
i = 0;
|
i = 0;
|
||||||
else
|
else
|
||||||
i = 1;
|
i = 1;
|
||||||
|
@ -13774,6 +13784,8 @@ qboolean Image_LocateHighResTexture(image_t *tex, flocation_t *bestloc, char *be
|
||||||
{
|
{
|
||||||
if (!tex_path[i].enabled)
|
if (!tex_path[i].enabled)
|
||||||
continue;
|
continue;
|
||||||
|
if (exactpath && i)
|
||||||
|
break;
|
||||||
if (tex_path[i].args >= 3)
|
if (tex_path[i].args >= 3)
|
||||||
{ //this is a path that needs subpaths
|
{ //this is a path that needs subpaths
|
||||||
char subpath[MAX_QPATH];
|
char subpath[MAX_QPATH];
|
||||||
|
|
|
@ -62,6 +62,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#define FTEENGINE
|
#define FTEENGINE
|
||||||
#include "../plugins/plugin.h"
|
#include "../plugins/plugin.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "fs.h"
|
||||||
|
|
||||||
#undef malloc
|
#undef malloc
|
||||||
|
|
||||||
|
@ -1077,7 +1078,7 @@ static void Friendly_Crash_Handler(int sig, siginfo_t *info, void *vcontext)
|
||||||
#endif
|
#endif
|
||||||
backtrace_symbols_fd(array+firstframe, size-firstframe, 2);
|
backtrace_symbols_fd(array+firstframe, size-firstframe, 2);
|
||||||
|
|
||||||
if (sig == SIGINT)
|
if (sig == SIGINT || fs_readonly)
|
||||||
fd = -1; //don't write out crash logs on ctrl+c
|
fd = -1; //don't write out crash logs on ctrl+c
|
||||||
else
|
else
|
||||||
fd = open("crash.log", O_WRONLY|O_CREAT|O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
|
fd = open("crash.log", O_WRONLY|O_CREAT|O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||||
|
@ -1181,7 +1182,6 @@ char *Sys_ConsoleInput(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
//begin meta generation helper
|
//begin meta generation helper
|
||||||
#include "fs.h"
|
|
||||||
static int Crypto_GenerateSignature(qbyte *hashdata, size_t hashsize, qbyte *signdata, size_t signsizemax)
|
static int Crypto_GenerateSignature(qbyte *hashdata, size_t hashsize, qbyte *signdata, size_t signsizemax)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
|
@ -1474,6 +1474,12 @@ qboolean Sys_ResolveFileURL(const char *inurl, int inlen, char *out, int outlen)
|
||||||
if (FAILED(pPathCreateFromUrlW(wurl, local, &grr, 0)))
|
if (FAILED(pPathCreateFromUrlW(wurl, local, &grr, 0)))
|
||||||
return false;
|
return false;
|
||||||
narrowen(out, outlen, local);
|
narrowen(out, outlen, local);
|
||||||
|
while(*out)
|
||||||
|
{
|
||||||
|
if (*out == '\\')
|
||||||
|
*out = '/';
|
||||||
|
out++;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1046,7 +1046,8 @@ void Con_TextEditor_f(void)
|
||||||
{
|
{
|
||||||
char *fname = Cmd_Argv(1);
|
char *fname = Cmd_Argv(1);
|
||||||
char *line = strrchr(fname, ':');
|
char *line = strrchr(fname, ':');
|
||||||
if (line)
|
char *lineend = NULL;
|
||||||
|
if (line && strtol(line+1, &lineend, 0) && !lineend)
|
||||||
*line++ = 0;
|
*line++ = 0;
|
||||||
if (!*fname)
|
if (!*fname)
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,6 +19,7 @@ hashtable_t filesystemhash;
|
||||||
static qboolean com_fschanged = true, com_fsneedreload;
|
static qboolean com_fschanged = true, com_fsneedreload;
|
||||||
qboolean com_installer = false;
|
qboolean com_installer = false;
|
||||||
qboolean fs_readonly;
|
qboolean fs_readonly;
|
||||||
|
static searchpath_t *fs_allowfileuri;
|
||||||
int waitingformanifest;
|
int waitingformanifest;
|
||||||
static unsigned int fs_restarts;
|
static unsigned int fs_restarts;
|
||||||
void *fs_thread_mutex;
|
void *fs_thread_mutex;
|
||||||
|
@ -170,6 +171,85 @@ void VARGS VFS_PRINTF(vfsfile_t *vf, const char *format, ...)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(_WIN32) && !defined(FTE_SDL) && !defined(WINRT) && !defined(_XBOX)
|
||||||
|
//windows has a special helper function to handle legacy URIs.
|
||||||
|
#else
|
||||||
|
qboolean Sys_ResolveFileURL(const char *inurl, int inlen, char *out, int outlen)
|
||||||
|
{
|
||||||
|
const unsigned char *i = inurl, *inend = inurl+inlen;
|
||||||
|
unsigned char *o = out, *outend = out+outlen;
|
||||||
|
unsigned char hex;
|
||||||
|
|
||||||
|
//make sure its a file url...
|
||||||
|
if (inlen < 5 || strncmp(inurl, "file:", 5))
|
||||||
|
return false;
|
||||||
|
i += 5;
|
||||||
|
|
||||||
|
if (i+1 < inend && i[0] == '/' && i[1] == '/')
|
||||||
|
{ //has an authority field...
|
||||||
|
i+=2;
|
||||||
|
//except we don't support authorities other than ourself...
|
||||||
|
if (i < inend || *i != '/')
|
||||||
|
return false; //must be an absolute path...
|
||||||
|
#ifdef _WIN32
|
||||||
|
i++; //on windows, (full)absolute paths start with a drive name...
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (i < inend && i[0] == '/')
|
||||||
|
; // file:/foo (no authority)
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//everything else must be percent-encoded
|
||||||
|
while (i < inend)
|
||||||
|
{
|
||||||
|
if (!*i || o == outend)
|
||||||
|
return false; //don't allow nulls...
|
||||||
|
else if (*i == '/' && i+1<inend && i[1] == '/')
|
||||||
|
return false; //two slashes is invalid (can be parent directory on some systems, or just buggy or weird)
|
||||||
|
else if (*i == '\\')
|
||||||
|
return false; //don't allow backslashes. they're meant to be percent-encoded anyway.
|
||||||
|
else if (*i == '%' && i+2<inend)
|
||||||
|
{
|
||||||
|
hex = 0;
|
||||||
|
if (i[1] >= 'A' && i[1] <= 'F')
|
||||||
|
hex += i[1]-'A'+10;
|
||||||
|
else if (i[1] >= 'a' && i[1] <= 'f')
|
||||||
|
hex += i[1]-'a'+10;
|
||||||
|
else if (i[1] >= '0' && i[1] <= '9')
|
||||||
|
hex += i[1]-'0';
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*o++ = *i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
hex <<= 4;
|
||||||
|
if (i[2] >= 'A' && i[2] <= 'F')
|
||||||
|
hex += i[2]-'A'+10;
|
||||||
|
else if (i[2] >= 'a' && i[2] <= 'f')
|
||||||
|
hex += i[2]-'a'+10;
|
||||||
|
else if (i[2] >= '0' && i[2] <= '9')
|
||||||
|
hex += i[2]-'0';
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*o++ = *i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*o++ = hex;
|
||||||
|
i += 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*o++ = *i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (o == outend)
|
||||||
|
return false;
|
||||||
|
*o = 0;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1104,7 +1184,7 @@ static int QDECL COM_Dir_List(const char *name, qofs_t size, time_t mtime, void
|
||||||
colour = "^1"; //superseeded
|
colour = "^1"; //superseeded
|
||||||
Q_snprintfz(link, sizeof(link), "\\tip\\flocate error");
|
Q_snprintfz(link, sizeof(link), "\\tip\\flocate error");
|
||||||
}
|
}
|
||||||
else if (loc.search->handle == spath)
|
else if (loc.search->handle == spath || (fs_allowfileuri&&loc.search == fs_allowfileuri))
|
||||||
{
|
{
|
||||||
colour = "^2";
|
colour = "^2";
|
||||||
|
|
||||||
|
@ -1657,6 +1737,19 @@ int FS_FLocateFile(const char *filename, unsigned int lflags, flocation_t *loc)
|
||||||
loc->search = NULL;
|
loc->search = NULL;
|
||||||
loc->len = -1;
|
loc->len = -1;
|
||||||
|
|
||||||
|
if (!strncmp(filename, "file:", 5))
|
||||||
|
{
|
||||||
|
if (fs_allowfileuri && Sys_ResolveFileURL(filename, strlen(filename), cleanpath, sizeof(cleanpath)))
|
||||||
|
{
|
||||||
|
fs_finds++;
|
||||||
|
found = fs_allowfileuri->handle->FindFile(fs_allowfileuri->handle, loc, cleanpath, NULL);
|
||||||
|
if (found)
|
||||||
|
loc->search = fs_allowfileuri;
|
||||||
|
}
|
||||||
|
pf = NULL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
filename = FS_GetCleanPath(filename, (lflags&FSLF_QUIET), cleanpath, sizeof(cleanpath));
|
filename = FS_GetCleanPath(filename, (lflags&FSLF_QUIET), cleanpath, sizeof(cleanpath));
|
||||||
if (!filename)
|
if (!filename)
|
||||||
{
|
{
|
||||||
|
@ -1864,7 +1957,7 @@ qboolean FS_GetLocationForPackageHandle(flocation_t *loc, searchpathfuncs_t *spa
|
||||||
if (search->handle == spath)
|
if (search->handle == spath)
|
||||||
{
|
{
|
||||||
loc->search = search;
|
loc->search = search;
|
||||||
return spath->FindFile(spath, loc, fname, NULL);
|
return spath->FindFile(spath, loc, fname, NULL) == FF_FOUND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -2033,27 +2126,28 @@ static const char *FS_GetCleanPath(const char *pattern, qboolean silent, char *o
|
||||||
char *o;
|
char *o;
|
||||||
char *seg;
|
char *seg;
|
||||||
char *end = outbuf + outlen;
|
char *end = outbuf + outlen;
|
||||||
|
static float throttletimer;
|
||||||
|
|
||||||
s = pattern;
|
s = pattern;
|
||||||
seg = o = outbuf;
|
seg = o = outbuf;
|
||||||
if (!pattern || !*pattern)
|
if (!pattern || !*pattern)
|
||||||
{
|
{
|
||||||
Con_Printf("Error: Empty filename\n");
|
Con_ThrottlePrintf(&throttletimer, 0, "Error: Empty filename\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
if (o == end)
|
if (o == end)
|
||||||
{
|
{
|
||||||
Con_Printf("Error: filename too long\n");
|
Con_ThrottlePrintf(&throttletimer, 0, "Error: filename too long\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (*s == ':')
|
if (*s == ':')
|
||||||
{
|
{
|
||||||
if (s == pattern+1 && (s[1] == '/' || s[1] == '\\'))
|
if (s == pattern+1 && (s[1] == '/' || s[1] == '\\'))
|
||||||
Con_Printf("Error: absolute path in filename %s\n", pattern);
|
Con_ThrottlePrintf(&throttletimer, 0, "Error: absolute path in filename %s\n", pattern);
|
||||||
else
|
else
|
||||||
Con_Printf("Error: alternative data stream in filename %s\n", pattern);
|
Con_ThrottlePrintf(&throttletimer, 0, "Error: alternative data stream in filename %s\n", pattern);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else if (*s == '\\' || *s == '/' || !*s)
|
else if (*s == '\\' || *s == '/' || !*s)
|
||||||
|
@ -2062,7 +2156,7 @@ static const char *FS_GetCleanPath(const char *pattern, qboolean silent, char *o
|
||||||
{
|
{
|
||||||
if (o == outbuf)
|
if (o == outbuf)
|
||||||
{
|
{
|
||||||
Con_Printf("Error: absolute path in filename %s\n", pattern);
|
Con_ThrottlePrintf(&throttletimer, 0, "Error: absolute path in filename %s\n", pattern);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!*s)
|
if (!*s)
|
||||||
|
@ -2070,7 +2164,7 @@ static const char *FS_GetCleanPath(const char *pattern, qboolean silent, char *o
|
||||||
*o++ = '\0';
|
*o++ = '\0';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Con_Printf("Error: empty directory name (%s)\n", pattern);
|
Con_ThrottlePrintf(&throttletimer, 0, "Error: empty directory name (%s)\n", pattern);
|
||||||
s++;
|
s++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -2080,17 +2174,17 @@ static const char *FS_GetCleanPath(const char *pattern, qboolean silent, char *o
|
||||||
seg++;
|
seg++;
|
||||||
if (!seg[0])
|
if (!seg[0])
|
||||||
{
|
{
|
||||||
Con_Printf("Error: No filename (%s)\n", pattern);
|
Con_ThrottlePrintf(&throttletimer, 0, "Error: No filename (%s)\n", pattern);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (seg[0] == '.')
|
if (seg[0] == '.')
|
||||||
{
|
{
|
||||||
if (o == seg+1)
|
if (o == seg+1)
|
||||||
Con_Printf("Error: source directory (%s)\n", pattern);
|
Con_ThrottlePrintf(&throttletimer, 0, "Error: source directory (%s)\n", pattern);
|
||||||
else if (seg[1] == '.')
|
else if (seg[1] == '.')
|
||||||
Con_Printf("Error: parent directory (%s)\n", pattern);
|
Con_ThrottlePrintf(&throttletimer, 0, "Error: parent directory (%s)\n", pattern);
|
||||||
else
|
else
|
||||||
Con_Printf("Error: hidden name (%s)\n", pattern);
|
Con_ThrottlePrintf(&throttletimer, 0, "Error: hidden name (%s)\n", pattern);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||||
|
@ -2108,7 +2202,7 @@ static const char *FS_GetCleanPath(const char *pattern, qboolean silent, char *o
|
||||||
{
|
{
|
||||||
if (o == seg+4 || seg[4] == ' '|| seg[4] == '\t' || seg[4] == '.')
|
if (o == seg+4 || seg[4] == ' '|| seg[4] == '\t' || seg[4] == '.')
|
||||||
{
|
{
|
||||||
Con_Printf("Error: reserved name in path (%c%c%c%c in %s)\n", seg[0], seg[1], seg[2], seg[3], pattern);
|
Con_ThrottlePrintf(&throttletimer, 0, "Error: reserved name in path (%c%c%c%c in %s)\n", seg[0], seg[1], seg[2], seg[3], pattern);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2125,7 +2219,7 @@ static const char *FS_GetCleanPath(const char *pattern, qboolean silent, char *o
|
||||||
{
|
{
|
||||||
if (o == seg+3 || seg[3] == ' '|| seg[3] == '\t' || seg[3] == '.')
|
if (o == seg+3 || seg[3] == ' '|| seg[3] == '\t' || seg[3] == '.')
|
||||||
{
|
{
|
||||||
Con_Printf("Error: reserved name in path (%c%c%c in %s)\n", seg[0], seg[1], seg[2], pattern);
|
Con_ThrottlePrintf(&throttletimer, 0, "Error: reserved name in path (%c%c%c in %s)\n", seg[0], seg[1], seg[2], pattern);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2401,6 +2495,16 @@ vfsfile_t *QDECL FS_OpenVFS(const char *filename, const char *mode, enum fs_rela
|
||||||
if (fs_readonly && *mode == 'w')
|
if (fs_readonly && *mode == 'w')
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (!strncmp(filename, "file:", 5))
|
||||||
|
{
|
||||||
|
if (fs_allowfileuri || relativeto == FS_SYSTEM)
|
||||||
|
{
|
||||||
|
if (Sys_ResolveFileURL(filename, strlen(filename), fullname, sizeof(fullname)))
|
||||||
|
return VFSOS_Open(fullname, mode);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (relativeto == FS_SYSTEM)
|
if (relativeto == FS_SYSTEM)
|
||||||
return VFSOS_Open(filename, mode);
|
return VFSOS_Open(filename, mode);
|
||||||
|
|
||||||
|
@ -2869,6 +2973,11 @@ static qboolean FS_EnumerateFilesEach(searchpathfuncs_t *handle, char *matches,
|
||||||
char *sep;
|
char *sep;
|
||||||
for (; matches; matches = sep)
|
for (; matches; matches = sep)
|
||||||
{
|
{
|
||||||
|
if (!strncmp(matches, "file:", 5))
|
||||||
|
{
|
||||||
|
sep = strchr(matches+5, ':');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
sep = strchr(matches, ':');
|
sep = strchr(matches, ':');
|
||||||
if (sep)
|
if (sep)
|
||||||
{
|
{
|
||||||
|
@ -2892,6 +3001,11 @@ static int FS_EnumerateFilesEachSys (const char *syspath, char *matches, int (*f
|
||||||
char *sep;
|
char *sep;
|
||||||
for (; matches; matches = sep)
|
for (; matches; matches = sep)
|
||||||
{
|
{
|
||||||
|
if (!strncmp(matches, "file:", 5))
|
||||||
|
{
|
||||||
|
sep = strchr(matches+5, ':');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
sep = strchr(matches, ':');
|
sep = strchr(matches, ':');
|
||||||
if (sep)
|
if (sep)
|
||||||
{
|
{
|
||||||
|
@ -2989,9 +3103,42 @@ searchpathfuncs_t *COM_EnumerateFilesPackage (char *matches, const char *package
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct fs_enumerate_fileuri_s
|
||||||
|
{
|
||||||
|
int (QDECL *func)(const char *, qofs_t, time_t mtime, void *, searchpathfuncs_t*);
|
||||||
|
void *parm;
|
||||||
|
};
|
||||||
|
static int QDECL COM_EnumerateFiles_FileURI (const char *name, qofs_t flags, time_t mtime, void *parm, searchpathfuncs_t *spath)
|
||||||
|
{
|
||||||
|
char syspath[MAX_OSPATH];
|
||||||
|
struct fs_enumerate_fileuri_s *e = parm;
|
||||||
|
size_t nlen = strlen(name)+1;
|
||||||
|
if (7+nlen > sizeof(syspath))
|
||||||
|
return true;
|
||||||
|
memcpy(syspath, "file://", 7);
|
||||||
|
memcpy(syspath+7, name, nlen);
|
||||||
|
return e->func(syspath, flags, mtime, e->parm, spath);
|
||||||
|
}
|
||||||
|
|
||||||
void COM_EnumerateFiles (const char *match, int (QDECL *func)(const char *, qofs_t, time_t mtime, void *, searchpathfuncs_t*), void *parm)
|
void COM_EnumerateFiles (const char *match, int (QDECL *func)(const char *, qofs_t, time_t mtime, void *, searchpathfuncs_t*), void *parm)
|
||||||
{
|
{
|
||||||
searchpath_t *search;
|
searchpath_t *search;
|
||||||
|
|
||||||
|
if (!strncmp(match, "file:", 5))
|
||||||
|
{
|
||||||
|
if (fs_allowfileuri)
|
||||||
|
{
|
||||||
|
char syspath[MAX_OSPATH];
|
||||||
|
struct fs_enumerate_fileuri_s e;
|
||||||
|
e.func = func;
|
||||||
|
e.parm = parm;
|
||||||
|
if (Sys_ResolveFileURL(match, strlen(match), syspath, sizeof(syspath)))
|
||||||
|
Sys_EnumerateFiles(NULL, syspath, COM_EnumerateFiles_FileURI, &e, NULL);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (search = com_searchpaths; search ; search = search->next)
|
for (search = com_searchpaths; search ; search = search->next)
|
||||||
{
|
{
|
||||||
// is the element a pak file?
|
// is the element a pak file?
|
||||||
|
@ -7502,6 +7649,11 @@ void COM_InitFilesystem (void)
|
||||||
COM_InitHomedir(NULL);
|
COM_InitHomedir(NULL);
|
||||||
|
|
||||||
fs_readonly = COM_CheckParm("-readonly");
|
fs_readonly = COM_CheckParm("-readonly");
|
||||||
|
if (COM_CheckParm("-allowfileuri") || COM_CheckParm("-allowfileurl"))
|
||||||
|
{
|
||||||
|
fs_allowfileuri = (searchpath_t*)Z_Malloc (sizeof(searchpath_t));
|
||||||
|
fs_allowfileuri->handle = VFSOS_OpenPath(NULL, NULL, "", "", "");
|
||||||
|
}
|
||||||
|
|
||||||
fs_thread_mutex = Sys_CreateMutex();
|
fs_thread_mutex = Sys_CreateMutex();
|
||||||
}
|
}
|
||||||
|
@ -7520,7 +7672,10 @@ extern searchpathfuncs_t *(QDECL FSPAK_LoadArchive) (vfsfile_t *packhandle, sear
|
||||||
extern searchpathfuncs_t *(QDECL FSDWD_LoadArchive) (vfsfile_t *packhandle, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix);
|
extern searchpathfuncs_t *(QDECL FSDWD_LoadArchive) (vfsfile_t *packhandle, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix);
|
||||||
#endif*/
|
#endif*/
|
||||||
void FS_RegisterDefaultFileSystems(void)
|
void FS_RegisterDefaultFileSystems(void)
|
||||||
{
|
{ //packages listed last will be scanned for last (and thus be favoured when searching for game files)
|
||||||
|
#ifdef PACKAGE_DOOMWAD
|
||||||
|
FS_RegisterFileSystemType(NULL, "wad", FSDWD_LoadArchive, true);
|
||||||
|
#endif
|
||||||
#ifdef PACKAGE_DZIP
|
#ifdef PACKAGE_DZIP
|
||||||
FS_RegisterFileSystemType(NULL, "dz", FSDZ_LoadArchive, false);
|
FS_RegisterFileSystemType(NULL, "dz", FSDZ_LoadArchive, false);
|
||||||
#endif
|
#endif
|
||||||
|
@ -7531,7 +7686,6 @@ void FS_RegisterDefaultFileSystems(void)
|
||||||
FS_RegisterFileSystemType(NULL, "PAK", FSPAK_LoadArchive, true);
|
FS_RegisterFileSystemType(NULL, "PAK", FSPAK_LoadArchive, true);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
FS_RegisterFileSystemType(NULL, "pk3dir", VFSOS_OpenPath, true); //used for git repos or whatever, to make packaging easier
|
|
||||||
#ifdef PACKAGE_PK3
|
#ifdef PACKAGE_PK3
|
||||||
FS_RegisterFileSystemType(NULL, "pk3", FSZIP_LoadArchive, true); //quake3's extension for zips
|
FS_RegisterFileSystemType(NULL, "pk3", FSZIP_LoadArchive, true); //quake3's extension for zips
|
||||||
FS_RegisterFileSystemType(NULL, "pk4", FSZIP_LoadArchive, true); //quake4's extension for zips...
|
FS_RegisterFileSystemType(NULL, "pk4", FSZIP_LoadArchive, true); //quake4's extension for zips...
|
||||||
|
@ -7545,7 +7699,5 @@ void FS_RegisterDefaultFileSystems(void)
|
||||||
FS_RegisterFileSystemType(NULL, "dll", FSZIP_LoadArchive, false); //for plugin metas / self-extracting zips.
|
FS_RegisterFileSystemType(NULL, "dll", FSZIP_LoadArchive, false); //for plugin metas / self-extracting zips.
|
||||||
FS_RegisterFileSystemType(NULL, "so", FSZIP_LoadArchive, false); //for plugin metas / self-extracting zips.
|
FS_RegisterFileSystemType(NULL, "so", FSZIP_LoadArchive, false); //for plugin metas / self-extracting zips.
|
||||||
#endif
|
#endif
|
||||||
#ifdef PACKAGE_DOOMWAD
|
FS_RegisterFileSystemType(NULL, "pk3dir", VFSOS_OpenPath, true); //used for git repos or whatever, to make packaging easier
|
||||||
FS_RegisterFileSystemType(NULL, "wad", FSDWD_LoadArchive, true);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -601,7 +601,7 @@ static qboolean QDECL VFSW32_CreateLoc(searchpathfuncs_t *handle, flocation_t *l
|
||||||
loc->offset = 0;
|
loc->offset = 0;
|
||||||
loc->fhandle = handle;
|
loc->fhandle = handle;
|
||||||
loc->rawname[sizeof(loc->rawname)-1] = 0;
|
loc->rawname[sizeof(loc->rawname)-1] = 0;
|
||||||
if (Q_snprintfz (loc->rawname, sizeof(loc->rawname), "%s/%s", wp->rootpath, filename))
|
if (Q_snprintfz (loc->rawname, sizeof(loc->rawname), "%s%s", wp->rootpath, filename))
|
||||||
return FF_NOTFOUND;
|
return FF_NOTFOUND;
|
||||||
for (ofs = loc->rawname+1 ; *ofs ; ofs++)
|
for (ofs = loc->rawname+1 ; *ofs ; ofs++)
|
||||||
{
|
{
|
||||||
|
@ -639,7 +639,7 @@ static unsigned int QDECL VFSW32_FLocate(searchpathfuncs_t *handle, flocation_t
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// check a file in the directory tree
|
// check a file in the directory tree
|
||||||
if (Q_snprintfz (netpath, sizeof(netpath), "%s/%s", wp->rootpath, filename))
|
if (Q_snprintfz (netpath, sizeof(netpath), "%s%s", wp->rootpath, filename))
|
||||||
return FF_NOTFOUND;
|
return FF_NOTFOUND;
|
||||||
|
|
||||||
if (!WinNT)
|
if (!WinNT)
|
||||||
|
@ -716,8 +716,8 @@ static qboolean QDECL VFSW32_RenameFile(searchpathfuncs_t *handle, const char *o
|
||||||
char newsyspath[MAX_OSPATH];
|
char newsyspath[MAX_OSPATH];
|
||||||
if (fs_readonly)
|
if (fs_readonly)
|
||||||
return false;
|
return false;
|
||||||
snprintf (oldsyspath, sizeof(oldsyspath)-1, "%s/%s", wp->rootpath, oldfname);
|
snprintf (oldsyspath, sizeof(oldsyspath)-1, "%s%s", wp->rootpath, oldfname);
|
||||||
snprintf (newsyspath, sizeof(newsyspath)-1, "%s/%s", wp->rootpath, newfname);
|
snprintf (newsyspath, sizeof(newsyspath)-1, "%s%s", wp->rootpath, newfname);
|
||||||
return Sys_Rename(oldsyspath, newsyspath);
|
return Sys_Rename(oldsyspath, newsyspath);
|
||||||
}
|
}
|
||||||
static qboolean QDECL VFSW32_RemoveFile(searchpathfuncs_t *handle, const char *filename)
|
static qboolean QDECL VFSW32_RemoveFile(searchpathfuncs_t *handle, const char *filename)
|
||||||
|
@ -726,7 +726,7 @@ static qboolean QDECL VFSW32_RemoveFile(searchpathfuncs_t *handle, const char *f
|
||||||
char syspath[MAX_OSPATH];
|
char syspath[MAX_OSPATH];
|
||||||
if (fs_readonly)
|
if (fs_readonly)
|
||||||
return false;
|
return false;
|
||||||
snprintf (syspath, sizeof(syspath)-1, "%s/%s", wp->rootpath, filename);
|
snprintf (syspath, sizeof(syspath)-1, "%s%s", wp->rootpath, filename);
|
||||||
if (*filename && filename[strlen(filename)-1] == '/')
|
if (*filename && filename[strlen(filename)-1] == '/')
|
||||||
return Sys_rmdir(syspath);
|
return Sys_rmdir(syspath);
|
||||||
return Sys_remove(syspath);
|
return Sys_remove(syspath);
|
||||||
|
@ -745,6 +745,8 @@ searchpathfuncs_t *QDECL VFSW32_OpenPath(vfsfile_t *mustbenull, searchpathfuncs_
|
||||||
{
|
{
|
||||||
wchar_t wide[MAX_OSPATH];
|
wchar_t wide[MAX_OSPATH];
|
||||||
memcpy(np->rootpath, desc, dlen+1);
|
memcpy(np->rootpath, desc, dlen+1);
|
||||||
|
if (*np->rootpath)
|
||||||
|
Q_strncpy(np->rootpath+dlen, "/", 2);
|
||||||
if (!WinNT)
|
if (!WinNT)
|
||||||
np->changenotification = FindFirstChangeNotificationA(np->rootpath, true, FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_CREATION);
|
np->changenotification = FindFirstChangeNotificationA(np->rootpath, true, FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_CREATION);
|
||||||
else
|
else
|
||||||
|
|
|
@ -75,6 +75,8 @@ unsigned int Sys_Milliseconds (void);
|
||||||
double Sys_DoubleTime (void);
|
double Sys_DoubleTime (void);
|
||||||
qboolean Sys_RandomBytes(qbyte *string, int len);
|
qboolean Sys_RandomBytes(qbyte *string, int len);
|
||||||
|
|
||||||
|
qboolean Sys_ResolveFileURL(const char *inurl, int inlen, char *out, int outlen);
|
||||||
|
|
||||||
char *Sys_ConsoleInput (void);
|
char *Sys_ConsoleInput (void);
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
|
|
|
@ -2220,8 +2220,8 @@ void Q_InitProgs(enum initprogs_e flags)
|
||||||
oldprnum=prnum;
|
oldprnum=prnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
//progs depended on by maps.
|
/* //progs depended on by maps.
|
||||||
a = as = COM_LoadStackFile(va("maps/%s.inf", svs.name), addons, sizeof(addons), NULL);
|
a = as = COM_LoadStackFile(va("%s.inf", sv.modelname), addons, sizeof(addons), NULL);
|
||||||
if (a)
|
if (a)
|
||||||
{
|
{
|
||||||
if (progstype == PROG_QW)
|
if (progstype == PROG_QW)
|
||||||
|
@ -2284,7 +2284,7 @@ void Q_InitProgs(enum initprogs_e flags)
|
||||||
a++;
|
a++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
//add any addons specified
|
//add any addons specified
|
||||||
for (i2 = 0; i2 < MAXADDONS; i2++)
|
for (i2 = 0; i2 < MAXADDONS; i2++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -698,7 +698,7 @@ void SV_Map_f (void)
|
||||||
{
|
{
|
||||||
char *mangled = Cmd_Argv(1);
|
char *mangled = Cmd_Argv(1);
|
||||||
char *sep = strchr(mangled, ':');
|
char *sep = strchr(mangled, ':');
|
||||||
if (sep)
|
if (sep && strncmp(mangled, "file:", 5) && strncmp(mangled, "http:", 5) && strncmp(mangled, "https:", 5))
|
||||||
{
|
{
|
||||||
*sep++ = 0;
|
*sep++ = 0;
|
||||||
if (Cmd_FromGamecode())
|
if (Cmd_FromGamecode())
|
||||||
|
@ -737,7 +737,7 @@ void SV_Map_f (void)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
snprintf (expanded, sizeof(expanded), "maps/%s.bsp", level); // this function and the if statement below, is a quake bugfix which stopped a map called "dm6++.bsp" from loading because of the + sign, quake2 map syntax interprets + character as "intro.cin+base1.bsp", to play a cinematic then load a map after
|
snprintf (expanded, sizeof(expanded), "maps/%s.bsp", level); // this function and the if statement below, is a quake bugfix which stopped a map called "dm6++.bsp" from loading because of the + sign, quake2 map syntax interprets + character as "intro.cin+base1.bsp", to play a cinematic then load a map after
|
||||||
if (!COM_FCheckExists (expanded))
|
if (!COM_FCheckExists (level) && !COM_FCheckExists (expanded))
|
||||||
{
|
{
|
||||||
nextserver = strchr(level, '+');
|
nextserver = strchr(level, '+');
|
||||||
if (nextserver)
|
if (nextserver)
|
||||||
|
@ -841,7 +841,7 @@ void SV_Map_f (void)
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
char *exts[] = {"maps/%s", "maps/%s.bsp", "maps/%s.bsp.gz", "maps/%s.bsp.xz", "maps/%s.cm", "maps/%s.hmp", /*"maps/%s.map",*/ /*"maps/%s.ent",*/ NULL};
|
char *exts[] = {"%s", "maps/%s", "maps/%s.bsp", "maps/%s.bsp.gz", "maps/%s.bsp.xz", "maps/%s.cm", "maps/%s.hmp", /*"maps/%s.map",*/ /*"maps/%s.ent",*/ NULL};
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
for (i = 0; exts[i]; i++)
|
for (i = 0; exts[i]; i++)
|
||||||
|
|
|
@ -1016,22 +1016,38 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
|
||||||
{
|
{
|
||||||
//.map is commented out because quite frankly, they're a bit annoying when the engine loads the gpled start.map when really you wanted to just play the damn game intead of take it apart.
|
//.map is commented out because quite frankly, they're a bit annoying when the engine loads the gpled start.map when really you wanted to just play the damn game intead of take it apart.
|
||||||
//if you want to load a .map, just use 'map foo.map' instead.
|
//if you want to load a .map, just use 'map foo.map' instead.
|
||||||
char *exts[] = {"maps/%s", "maps/%s.bsp", "maps/%s.cm", "maps/%s.hmp", /*"maps/%s.map",*/ "maps/%s.bsp.gz", "maps/%s.bsp.xz", NULL};
|
char *exts[] = {"maps/%s", "maps/%s.bsp", "maps/%s.cm", "maps/%s.hmp", /*"maps/%s.map",*/ "maps/%s.bsp.gz", "maps/%s.bsp.xz", NULL}, *e;
|
||||||
int depth, bestdepth;
|
int depth, bestdepth;
|
||||||
flocation_t loc;
|
flocation_t loc;
|
||||||
time_t filetime;
|
time_t filetime;
|
||||||
Q_strncpyz (svs.name, server, sizeof(svs.name));
|
Q_snprintfz (sv.modelname, sizeof(sv.modelname), "%s", server);
|
||||||
Q_snprintfz (sv.modelname, sizeof(sv.modelname), exts[0], server);
|
|
||||||
bestdepth = COM_FDepthFile(sv.modelname, false);
|
bestdepth = COM_FDepthFile(sv.modelname, false);
|
||||||
for (i = 1; exts[i]; i++)
|
if (bestdepth == FDEPTH_MISSING)
|
||||||
{
|
{ //not an exact name, scan the maps subdir.
|
||||||
depth = COM_FDepthFile(va(exts[i], server), false);
|
for (i = 0; exts[i]; i++)
|
||||||
if (depth < bestdepth)
|
|
||||||
{
|
{
|
||||||
bestdepth = depth;
|
depth = COM_FDepthFile(va(exts[i], server), false);
|
||||||
Q_snprintfz (sv.modelname, sizeof(sv.modelname), exts[i], server);
|
if (depth < bestdepth)
|
||||||
|
{
|
||||||
|
bestdepth = depth;
|
||||||
|
Q_snprintfz (sv.modelname, sizeof(sv.modelname), exts[i], server);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strncmp(sv.modelname, "maps/", 5))
|
||||||
|
Q_strncpyz (svs.name, sv.modelname+5, sizeof(svs.name));
|
||||||
|
else
|
||||||
|
Q_strncpyz (svs.name, sv.modelname, sizeof(svs.name));
|
||||||
|
e = (char*)COM_GetFileExtension(svs.name, NULL);
|
||||||
|
if (!strcmp(e, ".gz") || !strcmp(e, ".xz"))
|
||||||
|
{
|
||||||
|
*e = 0;
|
||||||
|
e = (char*)COM_GetFileExtension(svs.name, NULL);
|
||||||
|
}
|
||||||
|
if (!strcmp(e, ".bsp"))
|
||||||
|
*e = 0;
|
||||||
|
|
||||||
sv.world.worldmodel = Mod_ForName (sv.modelname, MLV_ERROR);
|
sv.world.worldmodel = Mod_ForName (sv.modelname, MLV_ERROR);
|
||||||
|
|
||||||
if (FS_FLocateFile(sv.modelname,FSLF_IFFOUND, &loc) && FS_GetLocMTime(&loc, &filetime))
|
if (FS_FLocateFile(sv.modelname,FSLF_IFFOUND, &loc) && FS_GetLocMTime(&loc, &filetime))
|
||||||
|
|
Loading…
Reference in a new issue