@@ -0,0 +1,374 @@
/* mz_strm_bzip.c -- Stream for bzip inflate/deflate
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/


#include "mz.h"
#include "mz_strm.h"
#include "mz_strm_bzip.h"

#include "bzlib.h"

/***************************************************************************/

static mz_stream_vtbl mz_stream_bzip_vtbl = {
mz_stream_bzip_open,
mz_stream_bzip_is_open,
mz_stream_bzip_read,
mz_stream_bzip_write,
mz_stream_bzip_tell,
mz_stream_bzip_seek,
mz_stream_bzip_close,
mz_stream_bzip_error,
mz_stream_bzip_create,
mz_stream_bzip_delete,
mz_stream_bzip_get_prop_int64,
mz_stream_bzip_set_prop_int64
};

/***************************************************************************/

typedef struct mz_stream_bzip_s {
mz_stream stream;
bz_stream bzstream;
int32_t mode;
int32_t error;
uint8_t buffer[INT16_MAX];
int32_t buffer_len;
int16_t stream_end;
int64_t total_in;
int64_t total_out;
int64_t max_total_in;
int8_t initialized;
int16_t level;
} mz_stream_bzip;

/***************************************************************************/

int32_t mz_stream_bzip_open(void *stream, const char *path, int32_t mode) {
mz_stream_bzip *bzip = (mz_stream_bzip *)stream;

MZ_UNUSED(path);

bzip->bzstream.bzalloc = 0;
bzip->bzstream.bzfree = 0;
bzip->bzstream.opaque = 0;
bzip->bzstream.total_in_lo32 = 0;
bzip->bzstream.total_in_hi32 = 0;
bzip->bzstream.total_out_lo32 = 0;
bzip->bzstream.total_out_hi32 = 0;

bzip->total_in = 0;
bzip->total_out = 0;

if (mode & MZ_OPEN_MODE_WRITE) {
#ifdef MZ_ZIP_NO_COMPRESSION
return MZ_SUPPORT_ERROR;
#else
bzip->bzstream.next_out = (char *)bzip->buffer;
bzip->bzstream.avail_out = sizeof(bzip->buffer);

bzip->error = BZ2_bzCompressInit(&bzip->bzstream, bzip->level, 0, 0);
#endif
} else if (mode & MZ_OPEN_MODE_READ) {
#ifdef MZ_ZIP_NO_DECOMPRESSION
return MZ_SUPPORT_ERROR;
#else
bzip->bzstream.next_in = (char *)bzip->buffer;
bzip->bzstream.avail_in = 0;

bzip->error = BZ2_bzDecompressInit(&bzip->bzstream, 0, 0);
#endif
}

if (bzip->error != BZ_OK)
return MZ_OPEN_ERROR;

bzip->initialized = 1;
bzip->stream_end = 0;
bzip->mode = mode;
return MZ_OK;
}

int32_t mz_stream_bzip_is_open(void *stream) {
mz_stream_bzip *bzip = (mz_stream_bzip *)stream;
if (bzip->initialized != 1)
return MZ_OPEN_ERROR;
return MZ_OK;
}

int32_t mz_stream_bzip_read(void *stream, void *buf, int32_t size) {
#ifdef MZ_ZIP_NO_DECOMPRESSION
MZ_UNUSED(stream);
MZ_UNUSED(buf);
MZ_UNUSED(size);
return MZ_SUPPORT_ERROR;
#else
mz_stream_bzip *bzip = (mz_stream_bzip *)stream;
uint64_t total_in_before = 0;
uint64_t total_out_before = 0;
uint64_t total_in_after = 0;
uint64_t total_out_after = 0;
int32_t total_in = 0;
int32_t total_out = 0;
int32_t in_bytes = 0;
int32_t out_bytes = 0;
int32_t bytes_to_read = sizeof(bzip->buffer);
int32_t read = 0;
int32_t err = BZ_OK;


if (bzip->stream_end)
return 0;

bzip->bzstream.next_out = (char *)buf;
bzip->bzstream.avail_out = (unsigned int)size;

do {
if (bzip->bzstream.avail_in == 0) {
if (bzip->max_total_in > 0) {
if ((int64_t)bytes_to_read > (bzip->max_total_in - bzip->total_in))
bytes_to_read = (int32_t)(bzip->max_total_in - bzip->total_in);
}

read = mz_stream_read(bzip->stream.base, bzip->buffer, bytes_to_read);

if (read < 0)
return read;

bzip->bzstream.next_in = (char *)bzip->buffer;
bzip->bzstream.avail_in = (uint32_t)read;
}

total_in_before = bzip->bzstream.avail_in;
total_out_before = bzip->bzstream.total_out_lo32 +
(((uint64_t)bzip->bzstream.total_out_hi32) << 32);

err = BZ2_bzDecompress(&bzip->bzstream);

total_in_after = bzip->bzstream.avail_in;
total_out_after = bzip->bzstream.total_out_lo32 +
(((uint64_t)bzip->bzstream.total_out_hi32) << 32);

in_bytes = (int32_t)(total_in_before - total_in_after);
out_bytes = (int32_t)(total_out_after - total_out_before);

total_in += in_bytes;
total_out += out_bytes;

bzip->total_in += in_bytes;
bzip->total_out += out_bytes;

if (err == BZ_STREAM_END) {
bzip->stream_end = 1;
break;
}
if (err != BZ_OK && err != BZ_RUN_OK) {
bzip->error = err;
break;
}
} while (bzip->bzstream.avail_out > 0);

if (bzip->error != 0)
return MZ_DATA_ERROR;

return total_out;
#endif
}

#ifndef MZ_ZIP_NO_COMPRESSION
static int32_t mz_stream_bzip_flush(void *stream) {
mz_stream_bzip *bzip = (mz_stream_bzip *)stream;
if (mz_stream_write(bzip->stream.base, bzip->buffer, bzip->buffer_len) != bzip->buffer_len)
return MZ_WRITE_ERROR;
return MZ_OK;
}

static int32_t mz_stream_bzip_compress(void *stream, int flush) {
mz_stream_bzip *bzip = (mz_stream_bzip *)stream;
uint64_t total_out_before = 0;
uint64_t total_out_after = 0;
uint32_t out_bytes = 0;
int32_t err = BZ_OK;

do {
if (bzip->bzstream.avail_out == 0) {
err = mz_stream_bzip_flush(bzip);
if (err != MZ_OK)
return err;

bzip->bzstream.avail_out = sizeof(bzip->buffer);
bzip->bzstream.next_out = (char *)bzip->buffer;

bzip->buffer_len = 0;
}

total_out_before = bzip->bzstream.total_out_lo32 +
(((uint64_t)bzip->bzstream.total_out_hi32) << 32);

err = BZ2_bzCompress(&bzip->bzstream, flush);

total_out_after = bzip->bzstream.total_out_lo32 +
(((uint64_t)bzip->bzstream.total_out_hi32) << 32);

out_bytes = (uint32_t)(total_out_after - total_out_before);

bzip->buffer_len += out_bytes;
bzip->total_out += out_bytes;

if (err == BZ_STREAM_END)
break;
if (err < 0) {
bzip->error = err;
return MZ_DATA_ERROR;
}
} while ((bzip->bzstream.avail_in > 0) || (flush == BZ_FINISH && err == BZ_FINISH_OK));

return MZ_OK;
}
#endif

int32_t mz_stream_bzip_write(void *stream, const void *buf, int32_t size) {
#ifdef MZ_ZIP_NO_COMPRESSION
MZ_UNUSED(stream);
MZ_UNUSED(buf);
MZ_UNUSED(size);
return MZ_SUPPORT_ERROR;
#else
mz_stream_bzip *bzip = (mz_stream_bzip *)stream;
int32_t err = MZ_OK;

bzip->bzstream.next_in = (char *)(intptr_t)buf;
bzip->bzstream.avail_in = (unsigned int)size;

err = mz_stream_bzip_compress(stream, BZ_RUN);
if (err != MZ_OK) {
return err;
}

bzip->total_in += size;
return size;
#endif
}

int64_t mz_stream_bzip_tell(void *stream) {
MZ_UNUSED(stream);

return MZ_TELL_ERROR;
}

int32_t mz_stream_bzip_seek(void *stream, int64_t offset, int32_t origin) {
MZ_UNUSED(stream);
MZ_UNUSED(offset);
MZ_UNUSED(origin);

return MZ_SEEK_ERROR;
}

int32_t mz_stream_bzip_close(void *stream) {
mz_stream_bzip *bzip = (mz_stream_bzip *)stream;

if (bzip->mode & MZ_OPEN_MODE_WRITE) {
#ifdef MZ_ZIP_NO_COMPRESSION
return MZ_SUPPORT_ERROR;
#else
mz_stream_bzip_compress(stream, BZ_FINISH);
mz_stream_bzip_flush(stream);

BZ2_bzCompressEnd(&bzip->bzstream);
#endif
} else if (bzip->mode & MZ_OPEN_MODE_READ) {
#ifdef MZ_ZIP_NO_DECOMPRESSION
return MZ_SUPPORT_ERROR;
#else
BZ2_bzDecompressEnd(&bzip->bzstream);
#endif
}

bzip->initialized = 0;

if (bzip->error != BZ_OK)
return MZ_CLOSE_ERROR;
return MZ_OK;
}

int32_t mz_stream_bzip_error(void *stream) {
mz_stream_bzip *bzip = (mz_stream_bzip *)stream;
return bzip->error;
}

int32_t mz_stream_bzip_get_prop_int64(void *stream, int32_t prop, int64_t *value) {
mz_stream_bzip *bzip = (mz_stream_bzip *)stream;
switch (prop) {
case MZ_STREAM_PROP_TOTAL_IN:
*value = bzip->total_in;
break;
case MZ_STREAM_PROP_TOTAL_IN_MAX:
*value = bzip->max_total_in;
break;
case MZ_STREAM_PROP_TOTAL_OUT:
*value = bzip->total_out;
break;
case MZ_STREAM_PROP_HEADER_SIZE:
*value = 0;
break;
default:
return MZ_EXIST_ERROR;
}
return MZ_OK;
}

int32_t mz_stream_bzip_set_prop_int64(void *stream, int32_t prop, int64_t value) {
mz_stream_bzip *bzip = (mz_stream_bzip *)stream;
switch (prop) {
case MZ_STREAM_PROP_COMPRESS_LEVEL:
if (value < 0)
bzip->level = 6;
else
bzip->level = (int16_t)value;
return MZ_OK;
case MZ_STREAM_PROP_TOTAL_IN_MAX:
bzip->max_total_in = value;
return MZ_OK;
}
return MZ_EXIST_ERROR;
}

void *mz_stream_bzip_create(void **stream) {
mz_stream_bzip *bzip = NULL;

bzip = (mz_stream_bzip *)MZ_ALLOC(sizeof(mz_stream_bzip));
if (bzip != NULL) {
memset(bzip, 0, sizeof(mz_stream_bzip));
bzip->stream.vtbl = &mz_stream_bzip_vtbl;
bzip->level = 6;
}
if (stream != NULL)
*stream = bzip;

return bzip;
}

void mz_stream_bzip_delete(void **stream) {
mz_stream_bzip *bzip = NULL;
if (stream == NULL)
return;
bzip = (mz_stream_bzip *)*stream;
if (bzip != NULL)
MZ_FREE(bzip);
*stream = NULL;
}

