diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/pdf/pdf-annot.c | 3 | ||||
-rw-r--r-- | source/pdf/pdf-field.c | 49 | ||||
-rw-r--r-- | source/pdf/pdf-form.c | 67 | ||||
-rw-r--r-- | source/pdf/pdf-pkcs7.c | 40 |
4 files changed, 129 insertions, 30 deletions
diff --git a/source/pdf/pdf-annot.c b/source/pdf/pdf-annot.c index 8e4fd9b1..0aada455 100644 --- a/source/pdf/pdf-annot.c +++ b/source/pdf/pdf-annot.c @@ -732,6 +732,9 @@ pdf_create_annot(pdf_document *doc, pdf_page *page, fz_annot_type type) pdf_dict_puts_drop(annot_obj, "Subtype", pdf_new_name(doc, type_str)); pdf_dict_puts_drop(annot_obj, "Rect", pdf_new_rect(doc, &rect)); + /* Make printable as default */ + pdf_dict_puts_drop(annot_obj, "F", pdf_new_int(doc, F_Print)); + annot = fz_malloc_struct(ctx, pdf_annot); annot->page = page; annot->rect = rect; diff --git a/source/pdf/pdf-field.c b/source/pdf/pdf-field.c index 2a2f07cc..127d92a5 100644 --- a/source/pdf/pdf-field.c +++ b/source/pdf/pdf-field.c @@ -53,3 +53,52 @@ int pdf_field_type(pdf_document *doc, pdf_obj *obj) else return PDF_WIDGET_TYPE_NOT_WIDGET; } + +void pdf_set_field_type(pdf_document *doc, pdf_obj *obj, int type) +{ + int setbits = 0; + int clearbits = 0; + char *typename = NULL; + + switch(type) + { + case PDF_WIDGET_TYPE_PUSHBUTTON: + typename = "Btn"; + setbits = Ff_Pushbutton; + break; + case PDF_WIDGET_TYPE_CHECKBOX: + typename = "Btn"; + clearbits = Ff_Pushbutton; + setbits = Ff_Radio; + break; + case PDF_WIDGET_TYPE_RADIOBUTTON: + typename = "Btn"; + clearbits = (Ff_Pushbutton|Ff_Radio); + break; + case PDF_WIDGET_TYPE_TEXT: + typename = "Tx"; + break; + case PDF_WIDGET_TYPE_LISTBOX: + typename = "Ch"; + clearbits = Ff_Combo; + break; + case PDF_WIDGET_TYPE_COMBOBOX: + typename = "Ch"; + setbits = Ff_Combo; + break; + case PDF_WIDGET_TYPE_SIGNATURE: + typename = "Sig"; + break; + } + + if (typename) + pdf_dict_puts_drop(obj, "FT", pdf_new_name(doc, typename)); + + if (setbits != 0 || clearbits != 0) + { + int bits = pdf_to_int(pdf_dict_gets(obj, "Ff")); + bits &= ~clearbits; + bits |= setbits; + pdf_dict_puts_drop(obj, "Ff", pdf_new_int(doc, bits)); + } +} diff --git a/source/pdf/pdf-form.c b/source/pdf/pdf-form.c index a6ea16c3..c08ecd4e 100644 --- a/source/pdf/pdf-form.c +++ b/source/pdf/pdf-form.c @@ -1,19 +1,5 @@ #include "mupdf/pdf.h" -enum -{ - F_Invisible = 1 << (1-1), - F_Hidden = 1 << (2-1), - F_Print = 1 << (3-1), - F_NoZoom = 1 << (4-1), - F_NoRotate = 1 << (5-1), - F_NoView = 1 << (6-1), - F_ReadOnly = 1 << (7-1), - F_Locked = 1 << (8-1), - F_ToggleNoView = 1 << (9-1), - F_LockedContents = 1 << (10-1) -}; - /* Must be kept in sync with definitions in pdf_util.js */ enum { @@ -23,6 +9,12 @@ enum Display_NoView }; +enum +{ + SigFlag_SignaturesExist = 1, + SigFlag_AppendOnly = 2 +}; + static char *get_string_or_stream(pdf_document *doc, pdf_obj *obj) { fz_context *ctx = doc->ctx; @@ -924,6 +916,53 @@ pdf_widget *pdf_next_widget(pdf_widget *previous) return (pdf_widget *)annot; } +pdf_widget *pdf_create_widget(pdf_document *doc, pdf_page *page, int type, char *fieldname) +{ + fz_context *ctx = doc->ctx; + pdf_obj *form = NULL; + int old_sigflags = pdf_to_int(pdf_dict_getp(pdf_trailer(doc), "Root/AcroForm/SigFlags")); + pdf_annot *annot = pdf_create_annot(doc, page, FZ_ANNOT_WIDGET); + + fz_try(ctx) + { + pdf_set_field_type(doc, annot->obj, type); + pdf_dict_puts_drop(annot->obj, "T", pdf_new_string(doc, fieldname, strlen(fieldname))); + annot->widget_type = type; + + if (type == PDF_WIDGET_TYPE_SIGNATURE) + { + int sigflags = (old_sigflags | (SigFlag_SignaturesExist|SigFlag_AppendOnly)); + pdf_dict_putp_drop(pdf_trailer(doc), "Root/AcroForm/SigFlags", pdf_new_int(doc, sigflags)); + } + + /* + pdf_create_annot will have linked the new widget into the page's + annot array. We also need it linked into the document's form + */ + form = pdf_dict_getp(pdf_trailer(doc), "Root/AcroForm/Fields"); + if (!form) + { + form = pdf_new_array(doc, 1); + pdf_dict_putp_drop(pdf_trailer(doc), "Root/AcroForm/Fields", form); + } + + pdf_array_push(form, annot->obj); /* Cleanup relies on this statement being last */ + } + fz_catch(ctx) + { + pdf_delete_annot(doc, page, annot); + + /* An empty Fields array may have been created, but that is harmless */ + + if (type == PDF_WIDGET_TYPE_SIGNATURE) + pdf_dict_putp_drop(pdf_trailer(doc), "Root/AcroForm/SigFlags", pdf_new_int(doc, old_sigflags)); + + fz_rethrow(ctx); + } + + return (pdf_widget *)annot; +} + int pdf_widget_get_type(pdf_widget *widget) { pdf_annot *annot = (pdf_annot *)widget; diff --git a/source/pdf/pdf-pkcs7.c b/source/pdf/pdf-pkcs7.c index 178d20ea..a36d1592 100644 --- a/source/pdf/pdf-pkcs7.c +++ b/source/pdf/pdf-pkcs7.c @@ -741,29 +741,37 @@ void pdf_sign_signature(pdf_document *doc, pdf_widget *widget, const char *sigfi fz_try(ctx) { char *dn_str; + pdf_obj *wobj = ((pdf_annot *)widget)->obj; + fz_rect rect = fz_empty_rect; - pdf_signature_set_value(doc, ((pdf_annot *)widget)->obj, signer); - dn = pdf_signer_designated_name(signer); - fzbuf = fz_new_buffer(ctx, 256); - if (!dn->cn) - fz_throw(ctx, FZ_ERROR_GENERIC, "Certificate has no common name"); + pdf_signature_set_value(doc, wobj, signer); - fz_buffer_printf(ctx, fzbuf, "cn=%s", dn->cn); + pdf_to_rect(ctx, pdf_dict_gets(wobj, "Rect"), &rect); + /* Create an appearance stream only if the signature is intended to be visible */ + if (!fz_is_empty_rect(&rect)) + { + dn = pdf_signer_designated_name(signer); + fzbuf = fz_new_buffer(ctx, 256); + if (!dn->cn) + fz_throw(ctx, FZ_ERROR_GENERIC, "Certificate has no common name"); + + fz_buffer_printf(ctx, fzbuf, "cn=%s", dn->cn); - if (dn->o) - fz_buffer_printf(ctx, fzbuf, ", o=%s", dn->o); + if (dn->o) + fz_buffer_printf(ctx, fzbuf, ", o=%s", dn->o); - if (dn->ou) - fz_buffer_printf(ctx, fzbuf, ", ou=%s", dn->ou); + if (dn->ou) + fz_buffer_printf(ctx, fzbuf, ", ou=%s", dn->ou); - if (dn->email) - fz_buffer_printf(ctx, fzbuf, ", email=%s", dn->email); + if (dn->email) + fz_buffer_printf(ctx, fzbuf, ", email=%s", dn->email); - if (dn->c) - fz_buffer_printf(ctx, fzbuf, ", c=%s", dn->c); + if (dn->c) + fz_buffer_printf(ctx, fzbuf, ", c=%s", dn->c); - (void)fz_buffer_storage(ctx, fzbuf, (unsigned char **) &dn_str); - pdf_set_signature_appearance(doc, (pdf_annot *)widget, dn->cn, dn_str, NULL); + (void)fz_buffer_storage(ctx, fzbuf, (unsigned char **) &dn_str); + pdf_set_signature_appearance(doc, (pdf_annot *)widget, dn->cn, dn_str, NULL); + } } fz_always(ctx) { |