diff options
Diffstat (limited to 'Src/Wasabi/api/filereader')
-rw-r--r-- | Src/Wasabi/api/filereader/api_filereader.cpp | 20 | ||||
-rw-r--r-- | Src/Wasabi/api/filereader/api_filereader.h | 104 | ||||
-rw-r--r-- | Src/Wasabi/api/filereader/api_readercallback.h | 22 | ||||
-rw-r--r-- | Src/Wasabi/api/filereader/filereaderapi.cpp | 53 | ||||
-rw-r--r-- | Src/Wasabi/api/filereader/filereaderapi.h | 25 | ||||
-rw-r--r-- | Src/Wasabi/api/filereader/local/fileread.cpp | 132 | ||||
-rw-r--r-- | Src/Wasabi/api/filereader/local/fileread.h | 23 | ||||
-rw-r--r-- | Src/Wasabi/api/filereader/svc_filereadI.h | 100 | ||||
-rw-r--r-- | Src/Wasabi/api/filereader/zip/zipread.cpp | 176 | ||||
-rw-r--r-- | Src/Wasabi/api/filereader/zip/zipread.h | 39 |
10 files changed, 694 insertions, 0 deletions
diff --git a/Src/Wasabi/api/filereader/api_filereader.cpp b/Src/Wasabi/api/filereader/api_filereader.cpp new file mode 100644 index 00000000..50b558b8 --- /dev/null +++ b/Src/Wasabi/api/filereader/api_filereader.cpp @@ -0,0 +1,20 @@ +#include <precomp.h> +#include "api_filereader.h" + +#ifdef CBCLASS +#undef CBCLASS +#endif +#define CBCLASS api_fileReaderI +START_DISPATCH; + CB(API_FILEREADER_FILEOPEN, fileOpen); + VCB(API_FILEREADER_FILECLOSE, fileClose); + CB(API_FILEREADER_FILEREAD, fileRead); + CB(API_FILEREADER_FILEWRITE, fileWrite); + CB(API_FILEREADER_FILESEEK, fileSeek); + CB(API_FILEREADER_FILETELL, fileTell); + CB(API_FILEREADER_FILEGETFILESIZE, fileGetFileSize); +// CB(API_FILEREADER_FILEEXISTS, fileExists); + CB(API_FILEREADER_FILEREMOVE, fileRemove); + CB(API_FILEREADER_FILEREMOVEUNDOABLE, fileRemoveUndoable); + CB(API_FILEREADER_FILEMOVE, fileMove); +END_DISPATCH; diff --git a/Src/Wasabi/api/filereader/api_filereader.h b/Src/Wasabi/api/filereader/api_filereader.h new file mode 100644 index 00000000..427c276f --- /dev/null +++ b/Src/Wasabi/api/filereader/api_filereader.h @@ -0,0 +1,104 @@ +#ifndef __API_FILEREADER_H +#define __API_FILEREADER_H + +#include <bfc/dispatch.h> + +class NOVTABLE api_fileReader : public Dispatchable +{ + public: + void *fileOpen(const wchar_t *filename, OSFNCSTR mode); + void fileClose(void *fileHandle); + size_t fileRead(void *buffer, size_t size, void *fileHandle); + size_t fileWrite(const void *buffer, int size, void *fileHandle); + int fileSeek(int64_t offset, int origin, void *fileHandle); + uint64_t fileTell(void *fileHandle); + uint64_t fileGetFileSize(void *fileHandle); + //int fileExists(const wchar_t *filename); + int fileRemove(const wchar_t *filename); + int fileRemoveUndoable(const wchar_t *filename); + int fileMove(const wchar_t *filename, const wchar_t *destfilename); + + enum { + API_FILEREADER_FILEOPEN = 0, + API_FILEREADER_FILECLOSE = 10, + API_FILEREADER_FILEREAD = 20, + API_FILEREADER_FILEWRITE = 30, + API_FILEREADER_FILESEEK = 40, + API_FILEREADER_FILETELL = 50, + API_FILEREADER_FILEGETFILESIZE = 60, + //API_FILEREADER_FILEEXISTS = 70, + API_FILEREADER_FILEREMOVE = 80, + API_FILEREADER_FILEREMOVEUNDOABLE = 90, + API_FILEREADER_FILEMOVE = 100, + }; +}; + +inline void *api_fileReader::fileOpen(const wchar_t *filename, OSFNCSTR mode) { + return _call(API_FILEREADER_FILEOPEN, (void *)NULL, filename, mode); +} + +inline void api_fileReader::fileClose(void *fileHandle) { + _voidcall(API_FILEREADER_FILECLOSE, fileHandle); +} + +inline size_t api_fileReader::fileRead(void *buffer, size_t size, void *fileHandle) { + return _call(API_FILEREADER_FILEREAD, (size_t)0, buffer, size, fileHandle); +} + +inline size_t api_fileReader::fileWrite(const void *buffer, int size, void *fileHandle) { + return _call(API_FILEREADER_FILEWRITE, (size_t)0, buffer, size, fileHandle); +} + +inline int api_fileReader::fileSeek(int64_t offset, int origin, void *fileHandle) { + return _call(API_FILEREADER_FILESEEK, (int)0, offset, origin, fileHandle); +} + +inline uint64_t api_fileReader::fileTell(void *fileHandle) { + return _call(API_FILEREADER_FILETELL, (uint64_t)0, fileHandle); +} + +inline uint64_t api_fileReader::fileGetFileSize(void *fileHandle) { + return _call(API_FILEREADER_FILEGETFILESIZE, (uint64_t)0, fileHandle); +} + +/*inline int api_fileReader::fileExists(const wchar_t *filename) { + return _call(API_FILEREADER_FILEEXISTS, (int)0, filename); +}*/ + +inline int api_fileReader::fileRemove(const wchar_t *filename) { + return _call(API_FILEREADER_FILEREMOVE, (int)0, filename); +} + +inline int api_fileReader::fileRemoveUndoable(const wchar_t *filename) { + return _call(API_FILEREADER_FILEREMOVEUNDOABLE, (int)0, filename); +} + +inline int api_fileReader::fileMove(const wchar_t *filename, const wchar_t *destfilename) { + return _call(API_FILEREADER_FILEMOVE, (int)0, filename, destfilename); +} + +class api_fileReaderI : public api_fileReader { + public: + virtual void *fileOpen(const wchar_t *filename, const wchar_t *mode)=0; + virtual void fileClose(void *fileHandle)=0; + virtual size_t fileRead(void *buffer, size_t size, void *fileHandle)=0; + virtual int fileWrite(const void *buffer, int size, void *fileHandle)=0; + virtual int fileSeek(int64_t offset, int origin, void *fileHandle)=0; + virtual uint64_t fileTell(void *fileHandle)=0; + virtual uint64_t fileGetFileSize(void *fileHandle)=0; + //virtual int fileExists(const wchar_t *filename)=0; + virtual int fileRemove(const wchar_t *filename)=0; + virtual int fileRemoveUndoable(const wchar_t *filename)=0; + virtual int fileMove(const wchar_t *filename, const wchar_t *destfilename)=0; + + protected: + RECVS_DISPATCH; +}; + +// {E357E736-4967-4279-B948-5073A186F565} +static const GUID fileReaderApiServiceGuid = +{ 0xe357e736, 0x4967, 0x4279, { 0xb9, 0x48, 0x50, 0x73, 0xa1, 0x86, 0xf5, 0x65 } }; + +extern api_fileReader *fileApi; + +#endif diff --git a/Src/Wasabi/api/filereader/api_readercallback.h b/Src/Wasabi/api/filereader/api_readercallback.h new file mode 100644 index 00000000..8d88a440 --- /dev/null +++ b/Src/Wasabi/api/filereader/api_readercallback.h @@ -0,0 +1,22 @@ +#ifndef __WASABI_API_READERCALLBACK_H +#define __WASABI_API_READERCALLBACK_H + +#include <bfc/dispatch.h> + +class NOVTABLE api_readercallback : public Dispatchable +{ +public: + void metaDataReader_onData(const char *data, int size); + + enum + { + METADATAREADERONDATA = 10, + }; +}; + +inline void api_readercallback::metaDataReader_onData(const char *data, int size) +{ + _voidcall(METADATAREADERONDATA, data, size); +} + +#endif diff --git a/Src/Wasabi/api/filereader/filereaderapi.cpp b/Src/Wasabi/api/filereader/filereaderapi.cpp new file mode 100644 index 00000000..b6fec99c --- /dev/null +++ b/Src/Wasabi/api/filereader/filereaderapi.cpp @@ -0,0 +1,53 @@ +#include <precomp.h> +#include "filereaderapi.h" +#include <api/filereader/local/fileread.h> + +api_fileReader *fileApi = NULL; + + +FileReaderApi::FileReaderApi() { +} + +FileReaderApi::~FileReaderApi() { +} + +void *FileReaderApi::fileOpen(const wchar_t *filename, const wchar_t *mode) { + return FileReaders::open(filename, mode); +} + +void FileReaderApi::fileClose(void *fileHandle) { + FileReaders::close(fileHandle); +} + +size_t FileReaderApi::fileRead(void *buffer, size_t size, void *fileHandle) { + return FileReaders::read(buffer, size, fileHandle); +} + +int FileReaderApi::fileWrite(const void *buffer, int size, void *fileHandle) { + return FileReaders::write(buffer, size, fileHandle); +} + +int FileReaderApi::fileSeek(int64_t offset, int origin, void *fileHandle) { + return FileReaders::seek(offset, origin, fileHandle); +} + +uint64_t FileReaderApi::fileTell(void *fileHandle) { + return FileReaders::tell(fileHandle); +} + +uint64_t FileReaderApi::fileGetFileSize(void *fileHandle) { + return FileReaders::getFileSize(fileHandle); +} + +int FileReaderApi::fileRemove(const wchar_t *filename) { + return FileReaders::remove(filename); +} + +int FileReaderApi::fileRemoveUndoable(const wchar_t *filename) { + return FileReaders::removeUndoable(filename); +} + +int FileReaderApi::fileMove(const wchar_t *filename, const wchar_t *destfilename) { + return FileReaders::move(filename, destfilename); +} + diff --git a/Src/Wasabi/api/filereader/filereaderapi.h b/Src/Wasabi/api/filereader/filereaderapi.h new file mode 100644 index 00000000..ad3e30a0 --- /dev/null +++ b/Src/Wasabi/api/filereader/filereaderapi.h @@ -0,0 +1,25 @@ +#ifndef _FILEREADERAPI_H +#define _FILEREADERAPI_H + +#include <api/filereader/api_filereader.h> + +class FileReaderApi : public api_fileReaderI +{ + public: + FileReaderApi(); + virtual ~FileReaderApi(); + + virtual void *fileOpen(const wchar_t *filename, const wchar_t *mode); + virtual void fileClose(void *fileHandle); + virtual size_t fileRead(void *buffer, size_t size, void *fileHandle); + virtual int fileWrite(const void *buffer, int size, void *fileHandle); + virtual int fileSeek(int64_t offset, int origin, void *fileHandle); + virtual uint64_t fileTell(void *fileHandle); + virtual uint64_t fileGetFileSize(void *fileHandle); + //virtual int fileExists(const wchar_t *filename); + virtual int fileRemove(const wchar_t *filename); + virtual int fileRemoveUndoable(const wchar_t *filename); + virtual int fileMove(const wchar_t *filename, const wchar_t *destfilename); +}; + +#endif diff --git a/Src/Wasabi/api/filereader/local/fileread.cpp b/Src/Wasabi/api/filereader/local/fileread.cpp new file mode 100644 index 00000000..f1107f47 --- /dev/null +++ b/Src/Wasabi/api/filereader/local/fileread.cpp @@ -0,0 +1,132 @@ +#include <precomp.h> +#include "fileread.h" +#include <api/service/svc_enum.h> + +void *FileReaders::open(const wchar_t *filename, const wchar_t *mode) { + int m=0; + + const wchar_t *p=mode; + wchar_t c; + while(c=*(p++)) + { + switch(c) + { + case 'r': m=SvcFileReader::READ; break; + case 'w': m=SvcFileReader::WRITE; break; + case 'a': m=SvcFileReader::APPEND; break; + case '+': m|=SvcFileReader::PLUS; break; + case 'b': m|=SvcFileReader::BINARY; break; + case 't': m|=SvcFileReader::TEXT; break; + } + } + + return FileReaderEnum(filename, m).getFirst(); +} + +void FileReaders::close(void *handle) +{ + svc_fileReader *fr=(svc_fileReader *)handle; + fr->close(); + SvcEnum::release(fr); +} + +size_t FileReaders::read(void *buffer, size_t size, void *handle) +{ + svc_fileReader *fr=(svc_fileReader *)handle; + return fr->read((int8_t *)buffer,size); +} + +size_t FileReaders::write(const void *buffer, size_t size, void *handle) +{ + svc_fileReader *fr=(svc_fileReader *)handle; + return fr->write((int8_t *)buffer,size); +} + +int FileReaders::seek(int64_t offset, int origin, void *handle) +{ + svc_fileReader *fr=(svc_fileReader *)handle; + if(!fr->canSeek()) return -1; + if(origin==SEEK_SET) return fr->seek(offset); + if(origin==SEEK_CUR) return fr->seek(fr->getPos()+offset); + return fr->seek(fr->getLength()-offset); +} + +uint64_t FileReaders::tell(void *handle) +{ + svc_fileReader *fr=(svc_fileReader *)handle; + return fr->getPos(); +} + +uint64_t FileReaders::getFileSize(void *handle) +{ + svc_fileReader *fr=(svc_fileReader *)handle; + return fr->getLength(); +} + +int FileReaders::exists(const wchar_t *filename) { + // Note that we do not do a system lock on the service since we can just + // release it directly via the factory + waService *s; + for(int i=0;s=WASABI_API_SVC->service_enumService(WaSvc::FILEREADER,i);i++) { + svc_fileReader *fr=(svc_fileReader *)s->getInterface(FALSE); + if(fr->isMine(filename) == 1 || fr->open(filename)) { + int ret=fr->exists(filename); + fr->close(); + s->releaseInterface(fr); fr = NULL; + return ret; + } + s->releaseInterface(fr); fr = NULL; + } + return 0; +} + +int FileReaders::remove(const wchar_t *filename) { + // Note that we do not do a system lock on the service since we can just + // release it directly via the factory + waService *s; + for(int i=0;s=WASABI_API_SVC->service_enumService(WaSvc::FILEREADER,i);i++) { + svc_fileReader *fr=(svc_fileReader *)s->getInterface(FALSE); + if (fr->isMine(filename) == 1 || fr->open(filename)) { + fr->close(); + int ret = fr->remove(filename); + s->releaseInterface(fr); fr = NULL; + return ret; + } + s->releaseInterface(fr); fr = NULL; + } + return 0; +} + +int FileReaders::removeUndoable(const wchar_t *filename) { + // Note that we do not do a system lock on the service since we can just + // release it directly via the factory + waService *s; + for(int i=0;s=WASABI_API_SVC->service_enumService(WaSvc::FILEREADER,i);i++) { + svc_fileReader *fr=(svc_fileReader *)s->getInterface(FALSE); + if(fr->isMine(filename) == 1 || fr->open(filename)) { + fr->close(); + int ret = fr->removeUndoable(filename); + s->releaseInterface(fr); fr = NULL; + return ret; + } + s->releaseInterface(fr); fr = NULL; + } + return 0; +} + +int FileReaders::move(const wchar_t *filename, const wchar_t *destfilename) { + // Note that we do not do a system lock on the service since we can just + // release it directly via the factory + waService *s; + for(int i=0;s=WASABI_API_SVC->service_enumService(WaSvc::FILEREADER,i);i++) { + svc_fileReader *fr=(svc_fileReader *)s->getInterface(FALSE); + if(fr->isMine(filename) == 1 || fr->open(filename)) { + fr->close(); + int ret = fr->move(filename,destfilename); + s->releaseInterface(fr); fr = NULL; + return ret; + } + s->releaseInterface(fr); fr = NULL; + } + return 0; +} diff --git a/Src/Wasabi/api/filereader/local/fileread.h b/Src/Wasabi/api/filereader/local/fileread.h new file mode 100644 index 00000000..14c22f46 --- /dev/null +++ b/Src/Wasabi/api/filereader/local/fileread.h @@ -0,0 +1,23 @@ +#ifndef _FILEREADERS_H +#define _FILEREADERS_H + +#include <api/filereader/svc_filereadI.h> +#include <api/service/servicei.h> + +class FileReaders +{ +public: + static void *open(const wchar_t *filename, const wchar_t *mode); + static void close(void *handle); + static size_t read(void *buffer, size_t size, void *handle); + static size_t write(const void *buffer, size_t size, void *handle); + static int seek(int64_t offset, int origin, void *handle); + static uint64_t tell(void *handle); + static uint64_t getFileSize(void *handle); + static int exists(const wchar_t *filename); + static int remove(const wchar_t *filename); + static int removeUndoable(const wchar_t *filename); + static int move(const wchar_t *filename, const wchar_t *destfilename); +}; + +#endif//_FILEREADERS_H diff --git a/Src/Wasabi/api/filereader/svc_filereadI.h b/Src/Wasabi/api/filereader/svc_filereadI.h new file mode 100644 index 00000000..27d4768b --- /dev/null +++ b/Src/Wasabi/api/filereader/svc_filereadI.h @@ -0,0 +1,100 @@ +#ifndef __WASABI_SVC_FILEREADI_H +#define __WASABI_SVC_FILEREADI_H + +#include <api/service/svcs/svc_fileread.h> +#include <api/filereader/api_readercallback.h> +// derive from this one +class NOVTABLE svc_fileReaderI : public svc_fileReader +{ +public: + virtual int isMine(const wchar_t *filename, int mode = SvcFileReader::READ) { return -1; } + virtual int open(const wchar_t *filename, int mode = SvcFileReader::READ) = 0; // return 1 on success + virtual size_t read(int8_t *buffer, size_t length) = 0; // return number of bytes read (if < length then eof) + virtual size_t write(const int8_t *buffer, size_t length) = 0; // return number of bytes written + virtual void close() = 0; //must be safe to call even when not open + + virtual int canSetEOF() { return 0; } + virtual int setEOF(uint64_t newlen) { return -1; } + + virtual void abort() { } // tells the reader to abort its current prebuffering/reader + + virtual int getLength() { return -1; } // return -1 on unknown/infinite + virtual int getPos() = 0; + + virtual int canSeek() { return 0; } + virtual int seek(uint64_t position) { return 0; } + virtual uint64_t bytesAvailable(uint64_t requested) { return requested; } + + virtual int hasHeaders() { return 0; } + virtual const char *getHeader(const char *header) { return (const char *)NULL; } + + virtual int exists(const wchar_t *filename) { return 0; } // return 1 if true, 0 if not, -1 if unknown + + virtual int remove(const wchar_t *filename) { return 0; } // return 1 on success, 0 on error + + virtual int removeUndoable(const wchar_t *filename) { return -1; } + + virtual int move(const wchar_t *filename, const wchar_t *destfilename) { return 0; } // return 1 on success, 0 on error + + virtual void setMetaDataCallback(api_readercallback *cb) { } + + virtual int canPrefetch() { return 1; } // return 1 if your reader should prefetch infos about the file in pledit + // (HTTP reader will return 0 here for instance) + +protected: + RECVS_DISPATCH; +}; + + +// derive from this one +class NOVTABLE MetaDataReaderCallbackI : public api_readercallback { +public: + virtual void metaDataReader_onData(const char *data, int size)=0; + +protected: +#undef CBCLASS +#define CBCLASS MetaDataReaderCallbackI +START_DISPATCH_INLINE; + VCB(METADATAREADERONDATA, metaDataReader_onData); +END_DISPATCH; +#undef CBCLASS +}; + +#include <api/service/svcs/svc_redir.h> +#include <bfc/std_file.h> // for WA_MAX_PATH but this needs to be in a better place + +#define MAX_FILEREADER_REDIRECT 256 + +// note: this class handles both redirection and calling open() +class FileReaderEnum : public SvcEnumT<svc_fileReader> { +public: + FileReaderEnum(const wchar_t *filename, int mode=SvcFileReader::READ, int allow_redirect=FALSE) : + fn(filename), m(mode) + { + if (allow_redirect) { + for (int done = 0, c = 0; !done && c < MAX_FILEREADER_REDIRECT; done = 1, c++) { + RedirectEnum re(fn); + svc_redirect *svc; + while ((svc = re.getNext(FALSE)) != NULL) { + wchar_t buf[WA_MAX_PATH]=L""; + if (svc->redirect(fn, L"Filename", buf, WA_MAX_PATH)) { + fn = buf; + done = 0; + } + re.getLastFactory()->releaseInterface(svc); + } + } + } + } + virtual int testService(svc_fileReader *svc) { + if (!svc->isMine(fn)) return 0; + return !!svc->open(fn, m); + } + +private: + const wchar_t *fn; + int m; +}; + + +#endif
\ No newline at end of file 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 <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 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;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;; diff --git a/Src/Wasabi/api/filereader/zip/zipread.h b/Src/Wasabi/api/filereader/zip/zipread.h new file mode 100644 index 00000000..7210e6bd --- /dev/null +++ b/Src/Wasabi/api/filereader/zip/zipread.h @@ -0,0 +1,39 @@ +#ifndef _ZIPREAD_H +#define _ZIPREAD_H + +#include <api/service/svcs/svc_fileread.h> +#include <api/service/servicei.h> +#include <bfc/memblock.h> +#include <bfc/string/string.h> +#include <bfc/ptrlist.h> +#include <bfc/tlist.h> + +class ZipRead : public svc_fileReaderI { +public: + // service + static const char *getServiceName() { return "ZIP file reader"; } + + int open(const char *filename, int mode=SvcFileReader::READ); + int read(char *buffer, int length); + int write(const char *buffer, int length) { return 0; } + void close(); + int getPos(); + int getLength(); + +private: + FILE *openInTempDir(const char *walName, const char *file); + + typedef struct { + String *name; + String *zipName; + Std::fileInfoStruct checksum; + } openedZipEntry; + + static wasabi::TList<openedZipEntry> openedZipHandles; + + String zipTmpDir; + + FILE *handle; +}; + +#endif//_ZIPREAD_H |