void *mz_stream_bzip_get_interface(void) {
return (void *)&mz_stream_bzip_vtbl;
}

extern void bz_internal_error(int errcode) {
MZ_UNUSED(errcode);
}
@@ -0,0 +1,45 @@
/* mz_strm_bzip.h -- Stream for bzip inflate/deflate
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/

#ifndef MZ_STREAM_BZIP_H
#define MZ_STREAM_BZIP_H

#ifdef __cplusplus
extern "C" {
#endif

/***************************************************************************/

int32_t mz_stream_bzip_open(void *stream, const char *filename, int32_t mode);
int32_t mz_stream_bzip_is_open(void *stream);
int32_t mz_stream_bzip_read(void *stream, void *buf, int32_t size);
int32_t mz_stream_bzip_write(void *stream, const void *buf, int32_t size);
int64_t mz_stream_bzip_tell(void *stream);
int32_t mz_stream_bzip_seek(void *stream, int64_t offset, int32_t origin);
int32_t mz_stream_bzip_close(void *stream);
int32_t mz_stream_bzip_error(void *stream);

int32_t mz_stream_bzip_get_prop_int64(void *stream, int32_t prop, int64_t *value);
int32_t mz_stream_bzip_set_prop_int64(void *stream, int32_t prop, int64_t value);

void* mz_stream_bzip_create(void **stream);
void mz_stream_bzip_delete(void **stream);

void* mz_stream_bzip_get_interface(void);

void bz_internal_error(int errcode);

/***************************************************************************/

#ifdef __cplusplus
}
#endif

#endif
@@ -0,0 +1,356 @@
/* mz_strm_libcomp.c -- Stream for apple compression
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/


#include "mz.h"
#include "mz_strm.h"
#include "mz_strm_libcomp.h"

#include <compression.h>

/***************************************************************************/

static mz_stream_vtbl mz_stream_libcomp_vtbl = {
mz_stream_libcomp_open,
mz_stream_libcomp_is_open,
mz_stream_libcomp_read,
mz_stream_libcomp_write,
mz_stream_libcomp_tell,
mz_stream_libcomp_seek,
mz_stream_libcomp_close,
mz_stream_libcomp_error,
mz_stream_libcomp_create,
mz_stream_libcomp_delete,
mz_stream_libcomp_get_prop_int64,
mz_stream_libcomp_set_prop_int64
};

/***************************************************************************/

typedef struct mz_stream_libcomp_s {
mz_stream stream;
compression_stream
cstream;
uint8_t buffer[INT16_MAX];
int32_t buffer_len;
int64_t total_in;
int64_t total_out;
int64_t max_total_in;
int8_t initialized;
int32_t mode;
int32_t error;
int16_t method;
} mz_stream_libcomp;

/***************************************************************************/

int32_t mz_stream_libcomp_open(void *stream, const char *path, int32_t mode) {
mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream;
int32_t err = 0;
int16_t operation = 0;
compression_algorithm algorithm = 0;

MZ_UNUSED(path);

if (libcomp->method == 0)
return MZ_PARAM_ERROR;

libcomp->total_in = 0;
libcomp->total_out = 0;

if (mode & MZ_OPEN_MODE_WRITE) {
#ifdef MZ_ZIP_NO_COMPRESSION
return MZ_SUPPORT_ERROR;
#else
operation = COMPRESSION_STREAM_ENCODE;
#endif
} else if (mode & MZ_OPEN_MODE_READ) {
#ifdef MZ_ZIP_NO_DECOMPRESSION
return MZ_SUPPORT_ERROR;
#else
operation = COMPRESSION_STREAM_DECODE;
#endif
}

if (libcomp->method == MZ_COMPRESS_METHOD_DEFLATE)
algorithm = COMPRESSION_ZLIB;
else if (libcomp->method == MZ_COMPRESS_METHOD_XZ)
algorithm = COMPRESSION_LZMA;
else
return MZ_SUPPORT_ERROR;

err = compression_stream_init(&libcomp->cstream, (compression_stream_operation)operation, algorithm);

if (err == COMPRESSION_STATUS_ERROR) {
libcomp->error = err;
return MZ_OPEN_ERROR;
}

libcomp->initialized = 1;
libcomp->mode = mode;
return MZ_OK;
}

int32_t mz_stream_libcomp_is_open(void *stream) {
mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream;
if (libcomp->initialized != 1)
return MZ_OPEN_ERROR;
return MZ_OK;
}

int32_t mz_stream_libcomp_read(void *stream, void *buf, int32_t size) {
#ifdef MZ_ZIP_NO_DECOMPRESSION
MZ_UNUSED(stream);
MZ_UNUSED(buf);
MZ_UNUSED(size);
return MZ_SUPPORT_ERROR;
#else
mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream;
uint64_t total_in_before = 0;
uint64_t total_in_after = 0;
uint64_t total_out_before = 0;
uint64_t total_out_after = 0;
int32_t total_in = 0;
int32_t total_out = 0;
int32_t in_bytes = 0;
int32_t out_bytes = 0;
int32_t bytes_to_read = sizeof(libcomp->buffer);
int32_t read = 0;
int32_t err = MZ_OK;
int16_t flags = 0;

libcomp->cstream.dst_ptr = buf;
libcomp->cstream.dst_size = (size_t)size;

do {
if (libcomp->cstream.src_size == 0) {
if (libcomp->max_total_in > 0) {
if ((int64_t)bytes_to_read > (libcomp->max_total_in - libcomp->total_in))
bytes_to_read = (int32_t)(libcomp->max_total_in - libcomp->total_in);
}

read = mz_stream_read(libcomp->stream.base, libcomp->buffer, bytes_to_read);

if (read < 0)
return read;
if (read == 0)
flags = COMPRESSION_STREAM_FINALIZE;

libcomp->cstream.src_ptr = libcomp->buffer;
libcomp->cstream.src_size = (size_t)read;
}

total_in_before = libcomp->cstream.src_size;
total_out_before = libcomp->cstream.dst_size;

err = compression_stream_process(&libcomp->cstream, flags);
if (err == COMPRESSION_STATUS_ERROR) {
libcomp->error = err;
break;
}

total_in_after = libcomp->cstream.src_size;
total_out_after = libcomp->cstream.dst_size;

in_bytes = (int32_t)(total_in_before - total_in_after);
out_bytes = (int32_t)(total_out_before - total_out_after);

total_in += in_bytes;
total_out += out_bytes;

libcomp->total_in += in_bytes;
libcomp->total_out += out_bytes;

if (err == COMPRESSION_STATUS_END)
break;
if (err != COMPRESSION_STATUS_OK) {
libcomp->error = err;
break;
}
} while (libcomp->cstream.dst_size > 0);

if (libcomp->error != 0)
return MZ_DATA_ERROR;

return total_out;
#endif
}

static int32_t mz_stream_libcomp_flush(void *stream) {
mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream;
if (mz_stream_write(libcomp->stream.base, libcomp->buffer, libcomp->buffer_len) != libcomp->buffer_len)
return MZ_WRITE_ERROR;
return MZ_OK;
}

static int32_t mz_stream_libcomp_deflate(void *stream, int flush) {
mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream;
uint64_t total_out_before = 0;
uint64_t total_out_after = 0;
uint32_t out_bytes = 0;
int32_t err = MZ_OK;


do {
if (libcomp->cstream.dst_size == 0) {
err = mz_stream_libcomp_flush(libcomp);
if (err != MZ_OK) {
libcomp->error = err;
return err;
}

libcomp->cstream.dst_size = sizeof(libcomp->buffer);
libcomp->cstream.dst_ptr = libcomp->buffer;

libcomp->buffer_len = 0;
}

total_out_before = libcomp->cstream.dst_size;
err = compression_stream_process(&libcomp->cstream, flush);
total_out_after = libcomp->cstream.dst_size;

out_bytes = (uint32_t)(total_out_before - total_out_after);

libcomp->buffer_len += out_bytes;
libcomp->total_out += out_bytes;

if (err == COMPRESSION_STATUS_END)
break;
if (err != COMPRESSION_STATUS_OK) {
libcomp->error = err;
return MZ_DATA_ERROR;
}
} while ((libcomp->cstream.src_size > 0) || (flush == COMPRESSION_STREAM_FINALIZE && err == COMPRESSION_STATUS_OK));

return MZ_OK;
}

int32_t mz_stream_libcomp_write(void *stream, const void *buf, int32_t size) {
mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream;
int32_t err = size;

#ifdef MZ_ZIP_NO_COMPRESSION
MZ_UNUSED(libcomp);
err = MZ_SUPPORT_ERROR;
#else
libcomp->cstream.src_ptr = buf;
libcomp->cstream.src_size = (size_t)size;

mz_stream_libcomp_deflate(stream, 0);

libcomp->total_in += size;
#endif
return err;
}

int64_t mz_stream_libcomp_tell(void *stream) {
MZ_UNUSED(stream);

return MZ_TELL_ERROR;
}

int32_t mz_stream_libcomp_seek(void *stream, int64_t offset, int32_t origin) {
MZ_UNUSED(stream);
MZ_UNUSED(offset);
MZ_UNUSED(origin);

return MZ_SEEK_ERROR;
}

int32_t mz_stream_libcomp_close(void *stream) {
mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream;


if (libcomp->mode & MZ_OPEN_MODE_WRITE) {
#ifdef MZ_ZIP_NO_COMPRESSION
return MZ_SUPPORT_ERROR;
#else
mz_stream_libcomp_deflate(stream, COMPRESSION_STREAM_FINALIZE);
mz_stream_libcomp_flush(stream);
#endif
} else if (libcomp->mode & MZ_OPEN_MODE_READ) {
#ifdef MZ_ZIP_NO_DECOMPRESSION
return MZ_SUPPORT_ERROR;
#endif
}

compression_stream_destroy(&libcomp->cstream);

libcomp->initialized = 0;

if (libcomp->error != MZ_OK)
return MZ_CLOSE_ERROR;
return MZ_OK;
}

int32_t mz_stream_libcomp_error(void *stream) {
mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream;
return libcomp->error;
}

int32_t mz_stream_libcomp_get_prop_int64(void *stream, int32_t prop, int64_t *value) {
mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream;
switch (prop) {
case MZ_STREAM_PROP_TOTAL_IN:
*value = libcomp->total_in;
break;
case MZ_STREAM_PROP_TOTAL_IN_MAX:
*value = libcomp->max_total_in;
break;
case MZ_STREAM_PROP_TOTAL_OUT:
*value = libcomp->total_out;
break;
case MZ_STREAM_PROP_HEADER_SIZE:
*value = 0;
break;
default:
return MZ_EXIST_ERROR;
}
return MZ_OK;
}

int32_t mz_stream_libcomp_set_prop_int64(void *stream, int32_t prop, int64_t value) {
mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream;
switch (prop) {
case MZ_STREAM_PROP_COMPRESS_METHOD:
libcomp->method = (int16_t)value;
break;
case MZ_STREAM_PROP_TOTAL_IN_MAX:
libcomp->max_total_in = value;
break;
default:
return MZ_EXIST_ERROR;
}
return MZ_OK;
}

