diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2016-04-12 15:54:22 +0200 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2016-04-26 15:12:57 +0200 |
commit | 38d0278ffd22928cfcc66516a5f5a75f2480e702 (patch) | |
tree | 1ca80dadfab5ffb41eeb00808c715b53739f4786 /source/fitz/zip.c | |
parent | ebba90e528308e2e5bfdc69b24ed9dd32d42121a (diff) | |
download | mupdf-38d0278ffd22928cfcc66516a5f5a75f2480e702.tar.xz |
Add 'mutool convert' and new document writer interface.
Only supports CBZ writing for now.
Also add a zip file writer.
Diffstat (limited to 'source/fitz/zip.c')
-rw-r--r-- | source/fitz/zip.c | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/source/fitz/zip.c b/source/fitz/zip.c new file mode 100644 index 00000000..285fb635 --- /dev/null +++ b/source/fitz/zip.c @@ -0,0 +1,112 @@ +#include "mupdf/fitz.h" + +#include <zlib.h> + +#if !defined (INT32_MAX) +#define INT32_MAX 2147483647L +#endif + +#define ZIP_LOCAL_FILE_SIG 0x04034b50 +#define ZIP_CENTRAL_DIRECTORY_SIG 0x02014b50 +#define ZIP_END_OF_CENTRAL_DIRECTORY_SIG 0x06054b50 + +struct fz_zip_writer_s +{ + fz_output *output; + fz_buffer *central; + int count; +}; + +void +fz_write_zip_entry(fz_context *ctx, fz_zip_writer *zip, const char *name, fz_buffer *buf, int compress) +{ + int offset = fz_tell_output(ctx, zip->output); + int sum; + + sum = crc32(0, NULL, 0); + sum = crc32(sum, buf->data, buf->len); + + fz_write_buffer_int32_le(ctx, zip->central, ZIP_CENTRAL_DIRECTORY_SIG); + fz_write_buffer_int16_le(ctx, zip->central, 0); /* version made by: MS-DOS */ + fz_write_buffer_int16_le(ctx, zip->central, 20); /* version to extract: 2.0 */ + fz_write_buffer_int16_le(ctx, zip->central, 0); /* general purpose bit flag */ + fz_write_buffer_int16_le(ctx, zip->central, 0); /* compression method: store */ + fz_write_buffer_int16_le(ctx, zip->central, 0); /* TODO: last mod file time */ + fz_write_buffer_int16_le(ctx, zip->central, 0); /* TODO: last mod file date */ + fz_write_buffer_int32_le(ctx, zip->central, sum); /* crc-32 */ + fz_write_buffer_int32_le(ctx, zip->central, buf->len); /* csize */ + fz_write_buffer_int32_le(ctx, zip->central, buf->len); /* usize */ + fz_write_buffer_int16_le(ctx, zip->central, strlen(name)); /* file name length */ + fz_write_buffer_int16_le(ctx, zip->central, 0); /* extra field length */ + fz_write_buffer_int16_le(ctx, zip->central, 0); /* file comment length */ + fz_write_buffer_int16_le(ctx, zip->central, 0); /* disk number start */ + fz_write_buffer_int16_le(ctx, zip->central, 0); /* internal file attributes */ + fz_write_buffer_int32_le(ctx, zip->central, 0); /* external file attributes */ + fz_write_buffer_int32_le(ctx, zip->central, offset); /* relative offset of local header */ + fz_write_buffer(ctx, zip->central, name, strlen(name)); + + fz_write_int32_le(ctx, zip->output, ZIP_LOCAL_FILE_SIG); + fz_write_int16_le(ctx, zip->output, 20); /* version to extract: 2.0 */ + fz_write_int16_le(ctx, zip->output, 0); /* general purpose bit flag */ + fz_write_int16_le(ctx, zip->output, 0); /* compression method: store */ + fz_write_int16_le(ctx, zip->output, 0); /* TODO: last mod file time */ + fz_write_int16_le(ctx, zip->output, 0); /* TODO: last mod file date */ + fz_write_int32_le(ctx, zip->output, sum); /* crc-32 */ + fz_write_int32_le(ctx, zip->output, buf->len); /* csize */ + fz_write_int32_le(ctx, zip->output, buf->len); /* usize */ + fz_write_int16_le(ctx, zip->output, strlen(name)); /* file name length */ + fz_write_int16_le(ctx, zip->output, 0); /* extra field length */ + fz_write(ctx, zip->output, name, strlen(name)); + fz_write(ctx, zip->output, buf->data, buf->len); + + ++zip->count; +} + +void +fz_drop_zip_writer(fz_context *ctx, fz_zip_writer *zip) +{ + fz_try(ctx) + { + int offset = fz_tell_output(ctx, zip->output); + + fz_write(ctx, zip->output, zip->central->data, zip->central->len); + + fz_write_int32_le(ctx, zip->output, ZIP_END_OF_CENTRAL_DIRECTORY_SIG); + fz_write_int16_le(ctx, zip->output, 0); /* number of this disk */ + fz_write_int16_le(ctx, zip->output, 0); /* number of disk where central directory starts */ + fz_write_int16_le(ctx, zip->output, zip->count); /* entries in central directory in this disk */ + fz_write_int16_le(ctx, zip->output, zip->count); /* entries in central directory in total */ + fz_write_int32_le(ctx, zip->output, zip->central->len); /* size of the central directory */ + fz_write_int32_le(ctx, zip->output, offset); /* offset of the central directory */ + fz_write_int16_le(ctx, zip->output, 5); /* zip file comment length */ + + fz_write(ctx, zip->output, "MuPDF", 5); + } + fz_always(ctx) + { + fz_drop_output(ctx, zip->output); + fz_drop_buffer(ctx, zip->central); + fz_free(ctx, zip); + } + fz_catch(ctx) + fz_rethrow(ctx); +} + +fz_zip_writer * +fz_new_zip_writer(fz_context *ctx, const char *filename) +{ + fz_zip_writer *zip = fz_malloc_struct(ctx, fz_zip_writer); + fz_try(ctx) + { + zip->output = fz_new_output_with_path(ctx, filename, 0); + zip->central = fz_new_buffer(ctx, 0); + } + fz_catch(ctx) + { + fz_drop_output(ctx, zip->output); + fz_drop_buffer(ctx, zip->central); + fz_free(ctx, zip); + fz_rethrow(ctx); + } + return zip; +} |