| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389 |
- #include <ctype.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <zlib.h>
- #include <unzip.h>
- #include "squirrel.h"
- #include "sqstdblobimpl.h"
- SQ_OPT_STRING_STRLEN();
- #define LZ_BUFFER_SIZE 8192
- #define LZ_MAX_ZIP_NAME_SIZE 256
- #define ZIP_DOS_DIR_ATTRIBUTE_BITFLAG 0x10
- static const SQChar sq_minizip_unzip_TAG[] = _SC("sq_minizip_unzip_tag");
- #define GET_minizip_unzip_INSTANCE_VAR_AT(idx, Var) \
- SQ_GET_INSTANCE_VAR(v, idx, unzFile, Var, sq_minizip_unzip_TAG);\
- if(!Var) return sq_throwerror(v, _SC("miniz_ziparchive already destroyed"));
- #define GET_minizip_unzip_INSTANCE() GET_minizip_unzip_INSTANCE_VAR_AT(1, self)
- static SQRESULT sq_minizip_unzip_releasehook(SQUserPointer p, SQInteger size, void */*ep*/)
- {
- unzFile self = ((unzFile)p);
- if(self) {
- unzClose(self);
- }
- return 0;
- }
- static SQRESULT sq_minizip_unzip_constructor(HSQUIRRELVM v)
- {
- SQ_FUNC_VARS_NO_TOP(v);
- SQ_GET_STRING(v, 2, zip_fname);
- unzFile zip_archive = unzOpen64(zip_fname);
- if(!zip_archive)
- {
- return sq_throwerror(v, _SC("Cannot open %s\n"),zip_fname);
- }
- sq_setinstanceup(v, 1, zip_archive);
- sq_setreleasehook(v,1, sq_minizip_unzip_releasehook);
- return 1;
- }
- static SQRESULT sq_minizip_unzip_get_num_files(HSQUIRRELVM v)
- {
- SQ_FUNC_VARS_NO_TOP(v);
- GET_minizip_unzip_INSTANCE();
- unz_global_info64 gi;
- int err = unzGetGlobalInfo64(self,&gi);
- if(err != UNZ_OK)
- {
- return sq_throwerror(v, _SC("error %d with zipfile in unzGetGlobalInfo \n"), err);
- }
- sq_pushinteger(v, gi.number_entry);
- return 1;
- }
- static SQRESULT sq_minizip_unzip_locate_file(HSQUIRRELVM v)
- {
- SQ_FUNC_VARS(v);
- GET_minizip_unzip_INSTANCE();
- SQ_GET_STRING(v, 2, fname);
- SQ_OPT_BOOL(v, 3, iCaseSensitivity, false);
- sq_pushbool(v, unzLocateFile(self, fname, iCaseSensitivity) == UNZ_OK);
- return 1;
- }
- static SQRESULT sq_minizip_unzip_goto_first_file(HSQUIRRELVM v)
- {
- SQ_FUNC_VARS_NO_TOP(v);
- GET_minizip_unzip_INSTANCE();
- sq_pushbool(v, unzGoToFirstFile(self) == UNZ_OK);
- return 1;
- }
- static SQRESULT sq_minizip_unzip_goto_next_file(HSQUIRRELVM v)
- {
- SQ_FUNC_VARS_NO_TOP(v);
- GET_minizip_unzip_INSTANCE();
- sq_pushbool(v, unzGoToNextFile(self) == UNZ_OK);
- return 1;
- }
- static SQRESULT sq_minizip_unzip_get_file_info(HSQUIRRELVM v)
- {
- SQ_FUNC_VARS_NO_TOP(v);
- GET_minizip_unzip_INSTANCE();
- char filename_inzip[LZ_MAX_ZIP_NAME_SIZE];
- unz_file_info64 file_info;
- int err = unzGetCurrentFileInfo64(self,&file_info,filename_inzip,LZ_MAX_ZIP_NAME_SIZE,NULL,0,NULL,0);
- if (err!=UNZ_OK)
- {
- return sq_throwerror(v, _SC("error %d with zipfile in unzGetCurrentFileInfo\n"),err);
- }
- sq_newtable(v);
- sq_pushliteral(v, "name");
- sq_pushstring(v, filename_inzip, -1);
- sq_rawset(v, -3);
- sq_pushliteral(v, "size");
- sq_pushinteger(v, file_info.uncompressed_size);
- sq_rawset(v, -3);
- sq_pushliteral(v, "is_dir");
- sq_pushbool(v, file_info.external_fa & ZIP_DOS_DIR_ATTRIBUTE_BITFLAG);
- sq_rawset(v, -3);
- return 1;
- }
- static SQRESULT sq_minizip_unzip_extract_file(HSQUIRRELVM v)
- {
- SQ_FUNC_VARS_NO_TOP(v);
- GET_minizip_unzip_INSTANCE();
- int err = unzOpenCurrentFile(self);
- if (err!=UNZ_OK)
- {
- return sq_throwerror(v, _SC("error %d with zipfile in unzGetCurrentFileInfo\n"), err);
- }
- SQBlob b(0, 8192);
- char buf[8192];
- uInt size_buf = sizeof(buf);
- do
- {
- err = unzReadCurrentFile(self,buf,size_buf);
- if (err<0)
- {
- return sq_throwerror(v, _SC("error %d with zipfile in unzReadCurrentFile\n"), err);
- }
- if (err>0)
- {
- b.Write(buf, err);
- }
- }
- while (err>0);
- err = unzCloseCurrentFile(self);
- sq_pushstring(v, (SQChar*)b.GetBuf(), b.Len());
- return 1;
- }
- static SQRESULT sq_minizip_unzip_destroy(HSQUIRRELVM v)
- {
- SQ_FUNC_VARS_NO_TOP(v);
- GET_minizip_unzip_INSTANCE();
- int rc = sq_minizip_unzip_releasehook(self, 0, v);
- if(rc == 0) sq_setinstanceup(v, 1, 0);
- sq_pushinteger(v, rc);
- return 1;
- }
- #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name), sq_minizip_unzip_##name,nparams,tycheck}
- static SQRegFunction sq_minizip_unzip_methods[] =
- {
- _DECL_FUNC(constructor, 2, _SC("xs")),
- _DECL_FUNC(get_num_files, 1, _SC("x")),
- _DECL_FUNC(locate_file, -2, _SC("xsb")),
- _DECL_FUNC(goto_first_file, 1, _SC("x")),
- _DECL_FUNC(goto_next_file, 1, _SC("x")),
- _DECL_FUNC(get_file_info, 1, _SC("x")),
- _DECL_FUNC(extract_file, 1, _SC("x")),
- _DECL_FUNC(destroy, 1, _SC("x")),
- {0,0}
- };
- #undef _DECL_FUNC
- #if 0
- static const SQChar sq_minizip_unzip_TAG[] = _SC("sq_minizip_zip_tag");
- #define GET_minizip_zip_INSTANCE_VAR_AT(idx, Var) \
- SQ_GET_INSTANCE_VAR(v, idx, zipFile, Var, sq_minizip_zip_TAG);\
- if(!Var) return sq_throwerror(v, _SC("miniz_ziparchive already destroyed"));
- #define GET_minizip_zip_INSTANCE() GET_minizip_zip_INSTANCE_VAR_AT(1, self)
- static SQRESULT sq_minizip_zip_releasehook(SQUserPointer p, SQInteger size, void */*ep*/)
- {
- zipFile self = ((zipFile)p);
- if(self) {
- zipClose(self);
- }
- return 0;
- }
- static SQRESULT sq_minizip_zip_constructor(HSQUIRRELVM v)
- {
- SQ_FUNC_VARS_NO_TOP(v);
- SQ_GET_STRING(v, 2, zip_fname);
- SQ_GET_INTEGER(v, 3, append);
- zipFile zip_archive = zipOpen64(zip_fname, append);
- if(!zip_archive)
- {
- return sq_throwerror(v, _SC("Cannot open %s\n"),zip_fname);
- }
- sq_setinstanceup(v, 1, zip_archive);
- sq_setreleasehook(v,1, sq_minizip_zip_releasehook);
- return 1;
- }
- static SQRESULT sq_minizip_zip_destroy(HSQUIRRELVM v)
- {
- SQ_FUNC_VARS_NO_TOP(v);
- GET_minizip_zip_INSTANCE();
- int rc = sq_minizip_zip_releasehook(self, 0, v);
- if(rc == 0) sq_setinstanceup(v, 1, 0);
- sq_pushinteger(v, rc);
- return 1;
- }
- #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name), sq_minizip_zip_##name,nparams,tycheck}
- static SQRegFunction sq_minizip_zip_methods[] =
- {
- _DECL_FUNC(constructor, 3, _SC("xsi")),
- _DECL_FUNC(new_file, 3, _SC("xss")),
- _DECL_FUNC(destroy, 1, _SC("x")),
- {0,0}
- };
- #undef _DECL_FUNC
- #endif
- static SQRESULT sq_check_result(HSQUIRRELVM v, int result, const z_stream* stream) {
- /* Both of these are "normal" return codes: */
- if ( result == Z_OK || result == Z_STREAM_END ) return SQ_OK;
- switch ( result ) {
- case Z_NEED_DICT:
- return sq_throwerror(v, _SC("RequiresDictionary: input stream requires a dictionary to be deflated (%s)"),
- stream->msg);
- break;
- case Z_STREAM_ERROR:
- return sq_throwerror(v, _SC("InternalError: inconsistent internal zlib stream (%s)"),
- stream->msg);
- break;
- case Z_DATA_ERROR:
- return sq_throwerror(v, _SC("InvalidInput: input string does not conform to zlib format or checksum"));
- break;
- case Z_MEM_ERROR:
- return sq_throwerror(v, _SC("OutOfMemory: not enough memory (%s)"), stream->msg);
- break;
- case Z_BUF_ERROR:
- return sq_throwerror(v, _SC("InternalError: no progress possible (%s)"), stream->msg);
- break;
- case Z_VERSION_ERROR:
- return sq_throwerror(v, _SC("IncompatibleLibrary: built with version %s, but dynamically linked with version %s (%s)"),
- ZLIB_VERSION, zlibVersion(), stream->msg);
- break;
- default:
- return sq_throwerror(v, _SC("ZLibError: unknown code %d (%s)"), result, stream->msg);
- }
- return SQ_OK;
- }
- static SQRESULT sq_zlib_deflate(HSQUIRRELVM v)
- {
- SQ_FUNC_VARS(v);
- SQ_GET_STRING(v, 2, data);
- SQ_OPT_INTEGER(v, 3, level, Z_DEFAULT_COMPRESSION);
- /* Allocate the stream: */
- z_stream stream;
- stream.zalloc = Z_NULL;
- stream.zfree = Z_NULL;
- if(sq_check_result(v, deflateInit(&stream, level), &stream) != SQ_OK) return SQ_ERROR;
- SQBlob b(LZ_BUFFER_SIZE);
- /* Do the actual deflate'ing: */
- stream.next_in = (unsigned char*)data;
- stream.avail_in = data_size;
- if ( ! stream.avail_in ) {
- /* Passed empty string, make it a noop instead of erroring out. */
- sq_pushliteral(v, "");
- return 1;
- }
- int nchunks = 0;
- do {
- stream.next_out = ((unsigned char*)b.GetBuf()) + (LZ_BUFFER_SIZE * nchunks++);
- stream.avail_out = LZ_BUFFER_SIZE;
- int result = deflate(&stream, Z_FINISH);
- if (result == Z_STREAM_END )
- break;
- if (result != Z_OK)
- {
- sq_check_result(v, result, &stream);
- deflateEnd(&stream);
- return SQ_ERROR;
- }
- b.GrowBufOf(LZ_BUFFER_SIZE);
- } while ( stream.avail_out == 0 );
- SQInteger total_out = stream.total_out;
- /* Close the stream: */
- if(sq_check_result(v, deflateEnd(&stream), &stream) == SQ_ERROR) return SQ_ERROR;
- /* Need to do this before we alter the stack: */
- sq_pushstring(v, (const SQChar*)b.GetBuf(), total_out);
- return 1;
- }
- static SQRESULT sq_zlib_inflate(HSQUIRRELVM v)
- {
- SQ_FUNC_VARS(v);
- SQ_GET_STRING(v, 2, data);
- /* By default, we will do gzip header detection w/ max window size */
- SQ_OPT_INTEGER(v, 3, window_size, MAX_WBITS + 32);
- /* Allocate the stream: */
- z_stream stream;
- stream.zalloc = Z_NULL;
- stream.zfree = Z_NULL;
- if(sq_check_result(v, inflateInit2(&stream, window_size), &stream) != SQ_OK) return SQ_ERROR;
- SQBlob b(LZ_BUFFER_SIZE);
- /* Do the actual deflate'ing: */
- stream.next_in = (unsigned char*)data;
- stream.avail_in = data_size;
- if ( ! stream.avail_in ) {
- /* Passed empty string, make it a noop instead of erroring out. */
- sq_pushliteral(v, "");
- return 1;
- }
- int nchunks = 0;
- do {
- stream.next_out = ((unsigned char*)b.GetBuf()) + (LZ_BUFFER_SIZE * nchunks++);
- stream.avail_out = LZ_BUFFER_SIZE;
- int result = inflate(&stream, Z_FINISH);
- if ( Z_BUF_ERROR != result ) {
- /* Ignore Z_BUF_ERROR since that just indicates that we
- * need a larger buffer in order to proceed. Thanks to
- * Tobias Markmann for finding this bug!
- */
- if(sq_check_result(v, result, &stream) == SQ_OK) break;
- else {
- inflateEnd(&stream);
- return SQ_ERROR;
- }
- }
- b.GrowBufOf(LZ_BUFFER_SIZE);
- } while ( stream.avail_out == 0 );
- SQInteger total_out = stream.total_out;
- /* Close the stream: */
- if(sq_check_result(v, inflateEnd(&stream), &stream) == SQ_ERROR) return SQ_ERROR;
- /* Need to do this before we alter the stack: */
- sq_pushstring(v, (const SQChar*)b.GetBuf(), total_out);
- return 1;
- }
- static SQRESULT sq_zlib_version(HSQUIRRELVM v)
- {
- sq_pushstring(v, zlibVersion(), -1);
- return 1;
- }
- #ifdef __cplusplus
- extern "C" {
- #endif
- #define INT_CONST(v,num) sq_pushstring(v,_SC(#num),-1);sq_pushinteger(v,num);sq_newslot(v,-3,SQTrue);
- SQRESULT sqext_register_sq_zlib(HSQUIRRELVM v)
- {
- sq_pushliteral(v,_SC("zlib"));
- sq_newtable(v);
- INT_CONST(v, Z_DEFAULT_COMPRESSION);
- INT_CONST(v, Z_BEST_SPEED);
- INT_CONST(v, Z_BEST_COMPRESSION);
- sq_insertfunc(v, _SC("version"), sq_zlib_version, 1, _SC("."), SQTrue);
- sq_insertfunc(v, _SC("deflate"), sq_zlib_deflate, -2, _SC(".si"), SQTrue);
- sq_insertfunc(v, _SC("inflate"), sq_zlib_inflate, -2, _SC(".si"), SQTrue);
- sq_pushliteral(v,_SC("Unzip"));
- sq_newclass(v,SQFalse);
- sq_settypetag(v,-1,(void*)sq_minizip_unzip_TAG);
- sq_insert_reg_funcs(v, sq_minizip_unzip_methods);
- sq_newslot(v,-3,SQTrue);
- sq_newslot(v,-3,SQTrue); //push zlib table
- return 0;
- }
- #ifdef __cplusplus
- }
- #endif
|