static int sc_decompress_zlib_alloc(u8** out, size_t* outLen, const u8* in, size_t inLen, int gzip) { /* Since uncompress does not offer a way to make it uncompress gzip... manually set it up */ z_stream gz; int err; int window_size = 15; const int startSize = inLen < 1024 ? 2048 : inLen * 2; const int blockSize = inLen < 1024 ? 512 : inLen / 2; int bufferSize = startSize; if(gzip) window_size += 0x20; memset(&gz, 0, sizeof(gz)); gz.next_in = (u8*)in; gz.avail_in = inLen; err = inflateInit2(&gz, window_size); if(err != Z_OK) return zerr_to_opensc(err); *outLen = 0; while(1) { /* Setup buffer... */ int num; u8* buf = realloc(*out, bufferSize); if(!buf) { if(*out) free(*out); *out = NULL; return Z_MEM_ERROR; } *out = buf; gz.next_out = buf + *outLen; gz.avail_out = bufferSize - *outLen; err = inflate(&gz, Z_FULL_FLUSH); if(err != Z_STREAM_END && err != Z_OK) { if(*out) free(*out); *out = NULL; break; } num = bufferSize - *outLen - gz.avail_out; if(num > 0) { *outLen += num; bufferSize += num + blockSize; } if(err == Z_STREAM_END) { buf = realloc(buf, *outLen); /* Shrink it down, if it fails, just use old data */ if(buf) { *out = buf; } break; } } inflateEnd(&gz); return zerr_to_opensc(err); }
static int sc_decompress_gzip(u8* out, size_t* outLen, const u8* in, size_t inLen) { /* Since uncompress does not offer a way to make it uncompress gzip... manually set it up */ z_stream gz; int err; int window_size = 15 + 0x20; memset(&gz, 0, sizeof(gz)); gz.next_in = (u8*)in; gz.avail_in = inLen; gz.next_out = out; gz.avail_out = *outLen; err = inflateInit2(&gz, window_size); if(err != Z_OK) return zerr_to_opensc(err); err = inflate(&gz, Z_FINISH); if(err != Z_STREAM_END) { inflateEnd(&gz); return zerr_to_opensc(err); } *outLen = gz.total_out; err = inflateEnd(&gz); return zerr_to_opensc(err); }
static int sc_compress_gzip(u8* out, size_t* outLen, const u8* in, size_t inLen) { /* Since compress does not offer a way to make it compress gzip... manually set it up */ z_stream gz; int err; int window_size = 15 + 0x10; memset(&gz, 0, sizeof(gz)); gz.next_in = (u8*)in; gz.avail_in = inLen; gz.next_out = out; gz.avail_out = *outLen; err = deflateInit2(&gz, Z_BEST_COMPRESSION, Z_DEFLATED, window_size, 9, Z_DEFAULT_STRATEGY); if(err != Z_OK) return zerr_to_opensc(err); err = deflate(&gz, Z_FINISH); if(err != Z_STREAM_END) { deflateEnd(&gz); return zerr_to_opensc(err); } *outLen = gz.total_out; err = deflateEnd(&gz); return zerr_to_opensc(err); }
int sc_compress(u8* out, size_t* outLen, const u8* in, size_t inLen, int method) { unsigned long zlib_outlen; int rc; switch(method) { case COMPRESSION_ZLIB: zlib_outlen = *outLen; rc = zerr_to_opensc(compress(out, &zlib_outlen, in, inLen)); *outLen = zlib_outlen; return rc; case COMPRESSION_GZIP: return sc_compress_gzip(out, outLen, in, inLen); default: return SC_ERROR_INVALID_ARGUMENTS; } }
int sc_decompress(u8* out, size_t* outLen, const u8* in, size_t inLen, int method) { unsigned long zlib_outlen; int rc; if(method == COMPRESSION_AUTO) { method = detect_method(in, inLen); if(method == COMPRESSION_UNKNOWN) { return SC_ERROR_UNKNOWN_DATA_RECEIVED; } } switch(method) { case COMPRESSION_ZLIB: zlib_outlen = *outLen; rc = zerr_to_opensc(uncompress(out, &zlib_outlen, in, inLen)); *outLen = zlib_outlen; return rc; case COMPRESSION_GZIP: return sc_decompress_gzip(out, outLen, in, inLen); default: return SC_ERROR_INVALID_ARGUMENTS; } }