void *mz_stream_libcomp_create(void **stream) {
mz_stream_libcomp *libcomp = NULL;

libcomp = (mz_stream_libcomp *)MZ_ALLOC(sizeof(mz_stream_libcomp));
if (libcomp != NULL) {
memset(libcomp, 0, sizeof(mz_stream_libcomp));
libcomp->stream.vtbl = &mz_stream_libcomp_vtbl;
}
if (stream != NULL)
*stream = libcomp;

return libcomp;
}

void mz_stream_libcomp_delete(void **stream) {
mz_stream_libcomp *libcomp = NULL;
if (stream == NULL)
return;
libcomp = (mz_stream_libcomp *)*stream;
if (libcomp != NULL)
MZ_FREE(libcomp);
*stream = NULL;
}
@@ -0,0 +1,45 @@
/* mz_strm_libcomp.h -- Stream for apple compression
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/

#ifndef MZ_STREAM_LIBCOMP_H
#define MZ_STREAM_LIBCOMP_H

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

/***************************************************************************/

int32_t mz_stream_libcomp_open(void *stream, const char *filename, int32_t mode);
int32_t mz_stream_libcomp_is_open(void *stream);
int32_t mz_stream_libcomp_read(void *stream, void *buf, int32_t size);
int32_t mz_stream_libcomp_write(void *stream, const void *buf, int32_t size);
int64_t mz_stream_libcomp_tell(void *stream);
int32_t mz_stream_libcomp_seek(void *stream, int64_t offset, int32_t origin);
int32_t mz_stream_libcomp_close(void *stream);
int32_t mz_stream_libcomp_error(void *stream);

int32_t mz_stream_libcomp_get_prop_int64(void *stream, int32_t prop, int64_t *value);
int32_t mz_stream_libcomp_set_prop_int64(void *stream, int32_t prop, int64_t value);

void* mz_stream_libcomp_create(void **stream);
void mz_stream_libcomp_delete(void **stream);

void* mz_stream_libcomp_get_interface(void);

/***************************************************************************/

#ifdef __cplusplus
}
#endif

#endif

Large diffs are not rendered by default.

@@ -0,0 +1,43 @@
/* mz_strm_lzma.h -- Stream for lzma inflate/deflate
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as lzma.
See the accompanying LICENSE file for the full text of the license.
*/

#ifndef MZ_STREAM_LZMA_H
#define MZ_STREAM_LZMA_H

#ifdef __cplusplus
extern "C" {
#endif

/***************************************************************************/

int32_t mz_stream_lzma_open(void *stream, const char *filename, int32_t mode);
int32_t mz_stream_lzma_is_open(void *stream);
int32_t mz_stream_lzma_read(void *stream, void *buf, int32_t size);
int32_t mz_stream_lzma_write(void *stream, const void *buf, int32_t size);
int64_t mz_stream_lzma_tell(void *stream);
int32_t mz_stream_lzma_seek(void *stream, int64_t offset, int32_t origin);
int32_t mz_stream_lzma_close(void *stream);
int32_t mz_stream_lzma_error(void *stream);

int32_t mz_stream_lzma_get_prop_int64(void *stream, int32_t prop, int64_t *value);
int32_t mz_stream_lzma_set_prop_int64(void *stream, int32_t prop, int64_t value);

void* mz_stream_lzma_create(void **stream);
void mz_stream_lzma_delete(void **stream);

void* mz_stream_lzma_get_interface(void);

/***************************************************************************/

#ifdef __cplusplus
}
#endif

#endif
@@ -0,0 +1,272 @@
/* mz_strm_mem.c -- Stream for memory access
part of the minizip-ng project
This interface is designed to access memory rather than files.
We do use a region of memory to put data in to and take it out of.
Based on Unzip ioapi.c version 0.22, May 19th, 2003
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
Copyright (C) 2003 Justin Fletcher
Copyright (C) 1998-2003 Gilles Vollant
https://www.winimage.com/zLibDll/minizip.html
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/


#include "mz.h"
#include "mz_strm.h"
#include "mz_strm_mem.h"

/***************************************************************************/

static mz_stream_vtbl mz_stream_mem_vtbl = {
mz_stream_mem_open,
mz_stream_mem_is_open,
mz_stream_mem_read,
mz_stream_mem_write,
mz_stream_mem_tell,
mz_stream_mem_seek,
mz_stream_mem_close,
mz_stream_mem_error,
mz_stream_mem_create,
mz_stream_mem_delete,
NULL,
NULL
};

/***************************************************************************/

typedef struct mz_stream_mem_s {
mz_stream stream;
int32_t mode;
uint8_t *buffer; /* Memory buffer pointer */
int32_t size; /* Size of the memory buffer */
int32_t limit; /* Furthest we've written */
int32_t position; /* Current position in the memory */
int32_t grow_size; /* Size to grow when full */
} mz_stream_mem;

/***************************************************************************/

static int32_t mz_stream_mem_set_size(void *stream, int32_t size) {
mz_stream_mem *mem = (mz_stream_mem *)stream;
int32_t new_size = size;
uint8_t *new_buf = NULL;


new_buf = (uint8_t *)MZ_ALLOC((uint32_t)new_size);
if (new_buf == NULL)
return MZ_BUF_ERROR;

if (mem->buffer) {
memcpy(new_buf, mem->buffer, mem->size);
MZ_FREE(mem->buffer);
}

mem->buffer = new_buf;
mem->size = new_size;
return MZ_OK;
}

int32_t mz_stream_mem_open(void *stream, const char *path, int32_t mode) {
mz_stream_mem *mem = (mz_stream_mem *)stream;
int32_t err = MZ_OK;

MZ_UNUSED(path);

mem->mode = mode;
mem->limit = 0;
mem->position = 0;

if (mem->mode & MZ_OPEN_MODE_CREATE)
err = mz_stream_mem_set_size(stream, mem->grow_size);
else
mem->limit = mem->size;

return err;
}

int32_t mz_stream_mem_is_open(void *stream) {
mz_stream_mem *mem = (mz_stream_mem *)stream;
if (mem->buffer == NULL)
return MZ_OPEN_ERROR;
return MZ_OK;
}

int32_t mz_stream_mem_read(void *stream, void *buf, int32_t size) {
mz_stream_mem *mem = (mz_stream_mem *)stream;

if (size > mem->size - mem->position)
size = mem->size - mem->position;
if (mem->position + size > mem->limit)
size = mem->limit - mem->position;

if (size <= 0)
return 0;

memcpy(buf, mem->buffer + mem->position, size);
mem->position += size;

return size;
}

int32_t mz_stream_mem_write(void *stream, const void *buf, int32_t size) {
mz_stream_mem *mem = (mz_stream_mem *)stream;
int32_t new_size = 0;
int32_t err = MZ_OK;

if (size == 0)
return size;

if (size > mem->size - mem->position) {
if (mem->mode & MZ_OPEN_MODE_CREATE) {
new_size = mem->size;
if (size < mem->grow_size)
new_size += mem->grow_size;
else
new_size += size;

err = mz_stream_mem_set_size(stream, new_size);
if (err != MZ_OK)
return err;
} else {
size = mem->size - mem->position;
}
}

memcpy(mem->buffer + mem->position, buf, size);

mem->position += size;
if (mem->position > mem->limit)
mem->limit = mem->position;

return size;
}

int64_t mz_stream_mem_tell(void *stream) {
mz_stream_mem *mem = (mz_stream_mem *)stream;
return mem->position;
}

int32_t mz_stream_mem_seek(void *stream, int64_t offset, int32_t origin) {
mz_stream_mem *mem = (mz_stream_mem *)stream;
int64_t new_pos = 0;
int32_t err = MZ_OK;

switch (origin) {
case MZ_SEEK_CUR:
new_pos = mem->position + offset;
break;
case MZ_SEEK_END:
new_pos = mem->limit + offset;
break;
case MZ_SEEK_SET:
new_pos = offset;
break;
default:
return MZ_SEEK_ERROR;
}

if (new_pos > mem->size) {
if ((mem->mode & MZ_OPEN_MODE_CREATE) == 0)
return MZ_SEEK_ERROR;

err = mz_stream_mem_set_size(stream, (int32_t)new_pos);
if (err != MZ_OK)
return err;
} else if (new_pos < 0) {
return MZ_SEEK_ERROR;
}

mem->position = (int32_t)new_pos;
return MZ_OK;
}

int32_t mz_stream_mem_close(void *stream) {
MZ_UNUSED(stream);

/* We never return errors */
return MZ_OK;
}

int32_t mz_stream_mem_error(void *stream) {
MZ_UNUSED(stream);

/* We never return errors */
return MZ_OK;
}

void mz_stream_mem_set_buffer(void *stream, void *buf, int32_t size) {
mz_stream_mem *mem = (mz_stream_mem *)stream;
mem->buffer = (uint8_t *)buf;
mem->size = size;
mem->limit = size;
}

int32_t mz_stream_mem_get_buffer(void *stream, const void **buf) {
return mz_stream_mem_get_buffer_at(stream, 0, buf);
}

int32_t mz_stream_mem_get_buffer_at(void *stream, int64_t position, const void **buf) {
mz_stream_mem *mem = (mz_stream_mem *)stream;
if (buf == NULL || position < 0 || mem->size < position || mem->buffer == NULL)
return MZ_SEEK_ERROR;
*buf = mem->buffer + position;
return MZ_OK;
}

int32_t mz_stream_mem_get_buffer_at_current(void *stream, const void **buf) {
mz_stream_mem *mem = (mz_stream_mem *)stream;
return mz_stream_mem_get_buffer_at(stream, mem->position, buf);
}

void mz_stream_mem_get_buffer_length(void *stream, int32_t *length) {
mz_stream_mem *mem = (mz_stream_mem *)stream;
*length = mem->limit;
}

void mz_stream_mem_set_buffer_limit(void *stream, int32_t limit) {
mz_stream_mem *mem = (mz_stream_mem *)stream;
mem->limit = limit;
}

void mz_stream_mem_set_grow_size(void *stream, int32_t grow_size) {
mz_stream_mem *mem = (mz_stream_mem *)stream;
mem->grow_size = grow_size;
}

void *mz_stream_mem_create(void **stream) {
mz_stream_mem *mem = NULL;

mem = (mz_stream_mem *)MZ_ALLOC(sizeof(mz_stream_mem));
if (mem != NULL) {
memset(mem, 0, sizeof(mz_stream_mem));
mem->stream.vtbl = &mz_stream_mem_vtbl;
mem->grow_size = 4096;
}
if (stream != NULL)
*stream = mem;

return mem;
}

void mz_stream_mem_delete(void **stream) {
mz_stream_mem *mem = NULL;
if (stream == NULL)
return;
mem = (mz_stream_mem *)*stream;
if (mem != NULL) {
if ((mem->mode & MZ_OPEN_MODE_CREATE) && (mem->buffer != NULL))
MZ_FREE(mem->buffer);
MZ_FREE(mem);
}
*stream = NULL;
}

void *mz_stream_mem_get_interface(void) {
return (void *)&mz_stream_mem_vtbl;
}
@@ -0,0 +1,48 @@
/* mz_strm_mem.h -- Stream for memory access
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/

#ifndef MZ_STREAM_MEM_H
#define MZ_STREAM_MEM_H

#ifdef __cplusplus
extern "C" {
#endif

/***************************************************************************/

