mirror of
https://github.com/nzp-team/fteqw.git
synced 2025-01-22 08:21:29 +00:00
493d66b832
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5100 fc73d0e0-1445-4013-8a0c-d673dee63da5
720 lines
16 KiB
C
720 lines
16 KiB
C
#include "quakedef.h"
|
|
|
|
#ifdef WEBSERVER
|
|
|
|
#include "iweb.h"
|
|
#include "netinc.h"
|
|
|
|
#ifdef WEBSVONLY //we need some functions from quake
|
|
|
|
char *NET_SockadrToString(char *s, int slen, struct sockaddr_qstorage *addr)
|
|
{
|
|
switch(((struct sockaddr*)addr)->sa_family)
|
|
{
|
|
case AF_INET:
|
|
Q_snprintfz(s, slen, "%s:%u", inet_ntoa(((struct sockaddr_in*)addr)->sin_addr), ntohs(((struct sockaddr_in*)addr)->sin_port));
|
|
break;
|
|
case AF_INET6:
|
|
if (!memcmp(((struct sockaddr_in6*)addr)->sin6_addr.s6_bytes, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12))
|
|
{ //ipv4-mapped
|
|
Q_snprintfz(s, slen, "[::ffff:%u.%u.%u.%u]:%u",
|
|
((struct sockaddr_in6*)addr)->sin6_addr.s6_bytes[12],
|
|
((struct sockaddr_in6*)addr)->sin6_addr.s6_bytes[13],
|
|
((struct sockaddr_in6*)addr)->sin6_addr.s6_bytes[14],
|
|
((struct sockaddr_in6*)addr)->sin6_addr.s6_bytes[15],
|
|
|
|
ntohs(((struct sockaddr_in6*)addr)->sin6_port));
|
|
}
|
|
else
|
|
{
|
|
Q_snprintfz(s, slen, "[%x:%x:%x:%x:%x:%x:%x:%x]:%u",
|
|
ntohs(((struct sockaddr_in6*)addr)->sin6_addr.s6_words[0]),
|
|
ntohs(((struct sockaddr_in6*)addr)->sin6_addr.s6_words[1]),
|
|
ntohs(((struct sockaddr_in6*)addr)->sin6_addr.s6_words[2]),
|
|
ntohs(((struct sockaddr_in6*)addr)->sin6_addr.s6_words[3]),
|
|
|
|
ntohs(((struct sockaddr_in6*)addr)->sin6_addr.s6_words[4]),
|
|
ntohs(((struct sockaddr_in6*)addr)->sin6_addr.s6_words[5]),
|
|
ntohs(((struct sockaddr_in6*)addr)->sin6_addr.s6_words[6]),
|
|
ntohs(((struct sockaddr_in6*)addr)->sin6_addr.s6_words[7]),
|
|
|
|
ntohs(((struct sockaddr_in6*)addr)->sin6_port));
|
|
}
|
|
break;
|
|
default:
|
|
*s = 0;
|
|
break;
|
|
}
|
|
return s;
|
|
}
|
|
|
|
qboolean SV_AllowDownload (const char *name)
|
|
{
|
|
if (strstr(name, ".."))
|
|
return false;
|
|
if (strchr(name, ':'))
|
|
return false;
|
|
if (*name == '/' || *name == '\\')
|
|
return false;
|
|
return true;
|
|
}
|
|
char com_token[sizeof(com_token)];
|
|
com_tokentype_t com_tokentype;
|
|
int com_argc;
|
|
const char **com_argv;
|
|
|
|
vfsfile_t *IWebGenerateFile(const char *name, const char *content, int contentlength)
|
|
{
|
|
return NULL;
|
|
}
|
|
vfsfile_t *VFSSTDIO_Open(const char *osname, const char *mode, qboolean *needsflush);
|
|
vfsfile_t *FS_OpenVFS(const char *filename, const char *mode, enum fs_relative relativeto)
|
|
{
|
|
return VFSSTDIO_Open(filename, mode, NULL);
|
|
}
|
|
void Q_strncpyz(char *d, const char *s, int n)
|
|
{
|
|
int i;
|
|
n--;
|
|
if (n < 0)
|
|
return; //this could be an error
|
|
|
|
for (i=0; *s; i++)
|
|
{
|
|
if (i == n)
|
|
break;
|
|
*d++ = *s++;
|
|
}
|
|
*d='\0';
|
|
}
|
|
|
|
void VARGS Q_snprintfz (char *dest, size_t size, const char *fmt, ...)
|
|
{
|
|
va_list args;
|
|
va_start (args, fmt);
|
|
#ifdef _WIN32
|
|
#undef _vsnprintf
|
|
_vsnprintf (dest, size-1, fmt, args);
|
|
#else
|
|
vsnprintf (dest, size-1, fmt, args);
|
|
#endif
|
|
va_end (args);
|
|
//make sure its terminated.
|
|
dest[size-1] = 0;
|
|
}
|
|
|
|
/*char *va(char *format, ...)
|
|
{
|
|
#define VA_BUFFERS 2 //power of two
|
|
va_list argptr;
|
|
static char string[VA_BUFFERS][1024];
|
|
static int bufnum;
|
|
|
|
bufnum++;
|
|
bufnum &= (VA_BUFFERS-1);
|
|
|
|
va_start (argptr, format);
|
|
_vsnprintf (string[bufnum],sizeof(string[bufnum])-1, format,argptr);
|
|
va_end (argptr);
|
|
|
|
return string[bufnum];
|
|
}*/
|
|
|
|
#undef _vsnprintf
|
|
void Sys_Error(const char *format, ...)
|
|
{
|
|
va_list argptr;
|
|
char string[1024];
|
|
|
|
va_start (argptr, format);
|
|
#ifdef _WIN32
|
|
_vsnprintf (string,sizeof(string)-1, format,argptr);
|
|
string[sizeof(string)-1] = 0;
|
|
#else
|
|
vsnprintf (string,sizeof(string), format,argptr);
|
|
#endif
|
|
va_end (argptr);
|
|
|
|
printf("%s", string);
|
|
getchar();
|
|
exit(1000);
|
|
}
|
|
|
|
int COM_CheckParm(const char *parm)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
char *authedusername;
|
|
char *autheduserpassword;
|
|
int lport_min, lport_max;
|
|
int anonaccess = IWEBACC_READ;
|
|
iwboolean verbose;
|
|
int main(int argc, char **argv)
|
|
{
|
|
int httpport = 80;
|
|
int ftpport = 21;
|
|
int arg = 1;
|
|
#ifdef _WIN32
|
|
WSADATA pointlesscrap;
|
|
WSAStartup(2, &pointlesscrap);
|
|
#endif
|
|
|
|
while (arg < argc)
|
|
{
|
|
char *a = argv[arg];
|
|
if (!a)
|
|
continue;
|
|
if (*a != '-')
|
|
break; //other stuff
|
|
while (*a == '-')
|
|
a++;
|
|
arg++;
|
|
|
|
if (!strcmp(a, "help"))
|
|
{
|
|
printf("%s -http 80 -ftp 21 -user steve -pass swordfish -ports 5000 6000\n", argv[0]);
|
|
printf("runs a simple http server\n");
|
|
printf(" -http <num> specifies the port to listen on for http\n");
|
|
printf(" -ftp <num> specifies the port to listen on for ftp\n");
|
|
printf(" -ports <lowest> <highest> specifies a port range for incoming ftp connections, to work around firewall rules\n");
|
|
printf(" -user <name> specifies the username that has full access. if not supplied noone can write.\n");
|
|
printf(" -pass <pass> specifies the password to go with that username\n");
|
|
printf(" -noanon will refuse to serve files to anyone but the authed user\n");
|
|
return;
|
|
}
|
|
else if (!strcmp(a, "port") || !strcmp(a, "p"))
|
|
{
|
|
httpport = atoi(argv[arg++]);
|
|
ftpport = 0;
|
|
}
|
|
else if (!strcmp(a, "http") || !strcmp(a, "h"))
|
|
httpport = atoi(argv[arg++]);
|
|
else if (!strcmp(a, "ftp") || !strcmp(a, "f"))
|
|
ftpport = atoi(argv[arg++]);
|
|
else if (!strcmp(a, "noanon"))
|
|
anonaccess = 0;
|
|
else if (!strcmp(a, "ports"))
|
|
{
|
|
lport_min = atoi(argv[arg++]);
|
|
lport_max = atoi(argv[arg++]);
|
|
if (lport_max < lport_min)
|
|
lport_max = lport_min;
|
|
}
|
|
else if (!strcmp(a, "verbose") || !strcmp(a, "v"))
|
|
verbose = true;
|
|
else if (!strcmp(a, "user"))
|
|
authedusername = argv[arg++];
|
|
else if (!strcmp(a, "pass"))
|
|
autheduserpassword = argv[arg++];
|
|
else
|
|
printf("Unknown argument: %s\n", a);
|
|
}
|
|
|
|
if (arg < argc && atoi(argv[arg]))
|
|
{
|
|
httpport = atoi(argv[arg++]);
|
|
ftpport = 0;
|
|
}
|
|
if (arg < argc)
|
|
authedusername = argv[arg++];
|
|
if (arg < argc)
|
|
autheduserpassword = argv[arg++];
|
|
|
|
printf("http port %i\n", httpport);
|
|
printf("ftp port %i\n", ftpport);
|
|
if (authedusername || autheduserpassword)
|
|
printf("Username = \"%s\"\nPassword = \"%s\"\n", authedusername, autheduserpassword);
|
|
else
|
|
printf("Server is read only\n");
|
|
|
|
while(1)
|
|
{
|
|
if (ftpport)
|
|
FTP_ServerRun(1, ftpport);
|
|
if (httpport)
|
|
HTTP_ServerPoll(1, httpport);
|
|
#ifdef _WIN32
|
|
Sleep(1);
|
|
#else
|
|
usleep(10000);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
int IWebGetSafeListeningPort(void)
|
|
{
|
|
static int sequence;
|
|
return lport_min + (sequence++ % (lport_max+1-lport_min));
|
|
}
|
|
void VARGS IWebDPrintf(char *fmt, ...)
|
|
{
|
|
va_list args;
|
|
if (!verbose)
|
|
return;
|
|
va_start (args, fmt);
|
|
vprintf (fmt, args);
|
|
va_end (args);
|
|
}
|
|
|
|
|
|
#ifdef _WIN32
|
|
#ifdef _MSC_VER
|
|
#define ULL(x) x##ui64
|
|
#else
|
|
#define ULL(x) x##ull
|
|
#endif
|
|
|
|
static time_t Sys_FileTimeToTime(FILETIME ft)
|
|
{
|
|
ULARGE_INTEGER ull;
|
|
ull.LowPart = ft.dwLowDateTime;
|
|
ull.HighPart = ft.dwHighDateTime;
|
|
return ull.QuadPart / ULL(10000000) - ULL(11644473600);
|
|
}
|
|
void COM_EnumerateFiles (const char *match, int (*func)(const char *, qofs_t, time_t mtime, void *, searchpathfuncs_t *f), void *parm)
|
|
{
|
|
HANDLE r;
|
|
WIN32_FIND_DATAA fd;
|
|
char apath[MAX_OSPATH];
|
|
char file[MAX_OSPATH];
|
|
char *s;
|
|
int go;
|
|
strcpy(apath, match);
|
|
// sprintf(apath, "%s%s", gpath, match);
|
|
for (s = apath+strlen(apath)-1; s>= apath; s--)
|
|
{
|
|
if (*s == '/')
|
|
break;
|
|
}
|
|
s++;
|
|
*s = '\0';
|
|
|
|
strcpy(file, match);
|
|
r = FindFirstFileA(file, &fd);
|
|
if (r==(HANDLE)-1)
|
|
return;
|
|
go = true;
|
|
do
|
|
{
|
|
if (*fd.cFileName == '.');
|
|
else if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) //is a directory
|
|
{
|
|
sprintf(file, "%s%s/", apath, fd.cFileName);
|
|
go = func(file, fd.nFileSizeLow, Sys_FileTimeToTime(fd.ftLastWriteTime), parm, NULL);
|
|
}
|
|
else
|
|
{
|
|
sprintf(file, "%s%s", apath, fd.cFileName);
|
|
go = func(file, fd.nFileSizeLow, Sys_FileTimeToTime(fd.ftLastWriteTime), parm, NULL);
|
|
}
|
|
}
|
|
while(FindNextFileA(r, &fd) && go);
|
|
FindClose(r);
|
|
}
|
|
#endif
|
|
|
|
char *COM_ParseType (const char *data, char *out, int outlen, com_tokentype_t *toktype)
|
|
{
|
|
int c;
|
|
int len;
|
|
|
|
len = 0;
|
|
out[0] = 0;
|
|
|
|
if (!data)
|
|
return NULL;
|
|
|
|
// skip whitespace
|
|
skipwhite:
|
|
while ( (c = *data) <= ' ')
|
|
{
|
|
if (c == 0)
|
|
return NULL; // end of file;
|
|
data++;
|
|
}
|
|
|
|
// skip // comments
|
|
if (c=='/')
|
|
{
|
|
if (data[1] == '/')
|
|
{
|
|
while (*data && *data != '\n')
|
|
data++;
|
|
goto skipwhite;
|
|
}
|
|
}
|
|
|
|
|
|
// handle quoted strings specially
|
|
if (c == '\"')
|
|
{
|
|
com_tokentype = TTP_STRING;
|
|
data++;
|
|
while (1)
|
|
{
|
|
if (len >= outlen-1)
|
|
return (char*)data;
|
|
|
|
c = *data++;
|
|
if (c=='\"' || !c)
|
|
{
|
|
out[len] = 0;
|
|
return (char*)data;
|
|
}
|
|
out[len] = c;
|
|
len++;
|
|
}
|
|
}
|
|
|
|
com_tokentype = TTP_UNKNOWN;
|
|
|
|
// parse a regular word
|
|
do
|
|
{
|
|
if (len >= outlen-1)
|
|
return (char*)data;
|
|
|
|
out[len] = c;
|
|
data++;
|
|
len++;
|
|
c = *data;
|
|
} while (c>32);
|
|
|
|
out[len] = 0;
|
|
return (char*)data;
|
|
}
|
|
|
|
/*#undef COM_ParseToken
|
|
char *COM_ParseToken (const char *data, const char *punctuation)
|
|
{
|
|
int c;
|
|
int len;
|
|
len = 0;
|
|
com_token[0] = 0;
|
|
|
|
if (!data)
|
|
return NULL;
|
|
|
|
// skip whitespace
|
|
skipwhite:
|
|
while ( (c = *data) <= ' ')
|
|
{
|
|
if (c == 0)
|
|
return NULL; // end of file;
|
|
data++;
|
|
}
|
|
|
|
// skip // comments
|
|
if (c=='/')
|
|
{
|
|
if (data[1] == '/')
|
|
{
|
|
while (*data && *data != '\n')
|
|
data++;
|
|
goto skipwhite;
|
|
}
|
|
else if (data[1] == '*')
|
|
{
|
|
data+=2;
|
|
while (*data && (*data != '*' || data[1] != '/'))
|
|
data++;
|
|
data+=2;
|
|
goto skipwhite;
|
|
}
|
|
}
|
|
|
|
|
|
// handle quoted strings specially
|
|
if (c == '\"')
|
|
{
|
|
com_tokentype = TTP_STRING;
|
|
data++;
|
|
while (1)
|
|
{
|
|
c = *data++;
|
|
if (c=='\"' || !c)
|
|
{
|
|
com_token[len] = 0;
|
|
return (char*)data;
|
|
}
|
|
com_token[len] = c;
|
|
len++;
|
|
}
|
|
}
|
|
|
|
com_tokentype = TTP_UNKNOWN;
|
|
|
|
// parse single characters
|
|
if (c==',' || c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':' || c==';' || c == '=' || c == '!' || c == '>' || c == '<' || c == '&' || c == '|' || c == '+')
|
|
{
|
|
com_token[len] = c;
|
|
len++;
|
|
com_token[len] = 0;
|
|
return (char*)data+1;
|
|
}
|
|
|
|
// parse a regular word
|
|
do
|
|
{
|
|
com_token[len] = c;
|
|
data++;
|
|
len++;
|
|
c = *data;
|
|
if (c==',' || c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':' || c==';' || c == '=' || c == '!' || c == '>' || c == '<' || c == '&' || c == '|' || c == '+')
|
|
break;
|
|
} while (c>32);
|
|
|
|
com_token[len] = 0;
|
|
return (char*)data;
|
|
}*/
|
|
|
|
/*
|
|
IWEBFILE *IWebFOpenRead(char *name) //fread(name, "rb");
|
|
{
|
|
FILE *f;
|
|
char name2[512];
|
|
if (strstr(name, ".."))
|
|
return NULL;
|
|
sprintf(name2, "%s/%s", com_gamedir, name);
|
|
f = fopen(name2, "rb");
|
|
if (f)
|
|
{
|
|
IWEBFILE *ret = IWebMalloc(sizeof(IWEBFILE));
|
|
if (!ret)
|
|
{
|
|
fclose(f);
|
|
return NULL;
|
|
}
|
|
ret->f = f;
|
|
ret->start = 0;
|
|
|
|
fseek(f, 0, SEEK_END);
|
|
ret->end = ftell(f);//ret->start+ret->length;
|
|
fseek(f, 0, SEEK_SET);
|
|
|
|
ret->length = ret->end - ret->start;
|
|
return ret;
|
|
}
|
|
return NULL;
|
|
}
|
|
*/
|
|
|
|
|
|
#else
|
|
|
|
#ifdef WEBSERVER
|
|
cvar_t ftpserver = CVAR("sv_ftp", "0");
|
|
cvar_t ftpserver_port = CVAR("sv_ftp_port", "21");
|
|
cvar_t httpserver = CVAR("sv_http", "0");
|
|
cvar_t httpserver_port = CVAR("sv_http_port", "80");
|
|
cvar_t sv_readlevel = CVAR("sv_readlevel", "0"); //default to allow anyone
|
|
cvar_t sv_writelevel = CVAR("sv_writelevel", "35"); //allowed to write to uploads/uname
|
|
cvar_t sv_fulllevel = CVAR("sv_fulllevel", "51"); //allowed to write anywhere, replace any file...
|
|
cvar_t sv_ftp_port_range = CVARD("sv_ftp_port_range", "0", "Specifies the port range for the server to create listening sockets for 'active' ftp connections, to work around NAT/firewall issues.\nMost FTP clients should use passive connections, but there's still some holdouts like windows.");
|
|
|
|
int IWebGetSafeListeningPort(void)
|
|
{
|
|
char *e;
|
|
int base, range;
|
|
static int sequence;
|
|
if (!*sv_ftp_port_range.string)
|
|
return 0; //lets the OS pick.
|
|
base = strtol(sv_ftp_port_range.string, &e, 0);
|
|
while(*e == ' ')
|
|
e++;
|
|
if (*e == '-')
|
|
e++;
|
|
while(*e == ' ')
|
|
e++;
|
|
range = strtol(e, NULL, 0);
|
|
if (range < base)
|
|
range = base;
|
|
return base + (sequence++ % (range+1-base));
|
|
}
|
|
#endif
|
|
|
|
//this file contains functions called from each side.
|
|
|
|
void VARGS IWebWarnPrintf(char *fmt, ...)
|
|
{
|
|
va_list argptr;
|
|
char msg[4096];
|
|
|
|
va_start (argptr,fmt);
|
|
vsnprintf (msg,sizeof(msg)-10, fmt,argptr); //catch any nasty bugs... (this is hopefully impossible)
|
|
va_end (argptr);
|
|
|
|
Con_Printf(CON_WARNING "%s", msg);
|
|
}
|
|
|
|
void IWebInit(void)
|
|
{
|
|
#ifdef WEBSERVER
|
|
Cvar_Register(&sv_fulllevel, "Internet Server Access");
|
|
Cvar_Register(&sv_writelevel, "Internet Server Access");
|
|
Cvar_Register(&sv_readlevel, "Internet Server Access");
|
|
|
|
Cvar_Register(&ftpserver, "Internet Server Access");
|
|
Cvar_Register(&ftpserver_port, "Internet Server Access");
|
|
Cvar_Register(&sv_ftp_port_range, "Internet Server Access");
|
|
Cvar_Register(&httpserver, "Internet Server Access");
|
|
Cvar_Register(&httpserver_port, "Internet Server Access");
|
|
|
|
//don't allow these to be changed easily
|
|
//this basically blocks these from rcon / stuffcmd
|
|
ftpserver.restriction = RESTRICT_MAX;
|
|
httpserver.restriction = RESTRICT_MAX;
|
|
sv_fulllevel.restriction = RESTRICT_MAX;
|
|
sv_writelevel.restriction = RESTRICT_MAX;
|
|
sv_readlevel.restriction = RESTRICT_MAX;
|
|
#endif
|
|
}
|
|
void IWebRun(void)
|
|
{
|
|
#ifdef WEBSERVER
|
|
extern qboolean httpserverfailed, ftpserverfailed;
|
|
|
|
FTP_ServerRun(ftpserver.ival!= 0, ftpserver_port.ival);
|
|
HTTP_ServerPoll(httpserver.ival!=0, httpserver_port.ival);
|
|
if (ftpserverfailed)
|
|
{
|
|
Con_Printf("FTP Server failed to load, setting %s to 0\n", ftpserver.name);
|
|
Cvar_SetValue(&ftpserver, 0);
|
|
ftpserverfailed = false;
|
|
}
|
|
if (httpserverfailed)
|
|
{
|
|
Con_Printf("HTTP Server failed to load, setting %s to 0\n", httpserver.name);
|
|
Cvar_SetValue(&httpserver, 0);
|
|
httpserverfailed = false;
|
|
}
|
|
#endif
|
|
}
|
|
void IWebShutdown(void)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
#ifdef WEBSVONLY
|
|
void *Sys_CreateThread(char *name, int (*func)(void *), void *args, int priority, int stacksize)
|
|
{
|
|
return NULL;
|
|
}
|
|
qboolean FS_Remove(const char *fname, enum fs_relative relativeto)
|
|
{
|
|
return false;
|
|
}
|
|
qboolean FS_NativePath(const char *fname, enum fs_relative relativeto, char *out, int outlen)
|
|
{
|
|
Q_strncpyz(out, fname, outlen);
|
|
if (*out == '/' || strstr(out, ".."))
|
|
{
|
|
*out = 0;
|
|
return false;
|
|
}
|
|
return strlen(fname) == strlen(out);
|
|
}
|
|
void FS_FlushFSHashWritten(const char *fname) {}
|
|
void FS_FlushFSHashRemoved(const char *fname) {}
|
|
qboolean FS_Rename(const char *oldf, const char *newf, enum fs_relative relativeto)
|
|
{
|
|
return rename(oldf, newf) != -1;
|
|
}
|
|
#ifdef _WIN32
|
|
#include <direct.h>
|
|
void FS_CreatePath(const char *pname, enum fs_relative relativeto)
|
|
{
|
|
_mkdir(pname);
|
|
}
|
|
qboolean Sys_rmdir (const char *path)
|
|
{
|
|
return _rmdir(path) != -1;
|
|
}
|
|
#else
|
|
#include <unistd.h>
|
|
void FS_CreatePath(const char *pname, enum fs_relative relativeto)
|
|
{
|
|
mkdir(pname);
|
|
}
|
|
qboolean Sys_rmdir (const char *path)
|
|
{
|
|
return rmdir(path) != -1;
|
|
}
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
int IWebAuthorize(const char *name, const char *password)
|
|
{
|
|
#ifdef WEBSVONLY
|
|
if (authedusername)
|
|
{
|
|
if (!strcmp(name, authedusername))
|
|
{
|
|
if (!strcmp(password, autheduserpassword))
|
|
return IWEBACC_FULL;
|
|
}
|
|
}
|
|
|
|
//if they tried giving some other username, don't give them any access (prevents them from reading actual user files).
|
|
if (*name && stricmp(name, "anonymous"))
|
|
return 0;
|
|
return anonaccess;
|
|
#else
|
|
#ifndef CLIENTONLY
|
|
int id = Rank_GetPlayerID(NULL, name, atoi(password), false, true);
|
|
rankinfo_t info;
|
|
if (!id)
|
|
{
|
|
if (!sv_readlevel.value && (!*name || !stricmp(name, "anonymous")))
|
|
return IWEBACC_READ; //read only anywhere
|
|
return 0;
|
|
}
|
|
|
|
Rank_GetPlayerInfo(id, &info);
|
|
|
|
if (info.s.trustlevel >= sv_fulllevel.value)
|
|
return IWEBACC_READ | IWEBACC_WRITE | IWEBACC_FULL; //allowed to read and write anywhere to the quake filesystem
|
|
if (info.s.trustlevel >= sv_writelevel.value)
|
|
return IWEBACC_READ | IWEBACC_WRITE; //allowed to read anywhere write to specific places
|
|
if (info.s.trustlevel >= sv_readlevel.value)
|
|
return IWEBACC_READ; //read only anywhere
|
|
#endif
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
iwboolean IWebAllowUpLoad(const char *fname, const char *uname) //called for partial write access
|
|
{
|
|
if (strstr(fname, ".."))
|
|
return false;
|
|
if (!strncmp(fname, "uploads/", 8))
|
|
{
|
|
if (!strncmp(fname+8, uname, strlen(uname)))
|
|
if (fname[8+strlen(uname)] == '/')
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
char *Q_strcpyline(char *out, const char *in, int maxlen)
|
|
{
|
|
char *w = out;
|
|
while (*in && maxlen > 0)
|
|
{
|
|
if (*in == '\r' || *in == '\n')
|
|
break;
|
|
*w = *in;
|
|
in++;
|
|
w++;
|
|
maxlen--;
|
|
}
|
|
*w = '\0';
|
|
return out;
|
|
}
|
|
|
|
#endif
|