/* Copyright 2015 the unarr project authors (see AUTHORS file). License: LGPLv3 */ #ifndef zip_zip_h #define zip_zip_h #include "../common/unarr-imp.h" #ifdef HAVE_ZLIB #include #endif #include "inflate.h" #ifdef HAVE_BZIP2 #include #endif #include "../lzmasdk/LzmaDec.h" #include "../lzmasdk/Ppmd8.h" typedef struct ar_archive_zip_s ar_archive_zip; /***** parse-zip *****/ enum zip_signatures { SIG_LOCAL_FILE_HEADER = 0x04034B50, SIG_CENTRAL_DIRECTORY = 0x02014B50, SIG_END_OF_CENTRAL_DIRECTORY_64 = 0x06064B50, SIG_END_OF_CENTRAL_DIRECTORY_64_LOCATOR = 0x07064B50, SIG_END_OF_CENTRAL_DIRECTORY = 0x06054B50, }; enum compression_method { METHOD_STORE = 0, METHOD_DEFLATE = 8, METHOD_DEFLATE64 = 9, METHOD_BZIP2 = 12, METHOD_LZMA = 14, METHOD_PPMD = 98, }; #define ZIP_LOCAL_ENTRY_FIXED_SIZE 30 #define ZIP_DIR_ENTRY_FIXED_SIZE 46 #define ZIP_END_OF_CENTRAL_DIR_SIZE 22 struct zip_entry { uint32_t signature; uint16_t version; uint16_t min_version; uint16_t flags; uint16_t method; uint32_t dosdate; uint32_t crc; uint64_t datasize; uint64_t uncompressed; uint16_t namelen; uint16_t extralen; uint16_t commentlen; uint32_t disk; uint16_t attr_internal; uint32_t attr_external; off64_t header_offset; }; struct zip_eocd64 { uint32_t signature; uint16_t version; uint16_t min_version; uint32_t diskno; uint32_t diskno_dir; uint64_t numentries_disk; uint64_t numentries; uint64_t dir_size; off64_t dir_offset; uint16_t commentlen; }; struct ar_archive_zip_entry { off64_t offset; uint16_t method; uint16_t flags; uint32_t crc; char *name; uint32_t dosdate; }; bool zip_seek_to_compressed_data(ar_archive_zip *zip); bool zip_parse_local_file_entry(ar_archive_zip *zip, struct zip_entry *entry); off64_t zip_find_next_local_file_entry(ar_stream *stream, off64_t offset); bool zip_parse_directory_entry(ar_archive_zip *zip, struct zip_entry *entry); off64_t zip_find_end_of_last_directory_entry(ar_stream *stream, struct zip_eocd64 *eocd); bool zip_parse_end_of_central_directory(ar_stream *stream, struct zip_eocd64 *eocd); off64_t zip_find_end_of_central_directory(ar_stream *stream); const char *zip_get_name(ar_archive *ar); /***** uncompress-zip *****/ struct ar_archive_zip_uncomp; typedef uint32_t (* zip_uncomp_uncompress_data_fn)(struct ar_archive_zip_uncomp *uncomp, void *buffer, uint32_t buffer_size, bool is_last_chunk); typedef void (* zip_uncomp_clear_state_fn)(struct ar_archive_zip_uncomp *uncomp); struct InputBuffer { uint8_t data[4096]; uint16_t offset; uint16_t bytes_left; bool at_eof; }; struct ByteReader { IByteIn super; struct InputBuffer *input; ar_archive_zip *zip; }; struct ar_archive_zip_uncomp { bool initialized; zip_uncomp_uncompress_data_fn uncompress_data; zip_uncomp_clear_state_fn clear_state; union { #ifdef HAVE_ZLIB z_stream zstream; #endif inflate_state *inflate; #ifdef HAVE_BZIP2 bz_stream bstream; #endif struct { CLzmaDec dec; ELzmaFinishMode finish; ISzAlloc alloc; } lzma; struct { CPpmd8 ctx; struct ByteReader bytein; ISzAlloc alloc; } ppmd8; } state; struct InputBuffer input; }; bool zip_uncompress_part(ar_archive_zip *zip, void *buffer, size_t buffer_size); void zip_clear_uncompress(struct ar_archive_zip_uncomp *uncomp); /***** zip *****/ struct ar_archive_zip_dir { /* off64_t offset; // use ar_archive::entry_offset_first */ off64_t end_offset; }; struct ar_archive_zip_progress { size_t data_left; size_t bytes_done; uint32_t crc; }; struct ar_archive_zip_s { ar_archive super; struct ar_archive_zip_dir dir; struct ar_archive_zip_entry entry; struct ar_archive_zip_uncomp uncomp; struct ar_archive_zip_progress progress; bool deflatedonly; off64_t comment_offset; uint16_t comment_size; }; #endif