int32_t mz_stream_mem_open(void *stream, const char *filename, int32_t mode);
int32_t mz_stream_mem_is_open(void *stream);
int32_t mz_stream_mem_read(void *stream, void *buf, int32_t size);
int32_t mz_stream_mem_write(void *stream, const void *buf, int32_t size);
int64_t mz_stream_mem_tell(void *stream);
int32_t mz_stream_mem_seek(void *stream, int64_t offset, int32_t origin);
int32_t mz_stream_mem_close(void *stream);
int32_t mz_stream_mem_error(void *stream);

void mz_stream_mem_set_buffer(void *stream, void *buf, int32_t size);
int32_t mz_stream_mem_get_buffer(void *stream, const void **buf);
int32_t mz_stream_mem_get_buffer_at(void *stream, int64_t position, const void **buf);
int32_t mz_stream_mem_get_buffer_at_current(void *stream, const void **buf);
void mz_stream_mem_get_buffer_length(void *stream, int32_t *length);
void mz_stream_mem_set_buffer_limit(void *stream, int32_t limit);
void mz_stream_mem_set_grow_size(void *stream, int32_t grow_size);

void* mz_stream_mem_create(void **stream);
void mz_stream_mem_delete(void **stream);

void* mz_stream_mem_get_interface(void);

/***************************************************************************/

#ifdef __cplusplus
}
#endif

#endif
@@ -0,0 +1,40 @@
/* mz_sstrm_os.h -- Stream for filesystem access
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/

#ifndef MZ_STREAM_OS_H
#define MZ_STREAM_OS_H

#ifdef __cplusplus
extern "C" {
#endif

/***************************************************************************/

int32_t mz_stream_os_open(void *stream, const char *path, int32_t mode);
int32_t mz_stream_os_is_open(void *stream);
int32_t mz_stream_os_read(void *stream, void *buf, int32_t size);
int32_t mz_stream_os_write(void *stream, const void *buf, int32_t size);
int64_t mz_stream_os_tell(void *stream);
int32_t mz_stream_os_seek(void *stream, int64_t offset, int32_t origin);
int32_t mz_stream_os_close(void *stream);
int32_t mz_stream_os_error(void *stream);

void* mz_stream_os_create(void **stream);
void mz_stream_os_delete(void **stream);

void* mz_stream_os_get_interface(void);

/***************************************************************************/

#ifdef __cplusplus
}
#endif

#endif
@@ -0,0 +1,206 @@
/* mz_strm_posix.c -- Stream for filesystem access for posix/linux
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
Modifications for Zip64 support
Copyright (C) 2009-2010 Mathias Svensson
http://result42.com
Copyright (C) 1998-2010 Gilles Vollant
https://www.winimage.com/zLibDll/minizip.html
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/


#include "mz.h"
#include "mz_strm.h"
#include "mz_strm_os.h"

#include <stdio.h> /* fopen, fread.. */
#include <errno.h>

/***************************************************************************/

#define fopen64 fopen
#ifndef MZ_FILE32_API
# ifndef NO_FSEEKO
# define ftello64 ftello
# define fseeko64 fseeko
# elif defined(_MSC_VER) && (_MSC_VER >= 1400)
# define ftello64 _ftelli64
# define fseeko64 _fseeki64
# endif
#endif
#ifndef ftello64
# define ftello64 ftell
#endif
#ifndef fseeko64
# define fseeko64 fseek
#endif

/***************************************************************************/

static mz_stream_vtbl mz_stream_os_vtbl = {
mz_stream_os_open,
mz_stream_os_is_open,
mz_stream_os_read,
mz_stream_os_write,
mz_stream_os_tell,
mz_stream_os_seek,
mz_stream_os_close,
mz_stream_os_error,
mz_stream_os_create,
mz_stream_os_delete,
NULL,
NULL
};

/***************************************************************************/

typedef struct mz_stream_posix_s {
mz_stream stream;
int32_t error;
FILE *handle;
} mz_stream_posix;

/***************************************************************************/

int32_t mz_stream_os_open(void *stream, const char *path, int32_t mode) {
mz_stream_posix *posix = (mz_stream_posix *)stream;
const char *mode_fopen = NULL;

if (path == NULL)
return MZ_PARAM_ERROR;

if ((mode & MZ_OPEN_MODE_READWRITE) == MZ_OPEN_MODE_READ)
mode_fopen = "rb";
else if (mode & MZ_OPEN_MODE_APPEND)
mode_fopen = "r+b";
else if (mode & MZ_OPEN_MODE_CREATE)
mode_fopen = "wb";
else
return MZ_OPEN_ERROR;

posix->handle = fopen64(path, mode_fopen);
if (posix->handle == NULL) {
posix->error = errno;
return MZ_OPEN_ERROR;
}

if (mode & MZ_OPEN_MODE_APPEND)
return mz_stream_os_seek(stream, 0, MZ_SEEK_END);

return MZ_OK;
}

int32_t mz_stream_os_is_open(void *stream) {
mz_stream_posix *posix = (mz_stream_posix*)stream;
if (posix->handle == NULL)
return MZ_OPEN_ERROR;
return MZ_OK;
}

int32_t mz_stream_os_read(void *stream, void *buf, int32_t size) {
mz_stream_posix *posix = (mz_stream_posix*)stream;
int32_t read = (int32_t)fread(buf, 1, (size_t)size, posix->handle);
if (read < size && ferror(posix->handle)) {
posix->error = errno;
return MZ_READ_ERROR;
}
return read;
}

int32_t mz_stream_os_write(void *stream, const void *buf, int32_t size) {
mz_stream_posix *posix = (mz_stream_posix*)stream;
int32_t written = (int32_t)fwrite(buf, 1, (size_t)size, posix->handle);
if (written < size && ferror(posix->handle)) {
posix->error = errno;
return MZ_WRITE_ERROR;
}
return written;
}

int64_t mz_stream_os_tell(void *stream) {
mz_stream_posix *posix = (mz_stream_posix*)stream;
int64_t position = ftello64(posix->handle);
if (position == -1) {
posix->error = errno;
return MZ_TELL_ERROR;
}
return position;
}

int32_t mz_stream_os_seek(void *stream, int64_t offset, int32_t origin) {
mz_stream_posix *posix = (mz_stream_posix*)stream;
int32_t fseek_origin = 0;

switch (origin) {
case MZ_SEEK_CUR:
fseek_origin = SEEK_CUR;
break;
case MZ_SEEK_END:
fseek_origin = SEEK_END;
break;
case MZ_SEEK_SET:
fseek_origin = SEEK_SET;
break;
default:
return MZ_SEEK_ERROR;
}

if (fseeko64(posix->handle, offset, fseek_origin) != 0) {
posix->error = errno;
return MZ_SEEK_ERROR;
}

return MZ_OK;
}

int32_t mz_stream_os_close(void *stream) {
mz_stream_posix *posix = (mz_stream_posix*)stream;
int32_t closed = 0;
if (posix->handle != NULL) {
closed = fclose(posix->handle);
posix->handle = NULL;
}
if (closed != 0) {
posix->error = errno;
return MZ_CLOSE_ERROR;
}
return MZ_OK;
}

int32_t mz_stream_os_error(void *stream) {
mz_stream_posix *posix = (mz_stream_posix*)stream;
return posix->error;
}

void *mz_stream_os_create(void **stream) {
mz_stream_posix *posix = NULL;

posix = (mz_stream_posix *)MZ_ALLOC(sizeof(mz_stream_posix));
if (posix != NULL) {
memset(posix, 0, sizeof(mz_stream_posix));
posix->stream.vtbl = &mz_stream_os_vtbl;
}
if (stream != NULL)
*stream = posix;

return posix;
}

void mz_stream_os_delete(void **stream) {
mz_stream_posix *posix = NULL;
if (stream == NULL)
return;
posix = (mz_stream_posix *)*stream;
if (posix != NULL)
MZ_FREE(posix);
*stream = NULL;
}

void *mz_stream_os_get_interface(void) {
return (void *)&mz_stream_os_vtbl;
}
@@ -0,0 +1,296 @@
/* mz_strm_win32.c -- Stream for filesystem access for windows
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
Copyright (C) 2009-2010 Mathias Svensson
Modifications for Zip64 support
http://result42.com
Copyright (C) 1998-2010 Gilles Vollant
https://www.winimage.com/zLibDll/minizip.html
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/


#include "mz.h"
#include "mz_os.h"
#include "mz_strm.h"
#include "mz_strm_os.h"

#include <windows.h>

/***************************************************************************/

#ifndef INVALID_HANDLE_VALUE
# define INVALID_HANDLE_VALUE (0xFFFFFFFF)
#endif

#ifndef INVALID_SET_FILE_POINTER
# define INVALID_SET_FILE_POINTER ((DWORD)-1)
#endif

#if defined(WINAPI_FAMILY_ONE_PARTITION) && !defined(MZ_WINRT_API)
# if WINAPI_FAMILY_ONE_PARTITION(WINAPI_FAMILY, WINAPI_PARTITION_APP)
# define MZ_WINRT_API 1
# endif
#endif

/***************************************************************************/

static mz_stream_vtbl mz_stream_os_vtbl = {
mz_stream_os_open,
mz_stream_os_is_open,
mz_stream_os_read,
mz_stream_os_write,
mz_stream_os_tell,
mz_stream_os_seek,
mz_stream_os_close,
mz_stream_os_error,
mz_stream_os_create,
mz_stream_os_delete,
NULL,
NULL
};

/***************************************************************************/

typedef struct mz_stream_win32_s {
mz_stream stream;
HANDLE handle;
int32_t error;
} mz_stream_win32;

/***************************************************************************/

#if 0
# define mz_stream_os_print printf
#else
# define mz_stream_os_print(fmt,...)
#endif

/***************************************************************************/

int32_t mz_stream_os_open(void *stream, const char *path, int32_t mode) {
mz_stream_win32 *win32 = (mz_stream_win32 *)stream;
uint32_t desired_access = 0;
uint32_t creation_disposition = 0;
uint32_t share_mode = FILE_SHARE_READ;
uint32_t flags_attribs = FILE_ATTRIBUTE_NORMAL;
wchar_t *path_wide = NULL;


if (path == NULL)
return MZ_PARAM_ERROR;

/* Some use cases require write sharing as well */
share_mode |= FILE_SHARE_WRITE;

if ((mode & MZ_OPEN_MODE_READWRITE) == MZ_OPEN_MODE_READ) {
desired_access = GENERIC_READ;
creation_disposition = OPEN_EXISTING;
} else if (mode & MZ_OPEN_MODE_APPEND) {
desired_access = GENERIC_WRITE | GENERIC_READ;
creation_disposition = OPEN_EXISTING;
} else if (mode & MZ_OPEN_MODE_CREATE) {
desired_access = GENERIC_WRITE | GENERIC_READ;
creation_disposition = CREATE_ALWAYS;
} else {
return MZ_PARAM_ERROR;
}

mz_stream_os_print("Win32 - Open - %s (mode %" PRId32 ")\n", path);

path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8);
if (path_wide == NULL)
return MZ_PARAM_ERROR;

#ifdef MZ_WINRT_API
win32->handle = CreateFile2(path_wide, desired_access, share_mode,
creation_disposition, NULL);
#else
win32->handle = CreateFileW(path_wide, desired_access, share_mode, NULL,
creation_disposition, flags_attribs, NULL);
#endif

mz_os_unicode_string_delete(&path_wide);

