Fix .zip with too many entries not getting loaded

This commit is contained in:
UnknownShadow200 2018-12-21 10:05:09 +11:00
parent 5de42ad3d3
commit 7813b5719e
10 changed files with 106 additions and 65 deletions

View File

@ -4,9 +4,10 @@
Copyright 2017 ClassicalSharp | Licensed under BSD-3
*/
#define PROGRAM_MAX_CMDARGS 5
#define PROGRAM_APP_NAME "ClassiCube 0.99.9.2"
#define PROGRAM_APP_VER "0.99.9.2"
#define GAME_MAX_CMDARGS 5
#define GAME_APP_NAME "ClassiCube 0.99.9.2"
#define GAME_APP_VER "0.99.9.2"
#define GAME_API_VER 1
/* Max number of characters strings can have. */
#define STRING_SIZE 64

View File

@ -1107,34 +1107,45 @@ static ReturnCode Zip_ReadLocalFileHeader(struct ZipState* state, struct ZipEntr
return 0;
}
static ReturnCode Zip_ReadCentralDirectory(struct ZipState* state, struct ZipEntry* entry) {
static ReturnCode Zip_ReadCentralDirectory(struct ZipState* state) {
struct Stream* stream = state->Input;
struct ZipEntry* entry;
uint8_t header[42];
String path; char pathBuffer[ZIP_MAXNAMELEN];
int pathLen, extraLen, commentLen;
ReturnCode res;
if ((res = Stream_Read(stream, header, sizeof(header)))) return res;
entry->CompressedSize = Stream_GetU32_LE(&header[16]);
entry->UncompressedSize = Stream_GetU32_LE(&header[20]);
pathLen = Stream_GetU16_LE(&header[24]);
path = String_Init(pathBuffer, pathLen, pathLen);
if (pathLen > ZIP_MAXNAMELEN) return ZIP_ERR_FILENAME_LEN;
if ((res = Stream_Read(stream, pathBuffer, pathLen))) return res;
/* skip data following central directory entry header */
extraLen = Stream_GetU16_LE(&header[26]);
commentLen = Stream_GetU16_LE(&header[28]);
if ((res = stream->Skip(stream, extraLen + commentLen))) return res;
if (!state->SelectEntry(&path)) return 0;
if (state->_usedEntries >= ZIP_MAX_ENTRIES) return ZIP_ERR_TOO_MANY_ENTRIES;
entry = &state->Entries[state->_usedEntries++];
entry->CompressedSize = Stream_GetU32_LE(&header[16]);
entry->UncompressedSize = Stream_GetU32_LE(&header[20]);
entry->LocalHeaderOffset = Stream_GetU32_LE(&header[38]);
/* skip data following central directory entry header */
return stream->Skip(stream, pathLen + extraLen + commentLen);
return 0;
}
static ReturnCode Zip_ReadEndOfCentralDirectory(struct ZipState* state, uint32_t* centralDirectoryOffset) {
static ReturnCode Zip_ReadEndOfCentralDirectory(struct ZipState* state) {
struct Stream* stream = state->Input;
uint8_t header[18];
ReturnCode res;
if ((res = Stream_Read(stream, header, sizeof(header)))) return res;
state->EntriesCount = Stream_GetU16_LE(&header[6]);
*centralDirectoryOffset = Stream_GetU32_LE(&header[12]);
state->_totalEntries = Stream_GetU16_LE(&header[6]);
state->_centralDirBeg = Stream_GetU32_LE(&header[12]);
return 0;
}
@ -1149,19 +1160,17 @@ static bool Zip_DefaultSelector(const String* path) { return true; }
void Zip_Init(struct ZipState* state, struct Stream* input) {
state->Input = input;
state->Obj = NULL;
state->EntriesCount = 0;
state->ProcessEntry = Zip_DefaultProcessor;
state->SelectEntry = Zip_DefaultSelector;
}
ReturnCode Zip_Extract(struct ZipState* state) {
struct Stream* stream = state->Input;
uint32_t stream_len, centralDirOffset;
uint32_t stream_len;
uint32_t sig = 0;
int i, count;
ReturnCode res;
state->EntriesCount = 0;
if ((res = stream->Length(stream, &stream_len))) return res;
/* At -22 for nearly all zips, but try a bit further back in case of comment */
@ -1175,19 +1184,19 @@ ReturnCode Zip_Extract(struct ZipState* state) {
}
if (sig != ZIP_SIG_ENDOFCENTRALDIR) return ZIP_ERR_NO_END_OF_CENTRAL_DIR;
res = Zip_ReadEndOfCentralDirectory(state, &centralDirOffset);
res = Zip_ReadEndOfCentralDirectory(state);
if (res) return res;
res = stream->Seek(stream, centralDirOffset);
res = stream->Seek(stream, state->_centralDirBeg);
if (res) return ZIP_ERR_SEEK_CENTRAL_DIR;
if (state->EntriesCount > ZIP_MAX_ENTRIES) return ZIP_ERR_TOO_MANY_ENTRIES;
state->_usedEntries = 0;
/* Read all the central directory entries */
for (count = 0; count < state->EntriesCount; count++) {
for (i = 0; i < state->_totalEntries; i++) {
if ((res = Stream_ReadU32_LE(stream, &sig))) return res;
if (sig == ZIP_SIG_CENTRALDIR) {
res = Zip_ReadCentralDirectory(state, &state->Entries[count]);
res = Zip_ReadCentralDirectory(state);
if (res) return res;
} else if (sig == ZIP_SIG_ENDOFCENTRALDIR) {
break;
@ -1197,7 +1206,7 @@ ReturnCode Zip_Extract(struct ZipState* state) {
}
/* Now read the local file header entries */
for (i = 0; i < count; i++) {
for (i = 0; i < state->_usedEntries; i++) {
struct ZipEntry* entry = &state->Entries[i];
res = stream->Seek(stream, entry->LocalHeaderOffset);
if (res) return ZIP_ERR_SEEK_LOCAL_DIR;

View File

@ -67,7 +67,7 @@ struct InflateState {
/* Initialises DEFLATE decompressor state to defaults. */
CC_API void Inflate_Init(struct InflateState* state, struct Stream* source);
/* Attempts to decompress all currently pending data. */
/* Attempts to decompress as much of the currently pending data as possible. */
/* NOTE: This is a low level call - usually you should use Inflate_MakeStream. */
void Inflate_Process(struct InflateState* state);
/* Deompresses input data read from another stream using DEFLATE. Read only stream. */
@ -122,13 +122,18 @@ struct ZipState {
/* Return non-zero to indicate an error and stop further processing. */
/* NOTE: data stream MAY NOT be seekable. (i.e. entry data might be compressed) */
ReturnCode (*ProcessEntry)(const String* path, struct Stream* data, void* obj);
/* Predicate used to select which entries in a .zip archive get proessed. */
/* Predicate used to select which entries in a .zip archive get processed. */
/* NOTE: returning false entirely skips the entry. (avoids pointless seek to entry) */
bool (*SelectEntry)(const String* path);
/* Generic object/pointer passed to ProcessEntry callback. */
void* Obj;
/* Number of entries in the .zip archive. */
int EntriesCount;
/* (internal) Number of entries selected by SelectEntry. */
int _usedEntries;
/* (internal) Total number of entries in the archive. */
int _totalEntries;
/* (internal) Offset to central directory entries. */
uint32_t _centralDirBeg;
/* Data for each entry in the .zip archive. */
struct ZipEntry Entries[ZIP_MAX_ENTRIES];
};

View File

@ -372,6 +372,41 @@ static void Game_LoadOptions(void) {
}*/
}
static void Game_LoadPlugin(const String* filename, void* obj) {
void* lib;
void* verSymbol; /* EXPORT int Plugin_ApiVersion = GAME_API_VER; */
void* compSymbol; /* EXPORT struct IGameComponent Plugin_Component = { (whatever) } */
int ver;
ReturnCode res;
res = Platform_LoadLibrary(filename, &lib);
if (res) { Chat_LogError2(res, "loading plugin", filename); return; }
res = Platform_GetSymbol(lib, "Plugin_ApiVersion", &verSymbol);
if (res) { Chat_LogError2(res, "getting plugin version", filename); return; }
res = Platform_GetSymbol(lib, "Plugin_Component", &compSymbol);
if (res) { Chat_LogError2(res, "initing plugin", filename); return; }
ver = *((int*)verSymbol);
if (ver < GAME_API_VER) {
Chat_Add1("&c%s plugin is outdated! Try getting a more recent version.", filename);
return;
} else if (ver > GAME_API_VER) {
Chat_Add1("&cYour game is too outdated to use %s plugin! Try updating it.", filename);
return;
}
Game_AddComponent((struct IGameComponent*)compSymbol);
}
static void Game_LoadPlugins(void) {
const static String dir = String_FromConst("plugins");
ReturnCode res;
res = Directory_Enum(&dir, NULL, Game_LoadPlugin);
if (res) Chat_LogError(res, "enumerating plugins directory");
}
void Game_Free(void* obj);
static void Game_Load(void) {
String title; char titleBuffer[STRING_SIZE];
@ -438,22 +473,13 @@ static void Game_Load(void) {
Game_AddComponent(&Audio_Component);
Game_AddComponent(&AxisLinesRenderer_Component);
/* TODO: plugin dll support */
/* List<string> nonLoaded = PluginLoader.LoadAll(); */
//Game_LoadPlugins();
for (comp = comps_head; comp; comp = comp->Next) {
if (comp->Init) comp->Init();
}
Game_ExtractInitialTexturePack();
Game_ExtractInitialTexturePack();
entTaskI = ScheduledTask_Add(GAME_DEF_TICKS, Entities_Tick);
/* TODO: plugin dll support */
/* if (nonLoaded != null) {
for (int i = 0; i < nonLoaded.Count; i++) {
Overlay warning = new PluginOverlay(this, nonLoaded[i]);
Gui_ShowOverlay(warning, false);
}
}*/
if (Gfx_WarnIfNecessary()) EnvRenderer_SetMode(EnvRenderer_Minimal | ENV_LEGACY);
String_InitArray(title, titleBuffer);

View File

@ -828,7 +828,7 @@ static void MainScreen_TickCheckUpdates(struct MainScreen* s) {
const static String needUpdate = String_FromConst("&aNew release");
const static String upToDate = String_FromConst("&eUp to date");
const static String failed = String_FromConst("&cCheck failed");
const static String currentStr = String_FromConst(PROGRAM_APP_VER);
const static String currentStr = String_FromConst(GAME_APP_VER);
uint32_t latest, current;
if (!CheckUpdateTask.Base.Working) return;

View File

@ -235,7 +235,7 @@ static void Launcher_Free(void) {
}
void Launcher_Run(void) {
const static String title = String_FromConst(PROGRAM_APP_NAME);
const static String title = String_FromConst(GAME_APP_NAME);
Window_CreateSimple(640, 400);
Window_SetTitle(&title);
Window_SetVisible(true);

View File

@ -1333,7 +1333,7 @@ static HINTERNET hInternet;
void Http_Init(void) {
/* TODO: Should we use INTERNET_OPEN_TYPE_PRECONFIG instead? */
hInternet = InternetOpenA(PROGRAM_APP_NAME, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
hInternet = InternetOpenA(GAME_APP_NAME, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (!hInternet) ErrorHandler_Fail2(GetLastError(), "Failed to init WinINet");
}
@ -2031,7 +2031,7 @@ int Platform_GetCommandLineArgs(int argc, STRING_REF const char** argv, String*
int i;
Platform_NextArg(&cmdArgs); /* skip exe path */
for (i = 0; i < PROGRAM_MAX_CMDARGS; i++) {
for (i = 0; i < GAME_MAX_CMDARGS; i++) {
args[i] = Platform_NextArg(&cmdArgs);
if (!args[i].length) break;

View File

@ -61,12 +61,12 @@ static void Program_RunGame(void) {
}
String_InitArray(title, titleBuffer);
String_Format2(&title, "%c (%s)", PROGRAM_APP_NAME, &Game_Username);
String_Format2(&title, "%c (%s)", GAME_APP_NAME, &Game_Username);
Game_Run(width, height, &title);
}
int main(int argc, char** argv) {
String args[PROGRAM_MAX_CMDARGS];
String args[GAME_MAX_CMDARGS];
int argsCount;
uint8_t ip[4];
uint16_t port;
@ -82,7 +82,7 @@ int main(int argc, char** argv) {
#ifdef CC_TEST_VORBIS
main_imdct();
#endif
Platform_LogConst("Starting " PROGRAM_APP_NAME " ..");
Platform_LogConst("Starting " GAME_APP_NAME " ..");
Utils_EnsureDirectory("maps");
Utils_EnsureDirectory("texpacks");

View File

@ -172,11 +172,11 @@ struct ResourceMusic Resources_Music[7] = {
/*########################################################################################################################*
*---------------------------------------------------------Zip writer------------------------------------------------------*
*#########################################################################################################################*/
static ReturnCode ZipPatcher_LocalFile(struct Stream* s, struct ResourceTexture* entry) {
String name = String_FromReadonly(entry->Filename);
static ReturnCode ZipPatcher_LocalFile(struct Stream* s, struct ResourceTexture* e) {
String name = String_FromReadonly(e->Filename);
uint8_t header[30 + STRING_SIZE];
ReturnCode res;
if ((res = s->Position(s, &entry->Offset))) return res;
if ((res = s->Position(s, &e->Offset))) return res;
Stream_SetU32_LE(&header[0], 0x04034b50); /* signature */
Stream_SetU16_LE(&header[4], 20); /* version needed */
@ -185,9 +185,9 @@ static ReturnCode ZipPatcher_LocalFile(struct Stream* s, struct ResourceTexture*
Stream_SetU16_LE(&header[10], 0); /* last modified */
Stream_SetU16_LE(&header[12], 0); /* last modified */
Stream_SetU32_LE(&header[14], 0); /* CRC32 */
Stream_SetU32_LE(&header[18], 0); /* Compressed size */
Stream_SetU32_LE(&header[22], 0); /* Uncompressed size */
Stream_SetU32_LE(&header[14], e->Crc32); /* CRC32 */
Stream_SetU32_LE(&header[18], e->Size); /* Compressed size */
Stream_SetU32_LE(&header[22], e->Size); /* Uncompressed size */
Stream_SetU16_LE(&header[26], name.length); /* name length */
Stream_SetU16_LE(&header[28], 0); /* extra field length */
@ -196,8 +196,8 @@ static ReturnCode ZipPatcher_LocalFile(struct Stream* s, struct ResourceTexture*
return Stream_Write(s, header, 30 + name.length);
}
static ReturnCode ZipPatcher_CentralDir(struct Stream* s, struct ResourceTexture* res) {
String name = String_FromReadonly(res->Filename);
static ReturnCode ZipPatcher_CentralDir(struct Stream* s, struct ResourceTexture* e) {
String name = String_FromReadonly(e->Filename);
uint8_t header[46 + STRING_SIZE];
struct DateTime now;
int modTime, modDate;
@ -214,9 +214,9 @@ static ReturnCode ZipPatcher_CentralDir(struct Stream* s, struct ResourceTexture
Stream_SetU16_LE(&header[12], modTime); /* last modified */
Stream_SetU16_LE(&header[14], modDate); /* last modified */
Stream_SetU32_LE(&header[16], res->Crc32); /* CRC32 */
Stream_SetU32_LE(&header[20], res->Size); /* compressed size */
Stream_SetU32_LE(&header[24], res->Size); /* uncompressed size */
Stream_SetU32_LE(&header[16], e->Crc32); /* CRC32 */
Stream_SetU32_LE(&header[20], e->Size); /* compressed size */
Stream_SetU32_LE(&header[24], e->Size); /* uncompressed size */
Stream_SetU16_LE(&header[28], name.length); /* name length */
Stream_SetU16_LE(&header[30], 0); /* extra field length */
@ -224,7 +224,7 @@ static ReturnCode ZipPatcher_CentralDir(struct Stream* s, struct ResourceTexture
Stream_SetU16_LE(&header[34], 0); /* disk number */
Stream_SetU16_LE(&header[36], 0); /* internal attributes */
Stream_SetU32_LE(&header[38], 0); /* external attributes */
Stream_SetU32_LE(&header[42], res->Offset); /* local header offset */
Stream_SetU32_LE(&header[42], e->Offset); /* local header offset */
Mem_Copy(&header[46], name.buffer, name.length);
return Stream_Write(s, header, 46 + name.length);

View File

@ -561,7 +561,7 @@ static void ServerConnection_Init(void) {
Gfx_LostContextFunction = ServerConnection.Tick;
ScheduledTask_Add(GAME_NET_TICKS, ServerConnection.Tick);
String_AppendConst(&ServerConnection_AppName, PROGRAM_APP_NAME);
String_AppendConst(&ServerConnection_AppName, GAME_APP_NAME);
}
static void ServerConnection_Free(void) {