diff --git a/source/src/protocol.cpp b/source/src/protocol.cpp index 0b83f22f..61d1c905 100644 --- a/source/src/protocol.cpp +++ b/source/src/protocol.cpp @@ -207,12 +207,45 @@ void freegzbuf(ucharbuf *p) // free a ucharbuf created by getgzbuf() } } +//#define FILENAMESALLLOWERCASE + +bool validmapname(const char *s) // checks for length, allowed chars and special DOS filenames +{ + int len = strlen(s); + if(len > MAXMAPNAMELEN) return false; + if(len == 3 || len == 4) + { + char uc[4]; + loopi(3) uc[i] = toupper(s[i]); + uc[3] = '\0'; + const char *resd = "COMLPTCONPRNAUXNUL", *fnd = strstr(resd, uc); + if(fnd) + { + int pos = (int) (fnd - resd); + if(pos == 0 || pos == 3) + { + if(isdigit(s[3])) return false; // COMx, LPTx + } + else if(pos % 3 == 0) return false; // CON, PRN, AUX, NUL + } + } + while(*s != '\0') + { +#ifdef FILENAMESALLLOWERCASE + if(!islower(*s) && !isdigit(*s) && *s != '_' && *s != '-' && *s != '.') return false; +#else + if(!isalnum(*s) && *s != '_' && *s != '-' && *s != '.') return false; +#endif + ++s; + } + return true; +} + + // filter text according to rules // dst can be identical to src; dst needs to be of size "min(len, strlen(s)) + 1" // returns dst -//#define FILENAMESALLLOWERCASE - char *filtertext(char *dst, const char *src, int flags, int len) { char *res = dst; diff --git a/source/src/protocol.h b/source/src/protocol.h index 0c6f3490..58d10090 100644 --- a/source/src/protocol.h +++ b/source/src/protocol.h @@ -9,6 +9,7 @@ #define DEMO_VERSION 2 // bump when demo format changes #define DEMO_MAGIC "ASSAULTCUBE_DEMO" #define DEMO_MINTIME 10000 // don't keep demo recordings with less than 10 seconds +#define MAXMAPNAMELEN 31 #define MAXMAPSENDSIZE 65536 #define MAXCFGFILESIZE 65536 #define MAXGZMSGSIZE 65536 diff --git a/source/src/protos.h b/source/src/protos.h index c6a5a8ca..480b53a1 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -1062,6 +1062,7 @@ extern void getstring(char *t, ucharbuf &p, int len = MAXTRANS); extern void putgzbuf(vector &d, vector &s); // zips a vector into a stream, stored in another vector extern ucharbuf *getgzbuf(ucharbuf &p); // fetch a gzipped buffer; needs to be freed properly later extern void freegzbuf(ucharbuf *p); // free a ucharbuf created by getgzbuf() +extern bool validmapname(const char *s); // checks for length, allowed chars and special DOS filenames extern char *filtertext(char *dst, const char *src, int flags, int len = sizeof(string)-1); extern void filterrichtext(char *dst, const char *src, int len = sizeof(string)-1); extern void filterlang(char *d, const char *s); diff --git a/source/src/serverfiles.h b/source/src/serverfiles.h index f960672c..b13f6a0d 100644 --- a/source/src/serverfiles.h +++ b/source/src/serverfiles.h @@ -83,37 +83,43 @@ struct servermap // in-memory version of a map file on a server stream *f = NULL; int restofhead; + string filename; + + if(!validmapname(fname)) err = "illegal filename"; + if(err) goto loadfailed; // load map files, prepare sendmap buffer - defformatstring(filename)("%s%s.cfg", fpath, fname); - path(filename); - uchar *cfgraw = (uchar *)loadfile(filename, &cfglen); - if(cfgraw) { - tigerhash(cfghash, cfgraw, cfglen); - loopk(cfglen) if(cfgraw[k] > 0x7f || (cfgraw[k] < 0x20 && !isspace(cfgraw[k]))) err = "illegal chars in cfg file"; - } - formatstring(filename)("%s%s.cgz", fpath, fname); - path(filename); - cgzraw = (uchar *)loadfile(filename, &cgzlen); - if(cgzraw) tigerhash(cgzhash, cgzraw, cgzlen); - if(!cgzraw) err = "loading cgz failed"; - else if(cfglen > MAXCFGFILESIZE) err = "cfg file too big"; - else if(cgzlen >= MAXMAPSENDSIZE) err = "cgz file too big"; - else if(cfgraw) - { - uLongf gzbufsize = GZBUFSIZE; - ASSERT(GZBUFSIZE < FLOORPLANBUFSIZE); - if(compress2(staticbuffer, &gzbufsize, cfgraw, cfglen, 9) != Z_OK) gzbufsize = 0; - cfggzlen = (int) gzbufsize; - if(cgzlen + cfggzlen < MAXMAPSENDSIZE) - { // map is small enough to be sent - cfgrawgz = new uchar[cfggzlen]; - memcpy(cfgrawgz, staticbuffer, cfggzlen); + formatstring(filename)("%s%s.cfg", fpath, fname); + path(filename); + uchar *cfgraw = (uchar *)loadfile(filename, &cfglen); + if(cfgraw) + { + tigerhash(cfghash, cfgraw, cfglen); + loopk(cfglen) if(cfgraw[k] > 0x7f || (cfgraw[k] < 0x20 && !isspace(cfgraw[k]))) err = "illegal chars in cfg file"; } - else err = "cgz + cfg.gz too big to send"; + formatstring(filename)("%s%s.cgz", fpath, fname); + path(filename); + cgzraw = (uchar *)loadfile(filename, &cgzlen); + if(cgzraw) tigerhash(cgzhash, cgzraw, cgzlen); + if(!cgzraw) err = "loading cgz failed"; + else if(cfglen > MAXCFGFILESIZE) err = "cfg file too big"; + else if(cgzlen >= MAXMAPSENDSIZE) err = "cgz file too big"; + else if(cfgraw) + { + uLongf gzbufsize = GZBUFSIZE; + ASSERT(GZBUFSIZE < FLOORPLANBUFSIZE); + if(compress2(staticbuffer, &gzbufsize, cfgraw, cfglen, 9) != Z_OK) gzbufsize = 0; + cfggzlen = (int) gzbufsize; + if(cgzlen + cfggzlen < MAXMAPSENDSIZE) + { // map is small enough to be sent + cfgrawgz = new uchar[cfggzlen]; + memcpy(cfgrawgz, staticbuffer, cfggzlen); + } + else err = "cgz + cfg.gz too big to send"; + } + DELETEA(cfgraw); } - DELETEA(cfgraw); if(err) goto loadfailed; // extract entity data and header info; compile map statistics; create floorplan diff --git a/source/src/tools.h b/source/src/tools.h index b882d5d4..f8f5b2a8 100644 --- a/source/src/tools.h +++ b/source/src/tools.h @@ -139,35 +139,6 @@ struct stringformatter #define defformatstring(d) string d; formatstring(d) #define defvformatstring(d,last,fmt) string d; { va_list ap; va_start(ap, last); vformatstring(d, fmt, ap); va_end(ap); } -#define MAXMAPNAMELEN 64 -inline bool validmapname(const char *s) -{ - int len = strlen(s); - if(len > MAXMAPNAMELEN) return false; - if(len == 3 || len == 4) - { - char uc[4]; - loopi(3) uc[i] = toupper(s[i]); - uc[3] = '\0'; - const char *resd = "COMLPTCONPRNAUXNUL", *fnd = strstr(resd, uc); - if(fnd) - { - int pos = (int) (fnd - resd); - if(pos == 0 || pos == 3) - { - if(isdigit(s[3])) return false; // COMx, LPTx - } - else if(pos % 3 == 0) return false; // CON, PRN, AUX, NUL - } - } - while(*s != '\0') - { - if(!isalnum(*s) && *s != '_' && *s != '-' && *s != '.') return false; - ++s; - } - return true; -} - #define loopv(v) for(int i = 0; i<(v).length(); i++) #define loopvj(v) for(int j = 0; j<(v).length(); j++) #define loopvk(v) for(int k = 0; k<(v).length(); k++)