if (mz_stream_os_is_open(stream) != MZ_OK) {
win32->error = GetLastError();
return MZ_OPEN_ERROR;
}

if (mode & MZ_OPEN_MODE_APPEND)
return mz_stream_os_seek(stream, 0, MZ_SEEK_END);

return MZ_OK;
}

int32_t mz_stream_os_is_open(void *stream) {
mz_stream_win32 *win32 = (mz_stream_win32 *)stream;
if (win32->handle == NULL || win32->handle == INVALID_HANDLE_VALUE)
return MZ_OPEN_ERROR;
return MZ_OK;
}

int32_t mz_stream_os_read(void *stream, void *buf, int32_t size) {
mz_stream_win32 *win32 = (mz_stream_win32 *)stream;
uint32_t read = 0;

if (mz_stream_os_is_open(stream) != MZ_OK)
return MZ_OPEN_ERROR;

if (!ReadFile(win32->handle, buf, size, (DWORD *)&read, NULL)) {
win32->error = GetLastError();
if (win32->error == ERROR_HANDLE_EOF)
win32->error = 0;
}

mz_stream_os_print("Win32 - Read - %" PRId32 "\n", read);

return read;
}

int32_t mz_stream_os_write(void *stream, const void *buf, int32_t size) {
mz_stream_win32 *win32 = (mz_stream_win32 *)stream;
int32_t written = 0;

if (mz_stream_os_is_open(stream) != MZ_OK)
return MZ_OPEN_ERROR;

if (!WriteFile(win32->handle, buf, size, (DWORD *)&written, NULL)) {
win32->error = GetLastError();
if (win32->error == ERROR_HANDLE_EOF)
win32->error = 0;
}

mz_stream_os_print("Win32 - Write - %" PRId32 "\n", written);

return written;
}

static int32_t mz_stream_os_seekinternal(HANDLE handle, LARGE_INTEGER large_pos,
LARGE_INTEGER *new_pos, uint32_t move_method) {
#ifdef MZ_WINRT_API
BOOL success = FALSE;
success = SetFilePointerEx(handle, large_pos, new_pos, move_method);
if ((success == FALSE) && (GetLastError() != NO_ERROR))
return MZ_SEEK_ERROR;

return MZ_OK;
#else
LONG high_part = 0;
uint32_t pos = 0;

high_part = large_pos.HighPart;
pos = SetFilePointer(handle, large_pos.LowPart, &high_part, move_method);

if ((pos == INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR))
return MZ_SEEK_ERROR;

if (new_pos != NULL) {
new_pos->LowPart = pos;
new_pos->HighPart = high_part;
}

return MZ_OK;
#endif
}

int64_t mz_stream_os_tell(void *stream) {
mz_stream_win32 *win32 = (mz_stream_win32 *)stream;
LARGE_INTEGER large_pos;

if (mz_stream_os_is_open(stream) != MZ_OK)
return MZ_OPEN_ERROR;

large_pos.QuadPart = 0;

if (mz_stream_os_seekinternal(win32->handle, large_pos, &large_pos, FILE_CURRENT) != MZ_OK)
win32->error = GetLastError();

mz_stream_os_print("Win32 - Tell - %" PRId64 "\n", large_pos.QuadPart);

return large_pos.QuadPart;
}

int32_t mz_stream_os_seek(void *stream, int64_t offset, int32_t origin) {
mz_stream_win32 *win32 = (mz_stream_win32 *)stream;
uint32_t move_method = 0xFFFFFFFF;
int32_t err = MZ_OK;
LARGE_INTEGER large_pos;


if (mz_stream_os_is_open(stream) != MZ_OK)
return MZ_OPEN_ERROR;

switch (origin) {
case MZ_SEEK_CUR:
move_method = FILE_CURRENT;
break;
case MZ_SEEK_END:
move_method = FILE_END;
break;
case MZ_SEEK_SET:
move_method = FILE_BEGIN;
break;
default:
return MZ_SEEK_ERROR;
}

mz_stream_os_print("Win32 - Seek - %" PRId64 " (origin %" PRId32 ")\n", offset, origin);

large_pos.QuadPart = offset;

err = mz_stream_os_seekinternal(win32->handle, large_pos, NULL, move_method);
if (err != MZ_OK) {
win32->error = GetLastError();
return err;
}

return MZ_OK;
}

int32_t mz_stream_os_close(void *stream) {
mz_stream_win32 *win32 = (mz_stream_win32 *)stream;

if (win32->handle != NULL)
CloseHandle(win32->handle);
mz_stream_os_print("Win32 - Close\n");
win32->handle = NULL;
return MZ_OK;
}

int32_t mz_stream_os_error(void *stream) {
mz_stream_win32 *win32 = (mz_stream_win32 *)stream;
return win32->error;
}

void *mz_stream_os_create(void **stream) {
mz_stream_win32 *win32 = NULL;

win32 = (mz_stream_win32 *)MZ_ALLOC(sizeof(mz_stream_win32));
if (win32 != NULL) {
memset(win32, 0, sizeof(mz_stream_win32));
win32->stream.vtbl = &mz_stream_os_vtbl;
}
if (stream != NULL)
*stream = win32;

return win32;
}

void mz_stream_os_delete(void **stream) {
mz_stream_win32 *win32 = NULL;
if (stream == NULL)
return;
win32 = (mz_stream_win32 *)*stream;
if (win32 != NULL)
MZ_FREE(win32);
*stream = NULL;
}

void *mz_stream_os_get_interface(void) {
return (void *)&mz_stream_os_vtbl;
}
@@ -0,0 +1,338 @@
/* mz_strm_pkcrypt.c -- Code for traditional PKWARE encryption
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
Copyright (C) 1998-2005 Gilles Vollant
Modifications for Info-ZIP crypting
https://www.winimage.com/zLibDll/minizip.html
Copyright (C) 2003 Terry Thorsen
This code is a modified version of crypting code in Info-ZIP distribution
Copyright (C) 1990-2000 Info-ZIP. All rights reserved.
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
This encryption code is a direct transcription of the algorithm from
Roger Schlafly, described by Phil Katz in the file appnote.txt. This
file (appnote.txt) is distributed with the PKZIP program (even in the
version without encryption capabilities).
*/


#include "mz.h"
#include "mz_crypt.h"
#include "mz_strm.h"
#include "mz_strm_pkcrypt.h"

/***************************************************************************/

static mz_stream_vtbl mz_stream_pkcrypt_vtbl = {
mz_stream_pkcrypt_open,
mz_stream_pkcrypt_is_open,
mz_stream_pkcrypt_read,
mz_stream_pkcrypt_write,
mz_stream_pkcrypt_tell,
mz_stream_pkcrypt_seek,
mz_stream_pkcrypt_close,
mz_stream_pkcrypt_error,
mz_stream_pkcrypt_create,
mz_stream_pkcrypt_delete,
mz_stream_pkcrypt_get_prop_int64,
mz_stream_pkcrypt_set_prop_int64
};

/***************************************************************************/

typedef struct mz_stream_pkcrypt_s {
mz_stream stream;
int32_t error;
int16_t initialized;
uint8_t buffer[UINT16_MAX];
int64_t total_in;
int64_t max_total_in;
int64_t total_out;
uint32_t keys[3]; /* keys defining the pseudo-random sequence */
uint8_t verify1;
uint8_t verify2;
const char *password;
} mz_stream_pkcrypt;

/***************************************************************************/

#define mz_stream_pkcrypt_decode(strm, c) \
(mz_stream_pkcrypt_update_keys(strm, \
c ^= mz_stream_pkcrypt_decrypt_byte(strm)))

#define mz_stream_pkcrypt_encode(strm, c, t) \
(t = mz_stream_pkcrypt_decrypt_byte(strm), \
mz_stream_pkcrypt_update_keys(strm, (uint8_t)c), (uint8_t)(t^(c)))

/***************************************************************************/

static uint8_t mz_stream_pkcrypt_decrypt_byte(void *stream) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;

unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an */
/* unpredictable manner on 16-bit systems; not a problem */
/* with any known compiler so far, though. */

temp = pkcrypt->keys[2] | 2;
return (uint8_t)(((temp * (temp ^ 1)) >> 8) & 0xff);
}

static uint8_t mz_stream_pkcrypt_update_keys(void *stream, uint8_t c) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
uint8_t buf = c;

pkcrypt->keys[0] = (uint32_t)~mz_crypt_crc32_update(~pkcrypt->keys[0], &buf, 1);

pkcrypt->keys[1] += pkcrypt->keys[0] & 0xff;
pkcrypt->keys[1] *= 134775813L;
pkcrypt->keys[1] += 1;

buf = (uint8_t)(pkcrypt->keys[1] >> 24);
pkcrypt->keys[2] = (uint32_t)~mz_crypt_crc32_update(~pkcrypt->keys[2], &buf, 1);

return (uint8_t)c;
}

static void mz_stream_pkcrypt_init_keys(void *stream, const char *password) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;

pkcrypt->keys[0] = 305419896L;
pkcrypt->keys[1] = 591751049L;
pkcrypt->keys[2] = 878082192L;

while (*password != 0) {
mz_stream_pkcrypt_update_keys(stream, (uint8_t)*password);
password += 1;
}
}

/***************************************************************************/

int32_t mz_stream_pkcrypt_open(void *stream, const char *path, int32_t mode) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
uint16_t t = 0;
int16_t i = 0;
uint8_t verify1 = 0;
uint8_t verify2 = 0;
uint8_t header[MZ_PKCRYPT_HEADER_SIZE];
const char *password = path;

pkcrypt->total_in = 0;
pkcrypt->total_out = 0;
pkcrypt->initialized = 0;

if (mz_stream_is_open(pkcrypt->stream.base) != MZ_OK)
return MZ_OPEN_ERROR;

if (password == NULL)
password = pkcrypt->password;
if (password == NULL)
return MZ_PARAM_ERROR;

mz_stream_pkcrypt_init_keys(stream, password);

if (mode & MZ_OPEN_MODE_WRITE) {
/* First generate RAND_HEAD_LEN - 2 random bytes. */
mz_crypt_rand(header, MZ_PKCRYPT_HEADER_SIZE - 2);

/* Encrypt random header (last two bytes is high word of crc) */
for (i = 0; i < MZ_PKCRYPT_HEADER_SIZE - 2; i++)
header[i] = mz_stream_pkcrypt_encode(stream, header[i], t);

header[i++] = mz_stream_pkcrypt_encode(stream, pkcrypt->verify1, t);
header[i++] = mz_stream_pkcrypt_encode(stream, pkcrypt->verify2, t);

if (mz_stream_write(pkcrypt->stream.base, header, sizeof(header)) != sizeof(header))
return MZ_WRITE_ERROR;

pkcrypt->total_out += MZ_PKCRYPT_HEADER_SIZE;
} else if (mode & MZ_OPEN_MODE_READ) {
if (mz_stream_read(pkcrypt->stream.base, header, sizeof(header)) != sizeof(header))
return MZ_READ_ERROR;

for (i = 0; i < MZ_PKCRYPT_HEADER_SIZE - 2; i++)
header[i] = mz_stream_pkcrypt_decode(stream, header[i]);

verify1 = mz_stream_pkcrypt_decode(stream, header[i++]);
verify2 = mz_stream_pkcrypt_decode(stream, header[i++]);

/* Older versions used 2 byte check, newer versions use 1 byte check. */
MZ_UNUSED(verify1);
if ((verify2 != 0) && (verify2 != pkcrypt->verify2))
return MZ_PASSWORD_ERROR;

pkcrypt->total_in += MZ_PKCRYPT_HEADER_SIZE;
}

