| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 | #include <precomp.h>#define REAL_STDIO#include "zipread.h"#include <zlib/unzip.h>#include <bfc/parse/pathparse.h>#include <api/skin/api_skin.h>#define UNZIPBUFSIZE 65536int 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;v<pp1.getNumStrings();v++)     if (!STRCASEEQLSAFE(pp1.enumString(v), pp2.enumString(v))) return 0;  String walName = pp2.enumString(v);  String file;  for (v=v+1;v<pp2.getNumStrings();v++) {    if (!file.isempty()) file.cat(DIRCHARSTR);    file += pp2.enumString(v);  }  // is there a zip file?  String zipName;  Std::fileInfoStruct zipFi;  if(!Std::getFileInfos(zipName=StringPrintf("%s%s.wal",WASABI_API_SKIN->getSkinsPath(),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;i<openedZipHandles.getNumItems();i++) {    if(!STRICMP(openedZipHandles[i].name->getValue(), 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<char> 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::openedZipEntry> ZipRead::openedZipHandles;;
 |