diff --git a/source/src/autodownload.cpp b/source/src/autodownload.cpp index 15d5ed3a..ed73622b 100644 --- a/source/src/autodownload.cpp +++ b/source/src/autodownload.cpp @@ -221,6 +221,11 @@ bool requirepackage(int type, const char *name, const char *host) pck->exts = mapexts; break; + case PCK_MOD: + prefix = "mods/"; + forceext = ".zip"; + break; + default: conoutf("\f3requirepackage: illegal package type %d (\"%s\")", type, name); // should probably be fatal() delete pck; @@ -230,7 +235,7 @@ bool requirepackage(int type, const char *name, const char *host) copystring(upath, name); unixpath(upath); filtertext(pck->name, name, FTXT__MEDIAFILEPATH); // also changes backslashes to slashes - if(strlen(upath) > 100 || strcmp(upath, pck->name) || (checkprefix && strncmp(pck->name, checkprefix, strlen(checkprefix)))) + if(strlen(upath) > 100 || strcmp(upath, pck->name) || (checkprefix && strncmp(pck->name, checkprefix, strlen(checkprefix))) || (type == PCK_MOD && !validzipmodname(upath))) { conoutf("\f3requirepackage: illegal media path \"%s\" (type: %d)", name, type); delete pck; @@ -305,7 +310,7 @@ void processdownload(package *pck, stream *f) // write downloaded data to file(s stream *d = openfile(path(pck->fullpath, true), "wb"); if(d) { - streamcopy(d, f, MAXMEDIADOWNLOADFILESIZE); + streamcopy(d, f, pck->type == PCK_MOD ? MAXMODDOWNLOADSIZE : MAXMEDIADOWNLOADFILESIZE); delete d; } delete f; @@ -493,3 +498,10 @@ void writepcksourcecfg() delete f; } } + +void getmod(char *name) +{ + if(requirepackage(PCK_MOD, name) && downloadpackages()) conoutf("mod package %s successfully downloaded", name); + else conoutf("failed to download mod package %s", name); +} +COMMAND(getmod, "s"); diff --git a/source/src/protocol.h b/source/src/protocol.h index b16d3120..0bce83bc 100644 --- a/source/src/protocol.h +++ b/source/src/protocol.h @@ -12,6 +12,7 @@ #define MAXMAPSENDSIZE 65536 #define MAXCFGFILESIZE 65536 #define MAXMEDIADOWNLOADFILESIZE 1024000 // hard cap on filesizes (raw and unzipped) - to limit the effect of zip bombs - no nice error messages: just cap +#define MAXMODDOWNLOADSIZE 1024000 // hard cap on the filesize of downloaded mod packages - to keep stuff reasonable #define MAXFILESINADZIP 21 // max number of files extracted from a zip by autodownload extern bool modprotocol; diff --git a/source/src/protos.h b/source/src/protos.h index 5f217bdb..593a903e 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -371,7 +371,7 @@ extern Texture *crosshairs[]; extern void drawcrosshair(playerent *p, int n, struct color *c = NULL, float size = -1.0f); // autodownload -enum { PCK_TEXTURE = 0, PCK_SKYBOX, PCK_MAPMODEL, PCK_AUDIO, PCK_MAP, PCK_NUM }; +enum { PCK_TEXTURE = 0, PCK_SKYBOX, PCK_MAPMODEL, PCK_AUDIO, PCK_MAP, PCK_MOD, PCK_NUM }; extern int autodownload; extern void setupautodownload(); extern void pollautodownloadresponse(); diff --git a/source/src/tools.h b/source/src/tools.h index d0b21e6b..88d12ddc 100644 --- a/source/src/tools.h +++ b/source/src/tools.h @@ -963,6 +963,7 @@ extern void listfilesrecursive(const char *dir, vector &files, int level extern void listzipfiles(const char *dir, const char *ext, vector &files); extern bool delfile(const char *path); extern void backup(char *name, char *backupname); +extern bool validzipmodname(char *name); extern void *zipmanualopen(stream *f, vector &files); extern stream *zipmanualstream(void *a, int n); extern int zipmanualread(void *a, int n, stream *f, int maxlen = INT_MAX); diff --git a/source/src/zip.cpp b/source/src/zip.cpp index a906dac8..ea934b36 100644 --- a/source/src/zip.cpp +++ b/source/src/zip.cpp @@ -498,6 +498,11 @@ const char *fixzipname(char *name) // check, if valid path + filename, based on return path(pname); } +bool validzipmodname(char *name) // check for valid _downloadable_ zip mod name (no '#' allowed), also changes backslashes to slashes +{ + return fixzipname(name) && !strchr(name, '#'); +} + VAR(zipcachemaxsize, 0, 512, 1024); // load zip files smaller than 512K straight into RAM void addzipmod(char *name)