pkcrypt->initialized = 1;
return MZ_OK;
}

int32_t mz_stream_pkcrypt_is_open(void *stream) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
if (pkcrypt->initialized == 0)
return MZ_OPEN_ERROR;
return MZ_OK;
}

int32_t mz_stream_pkcrypt_read(void *stream, void *buf, int32_t size) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
uint8_t *buf_ptr = (uint8_t *)buf;
int32_t bytes_to_read = size;
int32_t read = 0;
int32_t i = 0;


if ((int64_t)bytes_to_read > (pkcrypt->max_total_in - pkcrypt->total_in))
bytes_to_read = (int32_t)(pkcrypt->max_total_in - pkcrypt->total_in);

read = mz_stream_read(pkcrypt->stream.base, buf, bytes_to_read);

for (i = 0; i < read; i++)
buf_ptr[i] = mz_stream_pkcrypt_decode(stream, buf_ptr[i]);

if (read > 0)
pkcrypt->total_in += read;

return read;
}

int32_t mz_stream_pkcrypt_write(void *stream, const void *buf, int32_t size) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
const uint8_t *buf_ptr = (const uint8_t *)buf;
int32_t bytes_to_write = sizeof(pkcrypt->buffer);
int32_t total_written = 0;
int32_t written = 0;
int32_t i = 0;
uint16_t t = 0;

if (size < 0)
return MZ_PARAM_ERROR;

do {
if (bytes_to_write > (size - total_written))
bytes_to_write = (size - total_written);

for (i = 0; i < bytes_to_write; i += 1) {
pkcrypt->buffer[i] = mz_stream_pkcrypt_encode(stream, *buf_ptr, t);
buf_ptr += 1;
}

written = mz_stream_write(pkcrypt->stream.base, pkcrypt->buffer, bytes_to_write);
if (written < 0)
return written;

total_written += written;
} while (total_written < size && written > 0);

pkcrypt->total_out += total_written;
return total_written;
}

int64_t mz_stream_pkcrypt_tell(void *stream) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
return mz_stream_tell(pkcrypt->stream.base);
}

int32_t mz_stream_pkcrypt_seek(void *stream, int64_t offset, int32_t origin) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
return mz_stream_seek(pkcrypt->stream.base, offset, origin);
}

int32_t mz_stream_pkcrypt_close(void *stream) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
pkcrypt->initialized = 0;
return MZ_OK;
}

int32_t mz_stream_pkcrypt_error(void *stream) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
return pkcrypt->error;
}

void mz_stream_pkcrypt_set_password(void *stream, const char *password) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
pkcrypt->password = password;
}

void mz_stream_pkcrypt_set_verify(void *stream, uint8_t verify1, uint8_t verify2) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
pkcrypt->verify1 = verify1;
pkcrypt->verify2 = verify2;
}

void mz_stream_pkcrypt_get_verify(void *stream, uint8_t *verify1, uint8_t *verify2) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
*verify1 = pkcrypt->verify1;
*verify2 = pkcrypt->verify2;
}

int32_t mz_stream_pkcrypt_get_prop_int64(void *stream, int32_t prop, int64_t *value) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
switch (prop) {
case MZ_STREAM_PROP_TOTAL_IN:
*value = pkcrypt->total_in;
break;
case MZ_STREAM_PROP_TOTAL_OUT:
*value = pkcrypt->total_out;
break;
case MZ_STREAM_PROP_TOTAL_IN_MAX:
*value = pkcrypt->max_total_in;
break;
case MZ_STREAM_PROP_HEADER_SIZE:
*value = MZ_PKCRYPT_HEADER_SIZE;
break;
case MZ_STREAM_PROP_FOOTER_SIZE:
*value = 0;
break;
default:
return MZ_EXIST_ERROR;
}
return MZ_OK;
}

int32_t mz_stream_pkcrypt_set_prop_int64(void *stream, int32_t prop, int64_t value) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
switch (prop) {
case MZ_STREAM_PROP_TOTAL_IN_MAX:
pkcrypt->max_total_in = value;
break;
default:
return MZ_EXIST_ERROR;
}
return MZ_OK;
}

void *mz_stream_pkcrypt_create(void **stream) {
mz_stream_pkcrypt *pkcrypt = NULL;

pkcrypt = (mz_stream_pkcrypt *)MZ_ALLOC(sizeof(mz_stream_pkcrypt));
if (pkcrypt != NULL) {
memset(pkcrypt, 0, sizeof(mz_stream_pkcrypt));
pkcrypt->stream.vtbl = &mz_stream_pkcrypt_vtbl;
}

if (stream != NULL)
*stream = pkcrypt;
return pkcrypt;
}

void mz_stream_pkcrypt_delete(void **stream) {
mz_stream_pkcrypt *pkcrypt = NULL;
if (stream == NULL)
return;
pkcrypt = (mz_stream_pkcrypt *)*stream;
if (pkcrypt != NULL)
MZ_FREE(pkcrypt);
*stream = NULL;
}

void *mz_stream_pkcrypt_get_interface(void) {
return (void *)&mz_stream_pkcrypt_vtbl;
}
@@ -0,0 +1,46 @@
/* mz_strm_pkcrypt.h -- Code for traditional PKWARE encryption
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/

#ifndef MZ_STREAM_PKCRYPT_H
#define MZ_STREAM_PKCRYPT_H

#ifdef __cplusplus
extern "C" {
#endif

/***************************************************************************/

int32_t mz_stream_pkcrypt_open(void *stream, const char *filename, int32_t mode);
int32_t mz_stream_pkcrypt_is_open(void *stream);
int32_t mz_stream_pkcrypt_read(void *stream, void *buf, int32_t size);
int32_t mz_stream_pkcrypt_write(void *stream, const void *buf, int32_t size);
int64_t mz_stream_pkcrypt_tell(void *stream);
int32_t mz_stream_pkcrypt_seek(void *stream, int64_t offset, int32_t origin);
int32_t mz_stream_pkcrypt_close(void *stream);
int32_t mz_stream_pkcrypt_error(void *stream);

void mz_stream_pkcrypt_set_password(void *stream, const char *password);
void mz_stream_pkcrypt_set_verify(void *stream, uint8_t verify1, uint8_t verify2);
void mz_stream_pkcrypt_get_verify(void *stream, uint8_t *verify1, uint8_t *verify2);
int32_t mz_stream_pkcrypt_get_prop_int64(void *stream, int32_t prop, int64_t *value);
int32_t mz_stream_pkcrypt_set_prop_int64(void *stream, int32_t prop, int64_t value);

void* mz_stream_pkcrypt_create(void **stream);
void mz_stream_pkcrypt_delete(void **stream);

void* mz_stream_pkcrypt_get_interface(void);

/***************************************************************************/

#ifdef __cplusplus
}
#endif

#endif

Large diffs are not rendered by default.

@@ -0,0 +1,43 @@
/* mz_strm_split.h -- Stream for split files
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/

#ifndef MZ_STREAM_SPLIT_H
#define MZ_STREAM_SPLIT_H

#ifdef __cplusplus
extern "C" {
#endif

/***************************************************************************/

int32_t mz_stream_split_open(void *stream, const char *filename, int32_t mode);
int32_t mz_stream_split_is_open(void *stream);
int32_t mz_stream_split_read(void *stream, void *buf, int32_t size);
int32_t mz_stream_split_write(void *stream, const void *buf, int32_t size);
int64_t mz_stream_split_tell(void *stream);
int32_t mz_stream_split_seek(void *stream, int64_t offset, int32_t origin);
int32_t mz_stream_split_close(void *stream);
int32_t mz_stream_split_error(void *stream);

int32_t mz_stream_split_get_prop_int64(void *stream, int32_t prop, int64_t *value);
int32_t mz_stream_split_set_prop_int64(void *stream, int32_t prop, int64_t value);

void* mz_stream_split_create(void **stream);
void mz_stream_split_delete(void **stream);

void* mz_stream_split_get_interface(void);

/***************************************************************************/

#ifdef __cplusplus
}
#endif

#endif
@@ -0,0 +1,362 @@
/* mz_strm_wzaes.c -- Stream for WinZip AES encryption
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
Copyright (C) 1998-2010 Brian Gladman, Worcester, UK
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/


#include "mz.h"
#include "mz_crypt.h"
#include "mz_strm.h"
#include "mz_strm_wzaes.h"

/***************************************************************************/

#define MZ_AES_KEYING_ITERATIONS (1000)
#define MZ_AES_SALT_LENGTH(MODE) (4 * (MODE & 3) + 4)
#define MZ_AES_SALT_LENGTH_MAX (16)
#define MZ_AES_PW_LENGTH_MAX (128)
#define MZ_AES_PW_VERIFY_SIZE (2)
#define MZ_AES_AUTHCODE_SIZE (10)

/***************************************************************************/

static mz_stream_vtbl mz_stream_wzaes_vtbl = {
mz_stream_wzaes_open,
mz_stream_wzaes_is_open,
mz_stream_wzaes_read,
mz_stream_wzaes_write,
mz_stream_wzaes_tell,
mz_stream_wzaes_seek,
mz_stream_wzaes_close,
mz_stream_wzaes_error,
mz_stream_wzaes_create,
mz_stream_wzaes_delete,
mz_stream_wzaes_get_prop_int64,
mz_stream_wzaes_set_prop_int64
};

/***************************************************************************/

typedef struct mz_stream_wzaes_s {
mz_stream stream;
int32_t mode;
int32_t error;
int16_t initialized;
uint8_t buffer[UINT16_MAX];
int64_t total_in;
int64_t max_total_in;
int64_t total_out;
int16_t encryption_mode;
const char *password;
void *aes;
uint32_t crypt_pos;
uint8_t crypt_block[MZ_AES_BLOCK_SIZE];
void *hmac;
uint8_t nonce[MZ_AES_BLOCK_SIZE];
} mz_stream_wzaes;

/***************************************************************************/

int32_t mz_stream_wzaes_open(void *stream, const char *path, int32_t mode) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
uint16_t salt_length = 0;
uint16_t password_length = 0;
uint16_t key_length = 0;
uint8_t kbuf[2 * MZ_AES_KEY_LENGTH_MAX + MZ_AES_PW_VERIFY_SIZE];
uint8_t verify[MZ_AES_PW_VERIFY_SIZE];
uint8_t verify_expected[MZ_AES_PW_VERIFY_SIZE];
uint8_t salt_value[MZ_AES_SALT_LENGTH_MAX];
const char *password = path;

wzaes->total_in = 0;
wzaes->total_out = 0;
wzaes->initialized = 0;

if (mz_stream_is_open(wzaes->stream.base) != MZ_OK)
return MZ_OPEN_ERROR;

if (password == NULL)
password = wzaes->password;
if (password == NULL)
return MZ_PARAM_ERROR;
password_length = (uint16_t)strlen(password);
if (password_length > MZ_AES_PW_LENGTH_MAX)
return MZ_PARAM_ERROR;

if (wzaes->encryption_mode < 1 || wzaes->encryption_mode > 3)
return MZ_PARAM_ERROR;

salt_length = MZ_AES_SALT_LENGTH(wzaes->encryption_mode);

