diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2018-11-06 14:40:12 +0100 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2018-11-07 14:02:18 +0100 |
commit | 60b13ad3f7a1b597152d079b336fbbed75942998 (patch) | |
tree | 044d4c1fa08f815f8e2af98056eef430cc5bcd89 | |
parent | 635b325a64d7a271bbb6a9507c2d85332aa4d028 (diff) | |
download | mupdf-60b13ad3f7a1b597152d079b336fbbed75942998.tar.xz |
Fix 700053: Add 'decrypt' option to pdf_save_document.
This option is exposed as the -D flag to mutool clean.
Allow saving a document without encryption.
The next step is to allow saving a document with new encryption, but this
may require a fair amount of rejigging since the PDF write code to keep
separate doc->crypt objects for decryption and encryption.
-rw-r--r-- | include/mupdf/pdf/document.h | 1 | ||||
-rw-r--r-- | platform/gl/gl-annotate.c | 1 | ||||
-rw-r--r-- | source/pdf/pdf-write.c | 57 | ||||
-rw-r--r-- | source/tools/pdfclean.c | 3 |
4 files changed, 51 insertions, 11 deletions
diff --git a/include/mupdf/pdf/document.h b/include/mupdf/pdf/document.h index 7d2110b7..27e3d4f4 100644 --- a/include/mupdf/pdf/document.h +++ b/include/mupdf/pdf/document.h @@ -879,6 +879,7 @@ struct pdf_write_options_s int do_linear; /* Write linearised. */ int do_clean; /* Clean content streams. */ int do_sanitize; /* Sanitize content streams. */ + int do_decrypt; /* Save without decryption. */ int continue_on_error; /* If set, errors are (optionally) counted and writing continues. */ int *errors; /* Pointer to a place to store a count of errors */ }; diff --git a/platform/gl/gl-annotate.c b/platform/gl/gl-annotate.c index 48f0555e..155cac24 100644 --- a/platform/gl/gl-annotate.c +++ b/platform/gl/gl-annotate.c @@ -39,6 +39,7 @@ static void save_pdf_options(void) ui_checkbox("Compress images", &save_opts.do_compress_images); ui_checkbox("Compress fonts", &save_opts.do_compress_fonts); ui_checkbox("Decompress", &save_opts.do_decompress); + ui_checkbox("Decrypt", &save_opts.do_decrypt); ui_checkbox("Garbage collect", &save_opts.do_garbage); ui_checkbox("Linearize", &save_opts.do_linear); ui_checkbox("Clean syntax", &save_opts.do_clean); diff --git a/source/pdf/pdf-write.c b/source/pdf/pdf-write.c index 6417e2fa..0fe311c1 100644 --- a/source/pdf/pdf-write.c +++ b/source/pdf/pdf-write.c @@ -68,6 +68,7 @@ struct pdf_write_state_s int do_garbage; int do_linear; int do_clean; + int do_decrypt; int list_len; int *use_list; @@ -1705,13 +1706,25 @@ static void copystream(fz_context *ctx, pdf_document *doc, pdf_write_state *opts addhexfilter(ctx, doc, obj); } - pdf_dict_put_int(ctx, obj, PDF_NAME(Length), pdf_encrypted_len(ctx, doc->crypt, num, gen, (int)len)); - fz_write_printf(ctx, opts->out, "%d %d obj\n", num, gen); - pdf_print_encrypted_obj(ctx, opts->out, obj, opts->do_tight, doc->crypt, num, gen); - fz_write_string(ctx, opts->out, "\nstream\n"); - pdf_encrypt_data(ctx, doc->crypt, num, gen, write_data, opts->out, data, len); + + if (opts->do_decrypt) + { + pdf_dict_put_int(ctx, obj, PDF_NAME(Length), len); + pdf_print_obj(ctx, opts->out, obj, opts->do_tight); + fz_write_string(ctx, opts->out, "\nstream\n"); + fz_write_data(ctx, opts->out, data, len); + } + else + { + pdf_dict_put_int(ctx, obj, PDF_NAME(Length), pdf_encrypted_len(ctx, doc->crypt, num, gen, (int)len)); + pdf_print_encrypted_obj(ctx, opts->out, obj, opts->do_tight, doc->crypt, num, gen); + fz_write_string(ctx, opts->out, "\nstream\n"); + pdf_encrypt_data(ctx, doc->crypt, num, gen, write_data, opts->out, data, len); + } + fz_write_string(ctx, opts->out, "\nendstream\nendobj\n\n"); + } fz_always(ctx) { @@ -1769,12 +1782,23 @@ static void expandstream(fz_context *ctx, pdf_document *doc, pdf_write_state *op addhexfilter(ctx, doc, obj); } - pdf_dict_put_int(ctx, obj, PDF_NAME(Length), pdf_encrypted_len(ctx, doc->crypt, num, gen, (int)len)); - fz_write_printf(ctx, opts->out, "%d %d obj\n", num, gen); - pdf_print_encrypted_obj(ctx, opts->out, obj, opts->do_tight, doc->crypt, num, gen); - fz_write_string(ctx, opts->out, "\nstream\n"); - pdf_encrypt_data(ctx, doc->crypt, num, gen, write_data, opts->out, data, len); + + if (opts->do_decrypt) + { + pdf_dict_put_int(ctx, obj, PDF_NAME(Length), len); + pdf_print_obj(ctx, opts->out, obj, opts->do_tight); + fz_write_string(ctx, opts->out, "\nstream\n"); + fz_write_data(ctx, opts->out, data, len); + } + else + { + pdf_dict_put_int(ctx, obj, PDF_NAME(Length), pdf_encrypted_len(ctx, doc->crypt, num, gen, (int)len)); + pdf_print_encrypted_obj(ctx, opts->out, obj, opts->do_tight, doc->crypt, num, gen); + fz_write_string(ctx, opts->out, "\nstream\n"); + pdf_encrypt_data(ctx, doc->crypt, num, gen, write_data, opts->out, data, len); + } + fz_write_string(ctx, opts->out, "\nendstream\nendobj\n\n"); } fz_always(ctx) @@ -2800,6 +2824,7 @@ static void initialise_write_state(fz_context *ctx, pdf_document *doc, const pdf opts->do_garbage = in_opts->do_garbage; opts->do_linear = in_opts->do_linear; opts->do_clean = in_opts->do_clean; + opts->do_decrypt = in_opts->do_decrypt; opts->start = 0; opts->main_xref_offset = INT_MIN; @@ -2885,6 +2910,8 @@ pdf_parse_write_options(fz_context *ctx, pdf_write_options *opts, const char *ar opts->do_incremental = fz_option_eq(val, "yes"); if (fz_has_option(ctx, args, "continue-on-error", &val)) opts->continue_on_error = fz_option_eq(val, "yes"); + if (fz_has_option(ctx, args, "decrypt", &val)) + opts->do_decrypt = fz_option_eq(val, "yes"); if (fz_has_option(ctx, args, "garbage", &val)) { if (fz_option_eq(val, "yes")) @@ -2966,6 +2993,12 @@ do_pdf_save_document(fz_context *ctx, pdf_document *doc, pdf_write_state *opts, { initialise_write_state(ctx, doc, in_opts, opts); + /* Remove encryption dictionary if saving without encryption. */ + if (opts->do_decrypt) + { + pdf_dict_del(ctx, pdf_trailer(ctx, doc), PDF_NAME(Encrypt)); + } + /* Make sure any objects hidden in compressed streams have been loaded */ if (!opts->do_incremental) { @@ -3157,6 +3190,8 @@ void pdf_write_document(fz_context *ctx, pdf_document *doc, fz_output *out, pdf_ fz_throw(ctx, FZ_ERROR_GENERIC, "Can't do incremental writes with garbage collection"); if (in_opts->do_incremental && in_opts->do_linear) fz_throw(ctx, FZ_ERROR_GENERIC, "Can't do incremental writes with linearisation"); + if (in_opts->do_incremental && in_opts->do_decrypt) + fz_throw(ctx, FZ_ERROR_GENERIC, "Can't do incremental writes with decryption"); if (pdf_has_unsaved_sigs(ctx, doc) && !out->as_stream) fz_throw(ctx, FZ_ERROR_GENERIC, "Can't write pdf that has unsaved sigs to a fz_output unless it supports fz_stream_from_output!"); @@ -3186,6 +3221,8 @@ void pdf_save_document(fz_context *ctx, pdf_document *doc, const char *filename, fz_throw(ctx, FZ_ERROR_GENERIC, "Can't do incremental writes with garbage collection"); if (in_opts->do_incremental && in_opts->do_linear) fz_throw(ctx, FZ_ERROR_GENERIC, "Can't do incremental writes with linearisation"); + if (in_opts->do_incremental && in_opts->do_decrypt) + fz_throw(ctx, FZ_ERROR_GENERIC, "Can't do incremental writes with decryption"); prepare_for_save(ctx, doc, in_opts); diff --git a/source/tools/pdfclean.c b/source/tools/pdfclean.c index 6d5a69be..0e7a464a 100644 --- a/source/tools/pdfclean.c +++ b/source/tools/pdfclean.c @@ -51,7 +51,7 @@ int pdfclean_main(int argc, char **argv) opts.continue_on_error = 1; opts.errors = &errors; - while ((c = fz_getopt(argc, argv, "adfgilp:scz")) != -1) + while ((c = fz_getopt(argc, argv, "adfgilp:sczD")) != -1) { switch (c) { @@ -66,6 +66,7 @@ int pdfclean_main(int argc, char **argv) case 'l': opts.do_linear += 1; break; case 'c': opts.do_clean += 1; break; case 's': opts.do_sanitize += 1; break; + case 'D': opts.do_decrypt += 1; break; default: usage(); break; } } |