diff --git a/source/src/serveractions.h b/source/src/serveractions.h index 2b2e1419..5c263200 100644 --- a/source/src/serveractions.h +++ b/source/src/serveractions.h @@ -65,13 +65,22 @@ struct mapaction : serveraction bool notify = valid_client(caller); int maploc = MAP_NOTFOUND; mapstats *ms = map[0] ? getservermapstats(map, false, &maploc) : NULL; - mapok = (ms != NULL) && ( (mode != GMODE_COOPEDIT && mapisok(ms)) || (mode == GMODE_COOPEDIT && !readonlymap(maploc)) ); + bool validname = validmapname(map); + mapok = (ms != NULL) && validname && ( (mode != GMODE_COOPEDIT && mapisok(ms)) || (mode == GMODE_COOPEDIT && !readonlymap(maploc)) ); if(!mapok) { - if(notify) sendservmsg(ms ? - ( mode == GMODE_COOPEDIT ? "this map cannot be coopedited in this server" : "sorry, but this map does not satisfy some quality requisites to be played in MultiPlayer Mode" ) : - "the server does not have this map", - caller); + if(notify) + { + if(!validname) + sendservmsg("invalid map name", caller); + else + { + sendservmsg(ms ? + ( mode == GMODE_COOPEDIT ? "this map cannot be coopedited in this server" : "sorry, but this map does not satisfy some quality requisites to be played in MultiPlayer Mode" ) : + "the server does not have this map", + caller); + } + } } else { // check, if map supports mode diff --git a/source/src/tools.h b/source/src/tools.h index 0fe897cf..78ead339 100644 --- a/source/src/tools.h +++ b/source/src/tools.h @@ -160,6 +160,18 @@ inline bool issimilar (char s, char d) return false; } +#define MAXMAPNAMELEN 64 +inline bool validmapname(char *s) +{ + if(strlen(s) > MAXMAPNAMELEN) return false; + while(*s != '\0') + { + if(!isalnum(*s) && *s != '_' && *s != '-') return false; + ++s; + } + return true; +} + inline bool findpattern (char *s, char *d) // returns true if there is more than 80% of similarity { int len, hit = 0; diff --git a/source/src/worldio.cpp b/source/src/worldio.cpp index fc3e8da4..2db74b9f 100644 --- a/source/src/worldio.cpp +++ b/source/src/worldio.cpp @@ -10,11 +10,11 @@ void backup(char *name, char *backupname) rename(findfile(name, "wb"), backupfile); } -static string cgzname, ocgzname, bakname, pcfname, mcfname, omcfname; +static string cgzname, ocgzname, bakname, pcfname, mcfname, omcfname, mapname; const char *setnames(const char *name) { - string pakname, mapname; + string pakname; const char *slash = strpbrk(name, "/\\"); if(slash) { @@ -205,6 +205,11 @@ void save_world(char *mname) { if(!*mname) mname = getclientmap(); if(securemapcheck(mname)) return; + if(!validmapname(mname)) + { + conoutf("\f3invalid map name. it must only contains letters, digits, '-', '_' and be less than %d characters long", MAXMAPNAMELEN); + return; + } voptimize(); toptimize(); setnames(mname); @@ -322,6 +327,11 @@ bool load_world(char *mname) // still supports all map formats that have copystring(mcfname, omcfname); } else maploaded = getfilesize(cgzname); + if(!validmapname(mapname)) + { + conoutf("\f3invalid map name. it must only contains letters, digits, '-', '_' and be less than %d characters long", MAXMAPNAMELEN); + return false; + } stream *f = opengzfile(cgzname, "rb"); if(!f) { conoutf("\f3could not read map %s", cgzname); return false; } header tmp;