if (mode & MZ_OPEN_MODE_WRITE) {
mz_crypt_rand(salt_value, salt_length);
} else if (mode & MZ_OPEN_MODE_READ) {
if (mz_stream_read(wzaes->stream.base, salt_value, salt_length) != salt_length)
return MZ_READ_ERROR;
}

key_length = MZ_AES_KEY_LENGTH(wzaes->encryption_mode);

/* Derive the encryption and authentication keys and the password verifier */
mz_crypt_pbkdf2((uint8_t *)password, password_length, salt_value, salt_length,
MZ_AES_KEYING_ITERATIONS, kbuf, 2 * key_length + MZ_AES_PW_VERIFY_SIZE);

/* Initialize the encryption nonce and buffer pos */
wzaes->crypt_pos = MZ_AES_BLOCK_SIZE;
memset(wzaes->nonce, 0, sizeof(wzaes->nonce));

/* Initialize for encryption using key 1 */
mz_crypt_aes_reset(wzaes->aes);
mz_crypt_aes_set_mode(wzaes->aes, wzaes->encryption_mode);
mz_crypt_aes_set_encrypt_key(wzaes->aes, kbuf, key_length);

/* Initialize for authentication using key 2 */
mz_crypt_hmac_reset(wzaes->hmac);
mz_crypt_hmac_set_algorithm(wzaes->hmac, MZ_HASH_SHA1);
mz_crypt_hmac_init(wzaes->hmac, kbuf + key_length, key_length);

memcpy(verify, kbuf + (2 * key_length), MZ_AES_PW_VERIFY_SIZE);

if (mode & MZ_OPEN_MODE_WRITE) {
if (mz_stream_write(wzaes->stream.base, salt_value, salt_length) != salt_length)
return MZ_WRITE_ERROR;

wzaes->total_out += salt_length;

if (mz_stream_write(wzaes->stream.base, verify, MZ_AES_PW_VERIFY_SIZE) != MZ_AES_PW_VERIFY_SIZE)
return MZ_WRITE_ERROR;

wzaes->total_out += MZ_AES_PW_VERIFY_SIZE;
} else if (mode & MZ_OPEN_MODE_READ) {
wzaes->total_in += salt_length;

if (mz_stream_read(wzaes->stream.base, verify_expected, MZ_AES_PW_VERIFY_SIZE) != MZ_AES_PW_VERIFY_SIZE)
return MZ_READ_ERROR;

wzaes->total_in += MZ_AES_PW_VERIFY_SIZE;

if (memcmp(verify_expected, verify, MZ_AES_PW_VERIFY_SIZE) != 0)
return MZ_PASSWORD_ERROR;
}

wzaes->mode = mode;
wzaes->initialized = 1;

return MZ_OK;
}

int32_t mz_stream_wzaes_is_open(void *stream) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
if (wzaes->initialized == 0)
return MZ_OPEN_ERROR;
return MZ_OK;
}

static int32_t mz_stream_wzaes_ctr_encrypt(void *stream, uint8_t *buf, int32_t size) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
uint32_t pos = wzaes->crypt_pos;
uint32_t i = 0;
int32_t err = MZ_OK;

while (i < (uint32_t)size) {
if (pos == MZ_AES_BLOCK_SIZE) {
uint32_t j = 0;

/* Increment encryption nonce */
while (j < 8 && !++wzaes->nonce[j])
j += 1;

/* Encrypt the nonce to form next xor buffer */
memcpy(wzaes->crypt_block, wzaes->nonce, MZ_AES_BLOCK_SIZE);
mz_crypt_aes_encrypt(wzaes->aes, wzaes->crypt_block, sizeof(wzaes->crypt_block));
pos = 0;
}

buf[i++] ^= wzaes->crypt_block[pos++];
}

wzaes->crypt_pos = pos;
return err;
}

int32_t mz_stream_wzaes_read(void *stream, void *buf, int32_t size) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
int64_t max_total_in = 0;
int32_t bytes_to_read = size;
int32_t read = 0;

max_total_in = wzaes->max_total_in - MZ_AES_FOOTER_SIZE;
if ((int64_t)bytes_to_read > (max_total_in - wzaes->total_in))
bytes_to_read = (int32_t)(max_total_in - wzaes->total_in);

read = mz_stream_read(wzaes->stream.base, buf, bytes_to_read);

if (read > 0) {
mz_crypt_hmac_update(wzaes->hmac, (uint8_t *)buf, read);
mz_stream_wzaes_ctr_encrypt(stream, (uint8_t *)buf, read);

wzaes->total_in += read;
}

return read;
}

int32_t mz_stream_wzaes_write(void *stream, const void *buf, int32_t size) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
const uint8_t *buf_ptr = (const uint8_t *)buf;
int32_t bytes_to_write = sizeof(wzaes->buffer);
int32_t total_written = 0;
int32_t written = 0;

if (size < 0)
return MZ_PARAM_ERROR;

do {
if (bytes_to_write > (size - total_written))
bytes_to_write = (size - total_written);

memcpy(wzaes->buffer, buf_ptr, bytes_to_write);
buf_ptr += bytes_to_write;

mz_stream_wzaes_ctr_encrypt(stream, (uint8_t *)wzaes->buffer, bytes_to_write);
mz_crypt_hmac_update(wzaes->hmac, wzaes->buffer, bytes_to_write);

written = mz_stream_write(wzaes->stream.base, wzaes->buffer, bytes_to_write);
if (written < 0)
return written;

total_written += written;
} while (total_written < size && written > 0);

wzaes->total_out += total_written;
return total_written;
}

int64_t mz_stream_wzaes_tell(void *stream) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
return mz_stream_tell(wzaes->stream.base);
}

int32_t mz_stream_wzaes_seek(void *stream, int64_t offset, int32_t origin) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
return mz_stream_seek(wzaes->stream.base, offset, origin);
}

int32_t mz_stream_wzaes_close(void *stream) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
uint8_t expected_hash[MZ_AES_AUTHCODE_SIZE];
uint8_t computed_hash[MZ_HASH_SHA1_SIZE];

mz_crypt_hmac_end(wzaes->hmac, computed_hash, sizeof(computed_hash));

if (wzaes->mode & MZ_OPEN_MODE_WRITE) {
if (mz_stream_write(wzaes->stream.base, computed_hash, MZ_AES_AUTHCODE_SIZE) != MZ_AES_AUTHCODE_SIZE)
return MZ_WRITE_ERROR;

wzaes->total_out += MZ_AES_AUTHCODE_SIZE;
} else if (wzaes->mode & MZ_OPEN_MODE_READ) {
if (mz_stream_read(wzaes->stream.base, expected_hash, MZ_AES_AUTHCODE_SIZE) != MZ_AES_AUTHCODE_SIZE)
return MZ_READ_ERROR;

wzaes->total_in += MZ_AES_AUTHCODE_SIZE;

/* If entire entry was not read this will fail */
if (memcmp(computed_hash, expected_hash, MZ_AES_AUTHCODE_SIZE) != 0)
return MZ_CRC_ERROR;
}

wzaes->initialized = 0;
return MZ_OK;
}

int32_t mz_stream_wzaes_error(void *stream) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
return wzaes->error;
}

void mz_stream_wzaes_set_password(void *stream, const char *password) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
wzaes->password = password;
}

void mz_stream_wzaes_set_encryption_mode(void *stream, int16_t encryption_mode) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
wzaes->encryption_mode = encryption_mode;
}

int32_t mz_stream_wzaes_get_prop_int64(void *stream, int32_t prop, int64_t *value) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
switch (prop) {
case MZ_STREAM_PROP_TOTAL_IN:
*value = wzaes->total_in;
break;
case MZ_STREAM_PROP_TOTAL_OUT:
*value = wzaes->total_out;
break;
case MZ_STREAM_PROP_TOTAL_IN_MAX:
*value = wzaes->max_total_in;
break;
case MZ_STREAM_PROP_HEADER_SIZE:
*value = MZ_AES_SALT_LENGTH((int64_t)wzaes->encryption_mode) + MZ_AES_PW_VERIFY_SIZE;
break;
case MZ_STREAM_PROP_FOOTER_SIZE:
*value = MZ_AES_AUTHCODE_SIZE;
break;
default:
return MZ_EXIST_ERROR;
}
return MZ_OK;
}

int32_t mz_stream_wzaes_set_prop_int64(void *stream, int32_t prop, int64_t value) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
switch (prop) {
case MZ_STREAM_PROP_TOTAL_IN_MAX:
wzaes->max_total_in = value;
break;
default:
return MZ_EXIST_ERROR;
}
return MZ_OK;
}

void *mz_stream_wzaes_create(void **stream) {
mz_stream_wzaes *wzaes = NULL;

wzaes = (mz_stream_wzaes *)MZ_ALLOC(sizeof(mz_stream_wzaes));
if (wzaes != NULL) {
memset(wzaes, 0, sizeof(mz_stream_wzaes));
wzaes->stream.vtbl = &mz_stream_wzaes_vtbl;
wzaes->encryption_mode = MZ_AES_ENCRYPTION_MODE_256;

mz_crypt_hmac_create(&wzaes->hmac);
mz_crypt_aes_create(&wzaes->aes);
}
if (stream != NULL)
*stream = wzaes;

return wzaes;
}

void mz_stream_wzaes_delete(void **stream) {
mz_stream_wzaes *wzaes = NULL;
if (stream == NULL)
return;
wzaes = (mz_stream_wzaes *)*stream;
if (wzaes != NULL) {
mz_crypt_aes_delete(&wzaes->aes);
mz_crypt_hmac_delete(&wzaes->hmac);
MZ_FREE(wzaes);
}
*stream = NULL;
}

void *mz_stream_wzaes_get_interface(void) {
return (void *)&mz_stream_wzaes_vtbl;
}
@@ -0,0 +1,46 @@
/* mz_strm_wzaes.h -- Stream for WinZIP AES encryption
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/

#ifndef MZ_STREAM_WZAES_SHA1_H
#define MZ_STREAM_WZAES_SHA1_H

#ifdef __cplusplus
extern "C" {
#endif

/***************************************************************************/

int32_t mz_stream_wzaes_open(void *stream, const char *filename, int32_t mode);
int32_t mz_stream_wzaes_is_open(void *stream);
int32_t mz_stream_wzaes_read(void *stream, void *buf, int32_t size);
int32_t mz_stream_wzaes_write(void *stream, const void *buf, int32_t size);
int64_t mz_stream_wzaes_tell(void *stream);
int32_t mz_stream_wzaes_seek(void *stream, int64_t offset, int32_t origin);
int32_t mz_stream_wzaes_close(void *stream);
int32_t mz_stream_wzaes_error(void *stream);

void mz_stream_wzaes_set_password(void *stream, const char *password);
void mz_stream_wzaes_set_encryption_mode(void *stream, int16_t encryption_mode);

int32_t mz_stream_wzaes_get_prop_int64(void *stream, int32_t prop, int64_t *value);
int32_t mz_stream_wzaes_set_prop_int64(void *stream, int32_t prop, int64_t value);

void* mz_stream_wzaes_create(void **stream);
void mz_stream_wzaes_delete(void **stream);

void* mz_stream_wzaes_get_interface(void);

/***************************************************************************/

#ifdef __cplusplus
}
#endif

