diff options
author | Paul Gardiner <paul.gardiner@artifex.com> | 2018-01-04 15:11:24 +0000 |
---|---|---|
committer | Paul Gardiner <paul.gardiner@artifex.com> | 2018-01-19 13:52:25 +0000 |
commit | bcce8e5dc38509c5aa43174a0d6e0341444f1d87 (patch) | |
tree | 27bcd71231a322ad83fb7e83ff56d02e458f3ee6 /source/pdf/pdf-write.c | |
parent | 457873fbf7fd6d40242722f3a51b41428302d0ca (diff) | |
download | mupdf-bcce8e5dc38509c5aa43174a0d6e0341444f1d87.tar.xz |
Perform document signing via fz_stream and fz_output
This change achieves two goals. It allows signing to be performed even
when the document is obtained other than from a disk file. It also
reestablishes to a working state signing of file-based documents, a feature
that was broken due to complete_signatures being called after certain
tables, avaialble via the output options object, had been destroyed.
Diffstat (limited to 'source/pdf/pdf-write.c')
-rw-r--r-- | source/pdf/pdf-write.c | 138 |
1 files changed, 73 insertions, 65 deletions
diff --git a/source/pdf/pdf-write.c b/source/pdf/pdf-write.c index b13970b9..28a505f9 100644 --- a/source/pdf/pdf-write.c +++ b/source/pdf/pdf-write.c @@ -2624,95 +2624,102 @@ static void presize_unsaved_signature_byteranges(fz_context *ctx, pdf_document * } } -static void complete_signatures(fz_context *ctx, pdf_document *doc, pdf_write_state *opts, const char *filename) +static void complete_signatures(fz_context *ctx, pdf_document *doc, pdf_write_state *opts) { pdf_unsaved_sig *usig; char buf[5120]; int s; int i; int last_end; - FILE *f; + fz_stream *stm = NULL; + fz_var(stm); - for (s = 0; s < doc->num_incremental_sections; s++) + fz_try(ctx) { - pdf_xref *xref = &doc->xref_sections[doc->num_incremental_sections - s - 1]; - - if (xref->unsaved_sigs) + for (s = 0; s < doc->num_incremental_sections; s++) { - pdf_obj *byte_range; + pdf_xref *xref = &doc->xref_sections[doc->num_incremental_sections - s - 1]; - f = fopen(filename, "rb+"); - if (!f) - fz_throw(ctx, FZ_ERROR_GENERIC, "Failed to open %s to complete signatures", filename); - - /* Locate the byte ranges and contents in the saved file */ - for (usig = xref->unsaved_sigs; usig; usig = usig->next) + if (xref->unsaved_sigs) { - char *bstr, *cstr, *fstr; - int pnum = pdf_obj_parent_num(ctx, pdf_dict_getl(ctx, usig->field, PDF_NAME_V, PDF_NAME_ByteRange, NULL)); - fseek(f, opts->ofs_list[pnum], SEEK_SET); - (void)fread(buf, 1, sizeof(buf), f); - buf[sizeof(buf)-1] = 0; + pdf_obj *byte_range; - bstr = strstr(buf, "/ByteRange"); - cstr = strstr(buf, "/Contents"); - fstr = strstr(buf, "/Filter"); - - if (bstr && cstr && fstr && bstr < cstr && cstr < fstr) + stm = fz_stream_from_output(ctx, opts->out); + /* Locate the byte ranges and contents in the saved file */ + for (usig = xref->unsaved_sigs; usig; usig = usig->next) { - usig->byte_range_start = bstr - buf + 10 + opts->ofs_list[pnum]; - usig->byte_range_end = cstr - buf + opts->ofs_list[pnum]; - usig->contents_start = cstr - buf + 9 + opts->ofs_list[pnum]; - usig->contents_end = fstr - buf + opts->ofs_list[pnum]; + char *bstr, *cstr, *fstr; + int pnum = pdf_obj_parent_num(ctx, pdf_dict_getl(ctx, usig->field, PDF_NAME_V, PDF_NAME_ByteRange, NULL)); + fz_seek(ctx, stm, opts->ofs_list[pnum], SEEK_SET); + (void)fz_read(ctx, stm, (unsigned char *)buf, sizeof(buf)); + buf[sizeof(buf)-1] = 0; + + bstr = strstr(buf, "/ByteRange"); + cstr = strstr(buf, "/Contents"); + fstr = strstr(buf, "/Filter"); + + if (bstr && cstr && fstr && bstr < cstr && cstr < fstr) + { + usig->byte_range_start = bstr - buf + 10 + opts->ofs_list[pnum]; + usig->byte_range_end = cstr - buf + opts->ofs_list[pnum]; + usig->contents_start = cstr - buf + 9 + opts->ofs_list[pnum]; + usig->contents_end = fstr - buf + opts->ofs_list[pnum]; + } } - } - /* Recreate ByteRange with correct values. Initially store the - * recreated object in the first of the unsaved signatures */ - byte_range = pdf_new_array(ctx, doc, 4); - pdf_dict_putl_drop(ctx, xref->unsaved_sigs->field, byte_range, PDF_NAME_V, PDF_NAME_ByteRange, NULL); + fz_drop_stream(ctx, stm); + stm = NULL; - last_end = 0; - for (usig = xref->unsaved_sigs; usig; usig = usig->next) - { - pdf_array_push_drop(ctx, byte_range, pdf_new_int(ctx, doc, last_end)); - pdf_array_push_drop(ctx, byte_range, pdf_new_int(ctx, doc, usig->contents_start - last_end)); - last_end = usig->contents_end; - } - pdf_array_push_drop(ctx, byte_range, pdf_new_int(ctx, doc, last_end)); - pdf_array_push_drop(ctx, byte_range, pdf_new_int(ctx, doc, xref->end_ofs - last_end)); + /* Recreate ByteRange with correct values. Initially store the + * recreated object in the first of the unsaved signatures */ + byte_range = pdf_new_array(ctx, doc, 4); + pdf_dict_putl_drop(ctx, xref->unsaved_sigs->field, byte_range, PDF_NAME_V, PDF_NAME_ByteRange, NULL); - /* Copy the new ByteRange to the other unsaved signatures */ - for (usig = xref->unsaved_sigs->next; usig; usig = usig->next) - pdf_dict_putl_drop(ctx, usig->field, pdf_copy_array(ctx, byte_range), PDF_NAME_V, PDF_NAME_ByteRange, NULL); + last_end = 0; + for (usig = xref->unsaved_sigs; usig; usig = usig->next) + { + pdf_array_push_drop(ctx, byte_range, pdf_new_int(ctx, doc, last_end)); + pdf_array_push_drop(ctx, byte_range, pdf_new_int(ctx, doc, usig->contents_start - last_end)); + last_end = usig->contents_end; + } + pdf_array_push_drop(ctx, byte_range, pdf_new_int(ctx, doc, last_end)); + pdf_array_push_drop(ctx, byte_range, pdf_new_int(ctx, doc, xref->end_ofs - last_end)); - /* Write the byte range into buf, padding with spaces*/ - i = pdf_sprint_obj(ctx, buf, sizeof(buf), byte_range, 1); - memset(buf+i, ' ', sizeof(buf)-i); + /* Copy the new ByteRange to the other unsaved signatures */ + for (usig = xref->unsaved_sigs->next; usig; usig = usig->next) + pdf_dict_putl_drop(ctx, usig->field, pdf_copy_array(ctx, byte_range), PDF_NAME_V, PDF_NAME_ByteRange, NULL); - /* Write the byte range to the file */ - for (usig = xref->unsaved_sigs; usig; usig = usig->next) - { - fseek(f, usig->byte_range_start, SEEK_SET); - fwrite(buf, 1, usig->byte_range_end - usig->byte_range_start, f); - } + /* Write the byte range into buf, padding with spaces*/ + i = pdf_sprint_obj(ctx, buf, sizeof(buf), byte_range, 1); + memset(buf+i, ' ', sizeof(buf)-i); - fclose(f); + /* Write the byte range to the file */ + for (usig = xref->unsaved_sigs; usig; usig = usig->next) + { + fz_seek_output(ctx, opts->out, usig->byte_range_start, SEEK_SET); + fz_write_data(ctx, opts->out, buf, usig->byte_range_end - usig->byte_range_start); + } - /* Write the digests into the file */ - for (usig = xref->unsaved_sigs; usig; usig = usig->next) - pdf_write_digest(ctx, doc, filename, byte_range, usig->contents_start, usig->contents_end - usig->contents_start, usig->signer); + /* Write the digests into the file */ + for (usig = xref->unsaved_sigs; usig; usig = usig->next) + pdf_write_digest(ctx, opts->out, byte_range, usig->contents_start, usig->contents_end - usig->contents_start, usig->signer); - /* delete the unsaved_sigs records */ - while ((usig = xref->unsaved_sigs) != NULL) - { - xref->unsaved_sigs = usig->next; - pdf_drop_obj(ctx, usig->field); - pdf_drop_signer(ctx, usig->signer); - fz_free(ctx, usig); + /* delete the unsaved_sigs records */ + while ((usig = xref->unsaved_sigs) != NULL) + { + xref->unsaved_sigs = usig->next; + pdf_drop_obj(ctx, usig->field); + pdf_drop_signer(ctx, usig->signer); + fz_free(ctx, usig); + } } } } + fz_catch(ctx) + { + fz_drop_stream(ctx, stm); + fz_rethrow(ctx); + } } static void clean_content_streams(fz_context *ctx, pdf_document *doc, int sanitize, int ascii) @@ -3054,6 +3061,8 @@ do_pdf_save_document(fz_context *ctx, pdf_document *doc, pdf_write_state *opts, doc->xref_sections[0].end_ofs = fz_tell_output(ctx, opts->out); } + complete_signatures(ctx, doc, opts); + doc->dirty = 0; } fz_always(ctx) @@ -3149,7 +3158,6 @@ void pdf_save_document(fz_context *ctx, pdf_document *doc, const char *filename, { do_pdf_save_document(ctx, doc, &opts, in_opts); fz_close_output(ctx, opts.out); - complete_signatures(ctx, doc, &opts, filename); } fz_always(ctx) { |