From 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d Mon Sep 17 00:00:00 2001 From: Jef Date: Tue, 24 Sep 2024 14:54:57 +0200 Subject: Initial community commit --- Src/Wasabi/api/filereader/zip/zipread.cpp | 176 ++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 Src/Wasabi/api/filereader/zip/zipread.cpp (limited to 'Src/Wasabi/api/filereader/zip/zipread.cpp') diff --git a/Src/Wasabi/api/filereader/zip/zipread.cpp b/Src/Wasabi/api/filereader/zip/zipread.cpp new file mode 100644 index 00000000..f8c66c92 --- /dev/null +++ b/Src/Wasabi/api/filereader/zip/zipread.cpp @@ -0,0 +1,176 @@ +#include +#define REAL_STDIO +#include "zipread.h" +#include +#include +#include + +#define UNZIPBUFSIZE 65536 + +int ZipRead::open(const char *filename, int mode) { + unzFile f=NULL; + int success=0; + + if (WASABI_API_SKIN == NULL) return 0; + PathParser pp1(WASABI_API_SKIN->getSkinsPath()); + PathParser pp2(filename); + int v; + for (v=0;vgetSkinsPath(),walName.getValue()),&zipFi) && + !Std::getFileInfos(zipName=StringPrintf("%s%s.wsz",WASABI_API_SKIN->getSkinsPath(),walName.getValue()),&zipFi) && + !Std::getFileInfos(zipName=StringPrintf("%s%s.zip",WASABI_API_SKIN->getSkinsPath(),walName.getValue()),&zipFi)) + return 0; // zip not found + + if(zipTmpDir.isempty()) { + char tmpPath[WA_MAX_PATH]; + Std::getTempPath(sizeof(tmpPath)-1,tmpPath); + zipTmpDir=StringPrintf("%s_wa3sktmp",tmpPath); + Std::createDirectory(zipTmpDir); + } + + // check in cached opened zip dirs + int badcrc=0; + for(int i=0;igetValue(), walName)) { + if(!MEMCMP(&openedZipHandles[i].checksum,&zipFi,sizeof(zipFi))) { + // try to find it in the dezipped temp dir + handle=openInTempDir(walName,file); + if(handle) return 1; + else return 0; + } else { + // bad checksum + badcrc=1; + break; + } + } + } + + // is the dezipped dir is here? + if(!badcrc) { + StringPrintf tmpf("%s%s%s%s_wa3chksum",zipTmpDir.getValue(),DIRCHARSTR,walName.getValue(),DIRCHARSTR); + FILE *fh=fopen(tmpf,"rb"); + if(fh) { + Std::fileInfoStruct tmpFi={0,}; + fread(&tmpFi,1,sizeof(tmpFi),fh); + fclose(fh); + if(!MEMCMP(&tmpFi,&zipFi,sizeof(tmpFi))) { + // checksum correct + openedZipEntry ze={new String(walName), new String(zipName)}; + ze.checksum=tmpFi; + openedZipHandles.addItem(ze); + handle=openInTempDir(walName,file); + if(handle) return 1; + else return 0; + } + } + } + + // not found, so try to find it in a zip file + f = unzOpen(zipName); + if(!f) return 0; + + StringPrintf zDir("%s%s%s",zipTmpDir.getValue(),DIRCHARSTR,walName.getValue()); + Std::removeDirectory(zDir,1); + + // unpack the zip in temp folder + String dirmask; + unzGoToFirstFile(f); + Std::createDirectory(zDir); + do { + char filename[MAX_PATH]; + unzGetCurrentFileInfo(f,NULL,filename,sizeof(filename),NULL,0,NULL,0); + if (unzOpenCurrentFile(f) == UNZ_OK) { + int l; + dirmask.printf("%s%s%s",zDir.getValue(),DIRCHARSTR,filename); + if (Std::isDirChar(dirmask.lastChar())) { + // create dir + Std::createDirectory(dirmask); + } else { + // create file + FILE *fp = fopen(dirmask,"wb"); + if(!fp) { + String dir=dirmask; + char *p=(char *)Std::filename(dir); + if(p) { + *p=0; + Std::createDirectory(dir); + fp = fopen(dirmask,"wb"); + } + } + if (fp) { + do { + MemBlock buf(UNZIPBUFSIZE); + l=unzReadCurrentFile(f,buf.getMemory(),buf.getSizeInBytes()); + if (l > 0) fwrite(buf.getMemory(),1,l,fp); + } while (l > 0); + fclose(fp); + success=1; + } + } + if (unzCloseCurrentFile(f) == UNZ_CRCERROR) success=0; + } + } while (unzGoToNextFile(f) == UNZ_OK); + unzClose(f); + + // write the checksum file + Std::fileInfoStruct fi; + Std::getFileInfos(zipName, &fi); + FILE *fh=fopen(StringPrintf("%s%s_wa3chksum",zDir.getValue(),DIRCHARSTR),"wt"); + fwrite(&fi,1,sizeof(fi),fh); + fclose(fh); + + openedZipEntry ze={new String(walName), new String(zipName)}; + ze.checksum=fi; + openedZipHandles.addItem(ze); + + // try to find it (again) in the dezipped temp dir + handle=openInTempDir(walName,file); + if(handle) return 1; + return 0; +} + +FILE *ZipRead::openInTempDir(const char *walName, const char *file) { + StringPrintf tmpf("%s%s%s%s%s",zipTmpDir.getValue(),DIRCHARSTR,walName,DIRCHARSTR,file); + FILE *fh=fopen(tmpf,"rb"); + if(fh) return fh; + // okay maybe the file isn't in the root dir of the zip file + fh=fopen(StringPrintf("%s%s%s%s%s%s%s",zipTmpDir.getValue(),DIRCHARSTR,walName,DIRCHARSTR,walName,DIRCHARSTR,file),"rb"); + if(fh) return fh; + // definitely not here + return 0; +} + +void ZipRead::close() { + fclose(handle); +} + +int ZipRead::read(char *buffer, int size) { + return fread(buffer,1,size,handle); +} + +int ZipRead::getPos() { + return ftell(handle); +} + +int ZipRead::getLength() { + int pos=ftell(handle); + fseek(handle,0,SEEK_END); + int length=ftell(handle); + fseek(handle,pos,SEEK_SET); + return length; +} + +using namespace wasabi; + +TList ZipRead::openedZipHandles;; -- cgit