aboutsummaryrefslogtreecommitdiff
path: root/Src/Wasabi/api/filereader
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Wasabi/api/filereader
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Wasabi/api/filereader')
-rw-r--r--Src/Wasabi/api/filereader/api_filereader.cpp20
-rw-r--r--Src/Wasabi/api/filereader/api_filereader.h104
-rw-r--r--Src/Wasabi/api/filereader/api_readercallback.h22
-rw-r--r--Src/Wasabi/api/filereader/filereaderapi.cpp53
-rw-r--r--Src/Wasabi/api/filereader/filereaderapi.h25
-rw-r--r--Src/Wasabi/api/filereader/local/fileread.cpp132
-rw-r--r--Src/Wasabi/api/filereader/local/fileread.h23
-rw-r--r--Src/Wasabi/api/filereader/svc_filereadI.h100
-rw-r--r--Src/Wasabi/api/filereader/zip/zipread.cpp176
-rw-r--r--Src/Wasabi/api/filereader/zip/zipread.h39
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