From fc314b6616e14b83a40e8dca9cbe94caa2e4f08c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 6 Apr 2021 01:06:03 +0200 Subject: [PATCH] - allow loading Zips where all content is in a subdirectory. The same logic as in GZDoom applies: The root must not have any other content and the subdirectory must contain identifiable game content. Some handling was also added to strip out macOS resource fork folders because they can contain data that can confuse file detection. --- source/common/filesystem/file_zip.cpp | 16 ++++++++++++---- source/core/initfs.cpp | 14 ++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/source/common/filesystem/file_zip.cpp b/source/common/filesystem/file_zip.cpp index 00de98cdc..2adca1160 100644 --- a/source/common/filesystem/file_zip.cpp +++ b/source/common/filesystem/file_zip.cpp @@ -233,12 +233,14 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) } name.ToLower(); + if (name.IndexOf("__macosx") == 0) + continue; // skip Apple garbage. At this stage only the root folder matters, if (i == 0) { // check for special names, if one of these gets found this must be treated as a normal zip. bool isspecial = name.IndexOf("/") < 0 || (filter && filter->reservedFolders.Find(name) < filter->reservedFolders.Size()); if (isspecial) break; - name0 = name; + name0 = name.Left(name.LastIndexOf("/")+1); } else { @@ -252,7 +254,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) // at least one of the more common definition lumps must be present. for (auto &p : filter->requiredPrefixes) { - if (name.IndexOf(name0 + p) == 0) + if (name.IndexOf(name0 + p) == 0 || name.LastIndexOf(p) == name.Len() - strlen(p)) { foundspeciallump = true; break; @@ -272,7 +274,6 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) int len = LittleShort(zip_fh->NameLength); FString name(dirptr + sizeof(FZipCentralDirectoryInfo), len); - if (name0.IsNotEmpty()) name = name.Mid(name0.Len()); dirptr += sizeof(FZipCentralDirectoryInfo) + LittleShort(zip_fh->NameLength) + LittleShort(zip_fh->ExtraLength) + @@ -284,7 +285,14 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Central directory corrupted.", FileName.GetChars()); return false; } - + + if (name.IndexOf("__macosx") == 0 || name.IndexOf("__MACOSX") == 0) + { + skipped++; + continue; // Weed out Apple's resource fork garbage right here because it interferes with safe operation. + } + if (name0.IsNotEmpty()) name = name.Mid(name0.Len()); + // skip Directories if (name.IsEmpty() || (name.Back() == '/' && LittleLong(zip_fh->UncompressedSize) == 0)) { diff --git a/source/core/initfs.cpp b/source/core/initfs.cpp index f18fd50d3..6910d2cdf 100644 --- a/source/core/initfs.cpp +++ b/source/core/initfs.cpp @@ -274,6 +274,18 @@ static void DeleteStuff(FileSystem &fileSystem, const TArray& deletelum // // //========================================================================== +const char* iwad_folders[13] = { "textures/", "hires/", "sounds/", "music/", "maps/" }; +const char* iwad_reserved_duke[12] = { ".map", ".con", "menudef", "gldefs", "zscript", "maps/", nullptr }; +const char* iwad_reserved_blood[12] = { ".map", ".ini", "menudef", "gldefs", "zscript", "maps/", nullptr }; +const char* iwad_reserved_sw[12] = { ".map", "swcustom.txt", "menudef", "gldefs", "zscript", "maps/", nullptr }; +const char* iwad_reserved_ex[12] = { ".map", "menudef", "gldefs", "zscript", "maps/", nullptr }; + +const char** iwad_reserved() +{ + return (g_gameType & GAMEFLAG_PSEXHUMED) ? iwad_reserved_ex : + (g_gameType & GAMEFLAG_SW) ? iwad_reserved_sw : + (g_gameType & GAMEFLAG_BLOOD) ? iwad_reserved_blood : iwad_reserved_duke; +} void InitFileSystem(TArray& groups) { @@ -374,6 +386,8 @@ void InitFileSystem(TArray& groups) } todelete.Append(userConfig.toBeDeleted); LumpFilterInfo lfi; + for (auto p : iwad_folders) lfi.reservedFolders.Push(p); + for (auto p = iwad_reserved(); *p; p++) lfi.requiredPrefixes.Push(*p); lfi.dotFilter = LumpFilter;