#endif
@@ -0,0 +1,393 @@
/* mz_strm_zlib.c -- Stream for zlib inflate/deflate
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/


#include "mz.h"
#include "mz_strm.h"
#include "mz_strm_zlib.h"

#include "zlib.h"
#if defined(ZLIBNG_VERNUM) && !defined(ZLIB_COMPAT)
# include "zlib-ng.h"
#endif

/***************************************************************************/

#if defined(ZLIBNG_VERNUM) && !defined(ZLIB_COMPAT)
# define ZLIB_PREFIX(x) zng_ ## x
typedef zng_stream zlib_stream;
#else
# define ZLIB_PREFIX(x) x
typedef z_stream zlib_stream;
#endif

#if !defined(DEF_MEM_LEVEL)
# if MAX_MEM_LEVEL >= 8
# define DEF_MEM_LEVEL 8
# else
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
# endif
#endif

/***************************************************************************/

static mz_stream_vtbl mz_stream_zlib_vtbl = {
mz_stream_zlib_open,
mz_stream_zlib_is_open,
mz_stream_zlib_read,
mz_stream_zlib_write,
mz_stream_zlib_tell,
mz_stream_zlib_seek,
mz_stream_zlib_close,
mz_stream_zlib_error,
mz_stream_zlib_create,
mz_stream_zlib_delete,
mz_stream_zlib_get_prop_int64,
mz_stream_zlib_set_prop_int64
};

/***************************************************************************/

typedef struct mz_stream_zlib_s {
mz_stream stream;
zlib_stream zstream;
uint8_t buffer[INT16_MAX];
int32_t buffer_len;
int64_t total_in;
int64_t total_out;
int64_t max_total_in;
int8_t initialized;
int16_t level;
int32_t window_bits;
int32_t mode;
int32_t error;
} mz_stream_zlib;

/***************************************************************************/

int32_t mz_stream_zlib_open(void *stream, const char *path, int32_t mode) {
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;

MZ_UNUSED(path);

zlib->zstream.data_type = Z_BINARY;
zlib->zstream.zalloc = Z_NULL;
zlib->zstream.zfree = Z_NULL;
zlib->zstream.opaque = Z_NULL;
zlib->zstream.total_in = 0;
zlib->zstream.total_out = 0;

zlib->total_in = 0;
zlib->total_out = 0;

if (mode & MZ_OPEN_MODE_WRITE) {
#ifdef MZ_ZIP_NO_COMPRESSION
return MZ_SUPPORT_ERROR;
#else
zlib->zstream.next_out = zlib->buffer;
zlib->zstream.avail_out = sizeof(zlib->buffer);

zlib->error = ZLIB_PREFIX(deflateInit2)(&zlib->zstream, (int8_t)zlib->level, Z_DEFLATED,
zlib->window_bits, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
#endif
} else if (mode & MZ_OPEN_MODE_READ) {
#ifdef MZ_ZIP_NO_DECOMPRESSION
return MZ_SUPPORT_ERROR;
#else
zlib->zstream.next_in = zlib->buffer;
zlib->zstream.avail_in = 0;

zlib->error = ZLIB_PREFIX(inflateInit2)(&zlib->zstream, zlib->window_bits);
#endif
}

if (zlib->error != Z_OK)
return MZ_OPEN_ERROR;

zlib->initialized = 1;
zlib->mode = mode;
return MZ_OK;
}

int32_t mz_stream_zlib_is_open(void *stream) {
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
if (zlib->initialized != 1)
return MZ_OPEN_ERROR;
return MZ_OK;
}

int32_t mz_stream_zlib_read(void *stream, void *buf, int32_t size) {
#ifdef MZ_ZIP_NO_DECOMPRESSION
MZ_UNUSED(stream);
MZ_UNUSED(buf);
MZ_UNUSED(size);
return MZ_SUPPORT_ERROR;
#else
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
uint64_t total_in_before = 0;
uint64_t total_in_after = 0;
uint64_t total_out_before = 0;
uint64_t total_out_after = 0;
uint32_t total_in = 0;
uint32_t total_out = 0;
uint32_t in_bytes = 0;
uint32_t out_bytes = 0;
int32_t bytes_to_read = sizeof(zlib->buffer);
int32_t read = 0;
int32_t err = Z_OK;


zlib->zstream.next_out = (Bytef*)buf;
zlib->zstream.avail_out = (uInt)size;

do {
if (zlib->zstream.avail_in == 0) {
if (zlib->max_total_in > 0) {
if ((int64_t)bytes_to_read > (zlib->max_total_in - zlib->total_in))
bytes_to_read = (int32_t)(zlib->max_total_in - zlib->total_in);
}

read = mz_stream_read(zlib->stream.base, zlib->buffer, bytes_to_read);

if (read < 0)
return read;

zlib->zstream.next_in = zlib->buffer;
zlib->zstream.avail_in = read;
}

total_in_before = zlib->zstream.avail_in;
total_out_before = zlib->zstream.total_out;

err = ZLIB_PREFIX(inflate)(&zlib->zstream, Z_SYNC_FLUSH);
if ((err >= Z_OK) && (zlib->zstream.msg != NULL)) {
zlib->error = Z_DATA_ERROR;
break;
}

total_in_after = zlib->zstream.avail_in;
total_out_after = zlib->zstream.total_out;

in_bytes = (uint32_t)(total_in_before - total_in_after);
out_bytes = (uint32_t)(total_out_after - total_out_before);

total_in += in_bytes;
total_out += out_bytes;

zlib->total_in += in_bytes;
zlib->total_out += out_bytes;

if (err == Z_STREAM_END)
break;
if (err != Z_OK) {
zlib->error = err;
break;
}
} while (zlib->zstream.avail_out > 0);

if (zlib->error != 0) {
/* Zlib errors are compatible with MZ */
return zlib->error;
}

return total_out;
#endif
}

#ifndef MZ_ZIP_NO_COMPRESSION
static int32_t mz_stream_zlib_flush(void *stream) {
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
if (mz_stream_write(zlib->stream.base, zlib->buffer, zlib->buffer_len) != zlib->buffer_len)
return MZ_WRITE_ERROR;
return MZ_OK;
}

static int32_t mz_stream_zlib_deflate(void *stream, int flush) {
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
uint64_t total_out_before = 0;
uint64_t total_out_after = 0;
int32_t out_bytes = 0;
int32_t err = Z_OK;


do {
if (zlib->zstream.avail_out == 0) {
err = mz_stream_zlib_flush(zlib);
if (err != MZ_OK)
return err;

zlib->zstream.avail_out = sizeof(zlib->buffer);
zlib->zstream.next_out = zlib->buffer;

zlib->buffer_len = 0;
}

total_out_before = zlib->zstream.total_out;
err = ZLIB_PREFIX(deflate)(&zlib->zstream, flush);
total_out_after = zlib->zstream.total_out;

out_bytes = (uint32_t)(total_out_after - total_out_before);

zlib->buffer_len += out_bytes;
zlib->total_out += out_bytes;

if (err == Z_STREAM_END)
break;
if (err != Z_OK) {
zlib->error = err;
return MZ_DATA_ERROR;
}
} while ((zlib->zstream.avail_in > 0) || (flush == Z_FINISH && err == Z_OK));

return MZ_OK;
}
#endif

int32_t mz_stream_zlib_write(void *stream, const void *buf, int32_t size) {
#ifdef MZ_ZIP_NO_COMPRESSION
MZ_UNUSED(stream);
MZ_UNUSED(buf);
MZ_UNUSED(size);
return MZ_SUPPORT_ERROR;
#else
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
int32_t err = MZ_OK;

zlib->zstream.next_in = (Bytef*)(intptr_t)buf;
zlib->zstream.avail_in = (uInt)size;

err = mz_stream_zlib_deflate(stream, Z_NO_FLUSH);
if (err != MZ_OK) {
return err;
}

zlib->total_in += size;
return size;
#endif
}

int64_t mz_stream_zlib_tell(void *stream) {
MZ_UNUSED(stream);

return MZ_TELL_ERROR;
}

int32_t mz_stream_zlib_seek(void *stream, int64_t offset, int32_t origin) {
MZ_UNUSED(stream);
MZ_UNUSED(offset);
MZ_UNUSED(origin);

return MZ_SEEK_ERROR;
}

int32_t mz_stream_zlib_close(void *stream) {
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;


if (zlib->mode & MZ_OPEN_MODE_WRITE) {
#ifdef MZ_ZIP_NO_COMPRESSION
return MZ_SUPPORT_ERROR;
#else
mz_stream_zlib_deflate(stream, Z_FINISH);
mz_stream_zlib_flush(stream);

ZLIB_PREFIX(deflateEnd)(&zlib->zstream);
#endif
} else if (zlib->mode & MZ_OPEN_MODE_READ) {
#ifdef MZ_ZIP_NO_DECOMPRESSION
return MZ_SUPPORT_ERROR;
#else
ZLIB_PREFIX(inflateEnd)(&zlib->zstream);
#endif
}

zlib->initialized = 0;

if (zlib->error != Z_OK)
return MZ_CLOSE_ERROR;
return MZ_OK;
}

int32_t mz_stream_zlib_error(void *stream) {
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
return zlib->error;
}

int32_t mz_stream_zlib_get_prop_int64(void *stream, int32_t prop, int64_t *value) {
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
switch (prop) {
case MZ_STREAM_PROP_TOTAL_IN:
*value = zlib->total_in;
break;
case MZ_STREAM_PROP_TOTAL_IN_MAX:
*value = zlib->max_total_in;
break;
case MZ_STREAM_PROP_TOTAL_OUT:
*value = zlib->total_out;
break;
case MZ_STREAM_PROP_HEADER_SIZE:
*value = 0;
break;
case MZ_STREAM_PROP_COMPRESS_WINDOW:
*value = zlib->window_bits;
break;
default:
return MZ_EXIST_ERROR;
}
return MZ_OK;
}

int32_t mz_stream_zlib_set_prop_int64(void *stream, int32_t prop, int64_t value) {
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
switch (prop) {
case MZ_STREAM_PROP_COMPRESS_LEVEL:
zlib->level = (int16_t)value;
break;
case MZ_STREAM_PROP_TOTAL_IN_MAX:
zlib->max_total_in = value;
break;
case MZ_STREAM_PROP_COMPRESS_WINDOW:
zlib->window_bits = (int32_t)value;
break;
default:
return MZ_EXIST_ERROR;
}
return MZ_OK;
}

void *mz_stream_zlib_create(void **stream) {
mz_stream_zlib *zlib = NULL;

zlib = (mz_stream_zlib *)MZ_ALLOC(sizeof(mz_stream_zlib));
if (zlib != NULL) {
memset(zlib, 0, sizeof(mz_stream_zlib));
zlib->stream.vtbl = &mz_stream_zlib_vtbl;
zlib->level = Z_DEFAULT_COMPRESSION;
zlib->window_bits = -MAX_WBITS;
}
if (stream != NULL)
*stream = zlib;

return zlib;
}

void mz_stream_zlib_delete(void **stream) {
mz_stream_zlib *zlib = NULL;
if (stream == NULL)
return;
zlib = (mz_stream_zlib *)*stream;
if (zlib != NULL)
MZ_FREE(zlib);
*stream = NULL;
}

void *mz_stream_zlib_get_interface(void) {
return (void *)&mz_stream_zlib_vtbl;
}