#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;;