comparison mupdf-source/source/pdf/pdf-form.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children aa33339d6b8a
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 // Copyright (C) 2004-2025 Artifex Software, Inc.
2 //
3 // This file is part of MuPDF.
4 //
5 // MuPDF is free software: you can redistribute it and/or modify it under the
6 // terms of the GNU Affero General Public License as published by the Free
7 // Software Foundation, either version 3 of the License, or (at your option)
8 // any later version.
9 //
10 // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13 // details.
14 //
15 // You should have received a copy of the GNU Affero General Public License
16 // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
17 //
18 // Alternative licensing terms are available from the licensor.
19 // For commercial licensing, see <https://www.artifex.com/> or contact
20 // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
21 // CA 94129, USA, for further information.
22
23 #include "mupdf/fitz.h"
24 #include "pdf-annot-imp.h"
25
26 #include <string.h>
27
28 /* Must be kept in sync with definitions in pdf_util.js */
29 enum
30 {
31 Display_Visible,
32 Display_Hidden,
33 Display_NoPrint,
34 Display_NoView
35 };
36
37 enum
38 {
39 SigFlag_SignaturesExist = 1,
40 SigFlag_AppendOnly = 2
41 };
42
43 const char *pdf_field_value(fz_context *ctx, pdf_obj *field)
44 {
45 pdf_obj *v = pdf_dict_get_inheritable(ctx, field, PDF_NAME(V));
46 if (pdf_is_name(ctx, v))
47 return pdf_to_name(ctx, v);
48 if (pdf_is_stream(ctx, v))
49 {
50 // FIXME: pdf_dict_put_inheritable...
51 char *str = pdf_new_utf8_from_pdf_stream_obj(ctx, v);
52 fz_try(ctx)
53 pdf_dict_put_text_string(ctx, field, PDF_NAME(V), str);
54 fz_always(ctx)
55 fz_free(ctx, str);
56 fz_catch(ctx)
57 fz_rethrow(ctx);
58 v = pdf_dict_get(ctx, field, PDF_NAME(V));
59 }
60 return pdf_to_text_string(ctx, v);
61 }
62
63 int pdf_field_flags(fz_context *ctx, pdf_obj *obj)
64 {
65 return pdf_dict_get_inheritable_int(ctx, obj, PDF_NAME(Ff));
66 }
67
68 int pdf_field_type(fz_context *ctx, pdf_obj *obj)
69 {
70 pdf_obj *type = pdf_dict_get_inheritable(ctx, obj, PDF_NAME(FT));
71 int flags = pdf_field_flags(ctx, obj);
72 if (pdf_name_eq(ctx, type, PDF_NAME(Btn)))
73 {
74 if (flags & PDF_BTN_FIELD_IS_PUSHBUTTON)
75 return PDF_WIDGET_TYPE_BUTTON;
76 else if (flags & PDF_BTN_FIELD_IS_RADIO)
77 return PDF_WIDGET_TYPE_RADIOBUTTON;
78 else
79 return PDF_WIDGET_TYPE_CHECKBOX;
80 }
81 else if (pdf_name_eq(ctx, type, PDF_NAME(Tx)))
82 return PDF_WIDGET_TYPE_TEXT;
83 else if (pdf_name_eq(ctx, type, PDF_NAME(Ch)))
84 {
85 if (flags & PDF_CH_FIELD_IS_COMBO)
86 return PDF_WIDGET_TYPE_COMBOBOX;
87 else
88 return PDF_WIDGET_TYPE_LISTBOX;
89 }
90 else if (pdf_name_eq(ctx, type, PDF_NAME(Sig)))
91 return PDF_WIDGET_TYPE_SIGNATURE;
92 else
93 return PDF_WIDGET_TYPE_BUTTON;
94 }
95
96 const char *pdf_field_type_string(fz_context *ctx, pdf_obj *obj)
97 {
98 switch (pdf_field_type(ctx, obj))
99 {
100 default:
101 case PDF_WIDGET_TYPE_BUTTON: return "button";
102 case PDF_WIDGET_TYPE_CHECKBOX: return "checkbox";
103 case PDF_WIDGET_TYPE_COMBOBOX: return "combobox";
104 case PDF_WIDGET_TYPE_LISTBOX: return "listbox";
105 case PDF_WIDGET_TYPE_RADIOBUTTON: return "radiobutton";
106 case PDF_WIDGET_TYPE_SIGNATURE: return "signature";
107 case PDF_WIDGET_TYPE_TEXT: return "text";
108 }
109 }
110
111 /* Find the point in a field hierarchy where all descendants
112 * share the same name */
113 static pdf_obj *find_head_of_field_group(fz_context *ctx, pdf_obj *obj)
114 {
115 if (obj == NULL || pdf_dict_get(ctx, obj, PDF_NAME(T)))
116 return obj;
117 else
118 return find_head_of_field_group(ctx, pdf_dict_get(ctx, obj, PDF_NAME(Parent)));
119 }
120
121 static void pdf_field_mark_dirty(fz_context *ctx, pdf_obj *field)
122 {
123 pdf_document *doc = pdf_get_bound_document(ctx, field);
124 pdf_obj *kids = pdf_dict_get(ctx, field, PDF_NAME(Kids));
125 if (kids)
126 {
127 int i, n = pdf_array_len(ctx, kids);
128 for (i = 0; i < n; i++)
129 pdf_field_mark_dirty(ctx, pdf_array_get(ctx, kids, i));
130 }
131 pdf_dirty_obj(ctx, field);
132 if (doc)
133 doc->resynth_required = 1;
134 }
135
136 static void update_field_value(fz_context *ctx, pdf_document *doc, pdf_obj *obj, const char *text)
137 {
138 const char *old_text;
139 pdf_obj *grp;
140
141 if (!text)
142 text = "";
143
144 /* All fields of the same name should be updated, so
145 * set the value at the head of the group */
146 grp = find_head_of_field_group(ctx, obj);
147 if (grp)
148 obj = grp;
149
150 /* Only update if we change the actual value. */
151 old_text = pdf_dict_get_text_string(ctx, obj, PDF_NAME(V));
152 if (old_text && !strcmp(old_text, text))
153 return;
154
155 pdf_dict_put_text_string(ctx, obj, PDF_NAME(V), text);
156
157 pdf_field_mark_dirty(ctx, obj);
158 }
159
160 static pdf_obj *
161 pdf_lookup_field_imp(fz_context *ctx, pdf_obj *arr, const char *str, pdf_cycle_list *cycle_up);
162
163 static pdf_obj *
164 lookup_field_sub(fz_context *ctx, pdf_obj *dict, const char *str, pdf_cycle_list *cycle_up)
165 {
166 pdf_obj *kids;
167 pdf_obj *name;
168
169 name = pdf_dict_get(ctx, dict, PDF_NAME(T));
170
171 /* If we have a name, check it matches. If it matches, consume that
172 * portion of str. If not, exit. */
173 if (name)
174 {
175 const char *match = pdf_to_text_string(ctx, name);
176 const char *e = str;
177 size_t len;
178 while (*e && *e != '.')
179 e++;
180 len = e-str;
181 if (strncmp(str, match, len) != 0 || (match[len] != 0 && match[len] != '.'))
182 /* name doesn't match. */
183 return NULL;
184 str = e;
185 if (*str == '.')
186 str++;
187 }
188
189 /* If there is a kids array, but the search string is not empty, we have
190 encountered an internal field which represents a set of terminal fields. */
191
192 /* If there is a kids array and the search string is not empty,
193 walk those looking for the appropriate one. */
194 kids = pdf_dict_get(ctx, dict, PDF_NAME(Kids));
195 if (kids && *str != 0)
196 return pdf_lookup_field_imp(ctx, kids, str, cycle_up);
197
198 /* The field may be a terminal or an internal field at this point.
199 Accept it as the match if the match string is exhausted. */
200 if (*str == 0)
201 return dict;
202
203 return NULL;
204 }
205
206 static pdf_obj *
207 pdf_lookup_field_imp(fz_context *ctx, pdf_obj *arr, const char *str, pdf_cycle_list *cycle_up)
208 {
209 pdf_cycle_list cycle;
210 int len = pdf_array_len(ctx, arr);
211 int i;
212
213 for (i = 0; i < len; i++)
214 {
215 pdf_obj *k = pdf_array_get(ctx, arr, i);
216 pdf_obj *found;
217 if (pdf_cycle(ctx, &cycle, cycle_up, k))
218 fz_throw(ctx, FZ_ERROR_FORMAT, "cycle in fields");
219 found = lookup_field_sub(ctx, k, str, &cycle);
220 if (found)
221 return found;
222 }
223
224 return NULL;
225 }
226
227 pdf_obj *
228 pdf_lookup_field(fz_context *ctx, pdf_obj *arr, const char *str)
229 {
230 return pdf_lookup_field_imp(ctx, arr, str, NULL);
231 }
232
233 static void reset_form_field(fz_context *ctx, pdf_document *doc, pdf_obj *field)
234 {
235 /* Set V to DV wherever DV is present, and delete V where DV is not.
236 * FIXME: we assume for now that V has not been set unequal
237 * to DV higher in the hierarchy than "field".
238 *
239 * At the bottom of the hierarchy we may find widget annotations
240 * that aren't also fields, but DV and V will not be present in their
241 * dictionaries, and attempts to remove V will be harmless. */
242 pdf_obj *dv = pdf_dict_get(ctx, field, PDF_NAME(DV));
243 pdf_obj *kids = pdf_dict_get(ctx, field, PDF_NAME(Kids));
244
245 if (dv)
246 pdf_dict_put(ctx, field, PDF_NAME(V), dv);
247 else
248 pdf_dict_del(ctx, field, PDF_NAME(V));
249
250 if (kids == NULL)
251 {
252 /* The leaves of the tree are widget annotations
253 * In some cases we need to update the appearance state;
254 * in others we need to mark the field as dirty so that
255 * the appearance stream will be regenerated. */
256 switch (pdf_field_type(ctx, field))
257 {
258 case PDF_WIDGET_TYPE_CHECKBOX:
259 case PDF_WIDGET_TYPE_RADIOBUTTON:
260 {
261 pdf_obj *leafv = pdf_dict_get_inheritable(ctx, field, PDF_NAME(V));
262 pdf_obj *ap = pdf_dict_get(ctx, field, PDF_NAME(AP));
263 pdf_obj *n = pdf_dict_get(ctx, ap, PDF_NAME(N));
264
265 /* Value does not refer to any appearance state in the
266 normal appearance stream dictionary, default to Off instead. */
267 if (pdf_is_dict(ctx, n) && !pdf_dict_get(ctx, n, leafv))
268 leafv = NULL;
269
270 if (!pdf_is_name(ctx, leafv))
271 leafv = PDF_NAME(Off);
272 pdf_dict_put(ctx, field, PDF_NAME(AS), leafv);
273 }
274 pdf_field_mark_dirty(ctx, field);
275 break;
276
277 case PDF_WIDGET_TYPE_BUTTON:
278 case PDF_WIDGET_TYPE_SIGNATURE:
279 /* Pushbuttons and signatures have no value to reset. */
280 break;
281
282 default:
283 pdf_field_mark_dirty(ctx, field);
284 break;
285 }
286 }
287 }
288
289 void pdf_field_reset(fz_context *ctx, pdf_document *doc, pdf_obj *field)
290 {
291 pdf_obj *kids = pdf_dict_get(ctx, field, PDF_NAME(Kids));
292
293 reset_form_field(ctx, doc, field);
294
295 if (kids)
296 {
297 int i, n = pdf_array_len(ctx, kids);
298
299 for (i = 0; i < n; i++)
300 pdf_field_reset(ctx, doc, pdf_array_get(ctx, kids, i));
301 }
302 }
303
304 static void add_field_hierarchy_to_array(fz_context *ctx, pdf_obj *array, pdf_obj *field, pdf_obj *fields, int exclude)
305 {
306 pdf_obj *kids = pdf_dict_get(ctx, field, PDF_NAME(Kids));
307 char *needle = pdf_load_field_name(ctx, field);
308 int i, n;
309
310 fz_try(ctx)
311 {
312 n = pdf_array_len(ctx, fields);
313 for (i = 0; i < n; i++)
314 {
315 char *name = pdf_load_field_name(ctx, pdf_array_get(ctx, fields, i));
316 int found = !strcmp(needle, name);
317 fz_free(ctx, name);
318 if (found)
319 break;
320 }
321 }
322 fz_always(ctx)
323 fz_free(ctx, needle);
324 fz_catch(ctx)
325 fz_rethrow(ctx);
326
327 if ((exclude && i < n) || (!exclude && i == n))
328 return;
329
330 pdf_array_push(ctx, array, field);
331
332 if (kids)
333 {
334 n = pdf_array_len(ctx, kids);
335
336 for (i = 0; i < n; i++)
337 add_field_hierarchy_to_array(ctx, array, pdf_array_get(ctx, kids, i), fields, exclude);
338 }
339 }
340
341 /*
342 When resetting or submitting a form, the fields to act upon are defined
343 by an array of either field references or field names, plus a flag determining
344 whether to act upon the fields in the array, or all fields other than those in
345 the array. specified_fields interprets this information and produces the array
346 of fields to be acted upon.
347 */
348 static pdf_obj *specified_fields(fz_context *ctx, pdf_document *doc, pdf_obj *fields, int exclude)
349 {
350 pdf_obj *form = pdf_dict_getl(ctx, pdf_trailer(ctx, doc), PDF_NAME(Root), PDF_NAME(AcroForm), PDF_NAME(Fields), NULL);
351 int i, n;
352 pdf_obj *result = pdf_new_array(ctx, doc, 0);
353
354 fz_try(ctx)
355 {
356 n = pdf_array_len(ctx, fields);
357
358 for (i = 0; i < n; i++)
359 {
360 pdf_obj *field = pdf_array_get(ctx, fields, i);
361
362 if (pdf_is_string(ctx, field))
363 field = pdf_lookup_field(ctx, form, pdf_to_str_buf(ctx, field));
364
365 if (field)
366 add_field_hierarchy_to_array(ctx, result, field, fields, exclude);
367 }
368 }
369 fz_catch(ctx)
370 {
371 pdf_drop_obj(ctx, result);
372 fz_rethrow(ctx);
373 }
374
375 return result;
376 }
377
378 void pdf_reset_form(fz_context *ctx, pdf_document *doc, pdf_obj *fields, int exclude)
379 {
380 pdf_obj *sfields = specified_fields(ctx, doc, fields, exclude);
381 fz_try(ctx)
382 {
383 int i, n = pdf_array_len(ctx, sfields);
384 for (i = 0; i < n; i++)
385 reset_form_field(ctx, doc, pdf_array_get(ctx, sfields, i));
386 doc->recalculate = 1;
387 }
388 fz_always(ctx)
389 pdf_drop_obj(ctx, sfields);
390 fz_catch(ctx)
391 fz_rethrow(ctx);
392 }
393
394 typedef struct
395 {
396 pdf_obj *pageobj;
397 pdf_obj *chk;
398 } lookup_state;
399
400 static void *find_widget_on_page(fz_context *ctx, fz_page *page_, void *state_)
401 {
402 lookup_state *state = (lookup_state *) state_;
403 pdf_page *page = (pdf_page *) page_;
404 pdf_annot *widget;
405
406 if (state->pageobj && pdf_objcmp_resolve(ctx, state->pageobj, page->obj))
407 return NULL;
408
409 for (widget = pdf_first_widget(ctx, page); widget != NULL; widget = pdf_next_widget(ctx, widget))
410 {
411 if (!pdf_objcmp_resolve(ctx, state->chk, widget->obj))
412 return widget;
413 }
414
415 return NULL;
416 }
417
418 static pdf_annot *find_widget(fz_context *ctx, pdf_document *doc, pdf_obj *chk)
419 {
420 lookup_state state;
421
422 state.pageobj = pdf_dict_get(ctx, chk, PDF_NAME(P));
423 state.chk = chk;
424
425 return fz_process_opened_pages(ctx, (fz_document *) doc, find_widget_on_page, &state);
426 }
427
428 static void set_check(fz_context *ctx, pdf_document *doc, pdf_obj *chk, pdf_obj *name)
429 {
430 pdf_obj *n = pdf_dict_getp(ctx, chk, "AP/N");
431 pdf_obj *val;
432
433 /* If name is a possible value of this check
434 * box then use it, otherwise use "Off" */
435 if (pdf_dict_get(ctx, n, name))
436 val = name;
437 else
438 val = PDF_NAME(Off);
439
440 if (pdf_name_eq(ctx, pdf_dict_get(ctx, chk, PDF_NAME(AS)), val))
441 return;
442
443 pdf_dict_put(ctx, chk, PDF_NAME(AS), val);
444 pdf_set_annot_has_changed(ctx, find_widget(ctx, doc, chk));
445 }
446
447 /* Set the values of all fields in a group defined by a node
448 * in the hierarchy */
449 static void set_check_grp(fz_context *ctx, pdf_document *doc, pdf_obj *grp, pdf_obj *val)
450 {
451 pdf_obj *kids = pdf_dict_get(ctx, grp, PDF_NAME(Kids));
452
453 if (kids == NULL)
454 {
455 set_check(ctx, doc, grp, val);
456 }
457 else
458 {
459 int i, n = pdf_array_len(ctx, kids);
460
461 for (i = 0; i < n; i++)
462 set_check_grp(ctx, doc, pdf_array_get(ctx, kids, i), val);
463 }
464 }
465
466 void pdf_calculate_form(fz_context *ctx, pdf_document *doc)
467 {
468 if (doc->js)
469 {
470 fz_try(ctx)
471 {
472 pdf_obj *co = pdf_dict_getp(ctx, pdf_trailer(ctx, doc), "Root/AcroForm/CO");
473 int i, n = pdf_array_len(ctx, co);
474 for (i = 0; i < n; i++)
475 {
476 pdf_obj *field = pdf_array_get(ctx, co, i);
477 pdf_field_event_calculate(ctx, doc, field);
478 }
479 }
480 fz_always(ctx)
481 doc->recalculate = 0;
482 fz_catch(ctx)
483 fz_rethrow(ctx);
484 }
485 }
486
487 static pdf_obj *find_on_state(fz_context *ctx, pdf_obj *dict)
488 {
489 int i, n = pdf_dict_len(ctx, dict);
490 for (i = 0; i < n; ++i)
491 {
492 pdf_obj *key = pdf_dict_get_key(ctx, dict, i);
493 if (key != PDF_NAME(Off))
494 return key;
495 }
496 return NULL;
497 }
498
499 pdf_obj *pdf_button_field_on_state(fz_context *ctx, pdf_obj *field)
500 {
501 pdf_obj *ap = pdf_dict_get(ctx, field, PDF_NAME(AP));
502 pdf_obj *on = find_on_state(ctx, pdf_dict_get(ctx, ap, PDF_NAME(N)));
503 if (!on) on = find_on_state(ctx, pdf_dict_get(ctx, ap, PDF_NAME(D)));
504 if (!on) on = PDF_NAME(Yes);
505 return on;
506 }
507
508 static void
509 begin_annot_op(fz_context *ctx, pdf_annot *annot, const char *op)
510 {
511 if (!annot->page)
512 fz_throw(ctx, FZ_ERROR_ARGUMENT, "annotation not bound to any page");
513
514 pdf_begin_operation(ctx, annot->page->doc, op);
515 }
516
517 static void
518 end_annot_op(fz_context *ctx, pdf_annot *annot)
519 {
520 pdf_end_operation(ctx, annot->page->doc);
521 }
522
523 static void
524 abandon_annot_op(fz_context *ctx, pdf_annot *annot)
525 {
526 pdf_abandon_operation(ctx, annot->page->doc);
527 }
528
529 static void toggle_check_box(fz_context *ctx, pdf_annot *annot)
530 {
531 pdf_document *doc = annot->page->doc;
532
533 begin_annot_op(ctx, annot, "Toggle checkbox");
534
535 fz_try(ctx)
536 {
537 pdf_obj *field = annot->obj;
538 int ff = pdf_field_flags(ctx, field);
539 int is_radio = (ff & PDF_BTN_FIELD_IS_RADIO);
540 int is_no_toggle_to_off = (ff & PDF_BTN_FIELD_IS_NO_TOGGLE_TO_OFF);
541 pdf_obj *grp, *as, *val;
542
543 grp = find_head_of_field_group(ctx, field);
544 if (!grp)
545 grp = field;
546
547 /* TODO: check V value as well as or instead of AS? */
548 as = pdf_dict_get(ctx, field, PDF_NAME(AS));
549 if (pdf_is_name(ctx, as) && !pdf_name_eq(ctx, as, PDF_NAME(Off)))
550 {
551 if (is_radio && is_no_toggle_to_off)
552 {
553 end_annot_op(ctx, annot);
554 break;
555 }
556 val = PDF_NAME(Off);
557 }
558 else
559 {
560 val = pdf_button_field_on_state(ctx, field);
561 }
562
563 pdf_dict_put(ctx, grp, PDF_NAME(V), val);
564 set_check_grp(ctx, doc, grp, val);
565 doc->recalculate = 1;
566 end_annot_op(ctx, annot);
567 }
568 fz_catch(ctx)
569 {
570 abandon_annot_op(ctx, annot);
571 fz_rethrow(ctx);
572 }
573
574 pdf_set_annot_has_changed(ctx, annot);
575 }
576
577 int pdf_has_unsaved_changes(fz_context *ctx, pdf_document *doc)
578 {
579 int i;
580
581 if (doc->num_incremental_sections == 0)
582 return 0;
583
584 for (i = 0; i < doc->xref_sections->num_objects; i++)
585 if (doc->xref_sections->subsec->table[i].type != 0)
586 break;
587 return i != doc->xref_sections->num_objects;
588 }
589
590 int pdf_was_repaired(fz_context *ctx, pdf_document *doc)
591 {
592 return doc->repair_attempted;
593 }
594
595 int pdf_toggle_widget(fz_context *ctx, pdf_annot *widget)
596 {
597 switch (pdf_widget_type(ctx, widget))
598 {
599 default:
600 return 0;
601 case PDF_WIDGET_TYPE_CHECKBOX:
602 case PDF_WIDGET_TYPE_RADIOBUTTON:
603 toggle_check_box(ctx, widget);
604 return 1;
605 }
606 }
607
608 int
609 pdf_update_page(fz_context *ctx, pdf_page *page)
610 {
611 pdf_annot *annot;
612 pdf_annot *widget;
613 int changed = 0;
614
615 fz_try(ctx)
616 {
617 pdf_begin_implicit_operation(ctx, page->doc);
618 if (page->doc->recalculate)
619 pdf_calculate_form(ctx, page->doc);
620
621 for (annot = page->annots; annot; annot = annot->next)
622 if (pdf_update_annot(ctx, annot))
623 changed = 1;
624 for (widget = page->widgets; widget; widget = widget->next)
625 if (pdf_update_annot(ctx, widget))
626 changed = 1;
627 pdf_end_operation(ctx, page->doc);
628 }
629 fz_catch(ctx)
630 {
631 pdf_abandon_operation(ctx, page->doc);
632 fz_rethrow(ctx);
633 }
634
635 return changed;
636 }
637
638 pdf_annot *pdf_first_widget(fz_context *ctx, pdf_page *page)
639 {
640 return page->widgets;
641 }
642
643 pdf_annot *pdf_next_widget(fz_context *ctx, pdf_annot *widget)
644 {
645 return widget->next;
646 }
647
648 enum pdf_widget_type pdf_widget_type(fz_context *ctx, pdf_annot *widget)
649 {
650 enum pdf_widget_type ret = PDF_WIDGET_TYPE_BUTTON;
651
652 pdf_annot_push_local_xref(ctx, widget);
653
654 fz_try(ctx)
655 {
656 pdf_obj *subtype = pdf_dict_get(ctx, widget->obj, PDF_NAME(Subtype));
657 if (pdf_name_eq(ctx, subtype, PDF_NAME(Widget)))
658 ret = pdf_field_type(ctx, widget->obj);
659 }
660 fz_always(ctx)
661 pdf_annot_pop_local_xref(ctx, widget);
662 fz_catch(ctx)
663 fz_rethrow(ctx);
664
665 return ret;
666 }
667
668 static int set_validated_field_value(fz_context *ctx, pdf_document *doc, pdf_obj *field, const char *text, int ignore_trigger_events)
669 {
670 char *newtext = NULL;
671
672 if (!ignore_trigger_events)
673 {
674 if (!pdf_field_event_validate(ctx, doc, field, text, &newtext))
675 return 0;
676 }
677
678 update_field_value(ctx, doc, field, newtext ? newtext : text);
679
680 fz_free(ctx, newtext);
681
682 return 1;
683 }
684
685 static void update_checkbox_selector(fz_context *ctx, pdf_document *doc, pdf_obj *field, const char *val)
686 {
687 pdf_obj *kids = pdf_dict_get(ctx, field, PDF_NAME(Kids));
688
689 if (kids)
690 {
691 int i, n = pdf_array_len(ctx, kids);
692
693 for (i = 0; i < n; i++)
694 update_checkbox_selector(ctx, doc, pdf_array_get(ctx, kids, i), val);
695 }
696 else
697 {
698 pdf_obj *n = pdf_dict_getp(ctx, field, "AP/N");
699 pdf_obj *oval;
700
701 if (pdf_dict_gets(ctx, n, val))
702 oval = pdf_new_name(ctx, val);
703 else
704 oval = PDF_NAME(Off);
705 pdf_dict_put_drop(ctx, field, PDF_NAME(AS), oval);
706 }
707 }
708
709 static int set_checkbox_value(fz_context *ctx, pdf_document *doc, pdf_obj *field, const char *val)
710 {
711 update_checkbox_selector(ctx, doc, field, val);
712 update_field_value(ctx, doc, field, val);
713 return 1;
714 }
715
716 int pdf_set_field_value(fz_context *ctx, pdf_document *doc, pdf_obj *field, const char *text, int ignore_trigger_events)
717 {
718 int accepted = 0;
719
720 switch (pdf_field_type(ctx, field))
721 {
722 case PDF_WIDGET_TYPE_TEXT:
723 case PDF_WIDGET_TYPE_COMBOBOX:
724 case PDF_WIDGET_TYPE_LISTBOX:
725 accepted = set_validated_field_value(ctx, doc, field, text, ignore_trigger_events);
726 break;
727
728 case PDF_WIDGET_TYPE_CHECKBOX:
729 case PDF_WIDGET_TYPE_RADIOBUTTON:
730 accepted = set_checkbox_value(ctx, doc, field, text);
731 break;
732
733 default:
734 update_field_value(ctx, doc, field, text);
735 accepted = 1;
736 break;
737 }
738
739 if (!ignore_trigger_events)
740 doc->recalculate = 1;
741
742 return accepted;
743 }
744
745 char *pdf_field_border_style(fz_context *ctx, pdf_obj *field)
746 {
747 const char *bs = pdf_to_name(ctx, pdf_dict_getl(ctx, field, PDF_NAME(BS), PDF_NAME(S), NULL));
748 switch (*bs)
749 {
750 case 'S': return "Solid";
751 case 'D': return "Dashed";
752 case 'B': return "Beveled";
753 case 'I': return "Inset";
754 case 'U': return "Underline";
755 }
756 return "Solid";
757 }
758
759 void pdf_field_set_border_style(fz_context *ctx, pdf_obj *field, const char *text)
760 {
761 pdf_obj *val;
762
763 if (!strcmp(text, "Solid"))
764 val = PDF_NAME(S);
765 else if (!strcmp(text, "Dashed"))
766 val = PDF_NAME(D);
767 else if (!strcmp(text, "Beveled"))
768 val = PDF_NAME(B);
769 else if (!strcmp(text, "Inset"))
770 val = PDF_NAME(I);
771 else if (!strcmp(text, "Underline"))
772 val = PDF_NAME(U);
773 else
774 return;
775
776 pdf_dict_putl_drop(ctx, field, val, PDF_NAME(BS), PDF_NAME(S), NULL);
777 pdf_field_mark_dirty(ctx, field);
778 }
779
780 void pdf_field_set_button_caption(fz_context *ctx, pdf_obj *field, const char *text)
781 {
782 if (pdf_field_type(ctx, field) == PDF_WIDGET_TYPE_BUTTON)
783 {
784 pdf_obj *val = pdf_new_text_string(ctx, text);
785 pdf_dict_putl_drop(ctx, field, val, PDF_NAME(MK), PDF_NAME(CA), NULL);
786 pdf_field_mark_dirty(ctx, field);
787 }
788 }
789
790 int pdf_field_display(fz_context *ctx, pdf_obj *field)
791 {
792 pdf_obj *kids;
793 int f, res = Display_Visible;
794
795 /* Base response on first of children. Not ideal,
796 * but not clear how to handle children with
797 * differing values */
798 while ((kids = pdf_dict_get(ctx, field, PDF_NAME(Kids))) != NULL)
799 field = pdf_array_get(ctx, kids, 0);
800
801 f = pdf_dict_get_int(ctx, field, PDF_NAME(F));
802
803 if (f & PDF_ANNOT_IS_HIDDEN)
804 {
805 res = Display_Hidden;
806 }
807 else if (f & PDF_ANNOT_IS_PRINT)
808 {
809 if (f & PDF_ANNOT_IS_NO_VIEW)
810 res = Display_NoView;
811 }
812 else
813 {
814 if (f & PDF_ANNOT_IS_NO_VIEW)
815 res = Display_Hidden;
816 else
817 res = Display_NoPrint;
818 }
819
820 return res;
821 }
822
823 /*
824 * get the field name in a char buffer that has spare room to
825 * add more characters at the end.
826 */
827 static char *load_field_name(fz_context *ctx, pdf_obj *field, int spare, pdf_cycle_list *cycle_up)
828 {
829 pdf_cycle_list cycle;
830 char *res = NULL;
831 pdf_obj *parent;
832 const char *lname;
833 int llen;
834
835 if (pdf_cycle(ctx, &cycle, cycle_up, field))
836 fz_throw(ctx, FZ_ERROR_FORMAT, "Cycle in field parents");
837
838 parent = pdf_dict_get(ctx, field, PDF_NAME(Parent));
839 lname = pdf_dict_get_text_string(ctx, field, PDF_NAME(T));
840 llen = (int)strlen(lname);
841
842 // Limit fields to 16K
843 if (llen > (16 << 10) || llen + spare > (16 << 10))
844 fz_throw(ctx, FZ_ERROR_LIMIT, "Field name too long");
845
846 /*
847 * If we found a name at this point in the field hierarchy
848 * then we'll need extra space for it and a dot
849 */
850 if (llen)
851 spare += llen+1;
852
853 if (parent)
854 {
855 res = load_field_name(ctx, parent, spare, &cycle);
856 }
857 else
858 {
859 res = Memento_label(fz_malloc(ctx, spare+1), "form_field_name");
860 res[0] = 0;
861 }
862
863 if (llen)
864 {
865 if (res[0])
866 strcat(res, ".");
867
868 strcat(res, lname);
869 }
870
871 return res;
872 }
873
874 char *pdf_load_field_name(fz_context *ctx, pdf_obj *field)
875 {
876 return load_field_name(ctx, field, 0, NULL);
877 }
878
879 void pdf_create_field_name(fz_context *ctx, pdf_document *doc, const char *prefix, char *buf, size_t len)
880 {
881 pdf_obj *form = pdf_dict_getl(ctx, pdf_trailer(ctx, doc),
882 PDF_NAME(Root), PDF_NAME(AcroForm), PDF_NAME(Fields), NULL);
883 int i;
884 for (i = 0; i < 65536; ++i) {
885 fz_snprintf(buf, len, "%s%d", prefix, i);
886 if (!pdf_lookup_field(ctx, form, buf))
887 return;
888 }
889 fz_throw(ctx, FZ_ERROR_LIMIT, "Could not create unique field name.");
890 }
891
892 const char *pdf_field_label(fz_context *ctx, pdf_obj *field)
893 {
894 pdf_obj *label = pdf_dict_get_inheritable(ctx, field, PDF_NAME(TU));
895 if (!label)
896 label = pdf_dict_get_inheritable(ctx, field, PDF_NAME(T));
897 if (label)
898 return pdf_to_text_string(ctx, label);
899 return "Unnamed";
900 }
901
902 void pdf_field_set_display(fz_context *ctx, pdf_obj *field, int d)
903 {
904 pdf_obj *kids = pdf_dict_get(ctx, field, PDF_NAME(Kids));
905
906 if (!kids)
907 {
908 int mask = (PDF_ANNOT_IS_HIDDEN|PDF_ANNOT_IS_PRINT|PDF_ANNOT_IS_NO_VIEW);
909 int f = pdf_dict_get_int(ctx, field, PDF_NAME(F)) & ~mask;
910
911 switch (d)
912 {
913 case Display_Visible:
914 f |= PDF_ANNOT_IS_PRINT;
915 break;
916 case Display_Hidden:
917 f |= PDF_ANNOT_IS_HIDDEN;
918 break;
919 case Display_NoView:
920 f |= (PDF_ANNOT_IS_PRINT|PDF_ANNOT_IS_NO_VIEW);
921 break;
922 case Display_NoPrint:
923 break;
924 }
925
926 pdf_dict_put_int(ctx, field, PDF_NAME(F), f);
927 }
928 else
929 {
930 int i, n = pdf_array_len(ctx, kids);
931
932 for (i = 0; i < n; i++)
933 pdf_field_set_display(ctx, pdf_array_get(ctx, kids, i), d);
934 }
935 }
936
937 void pdf_field_set_fill_color(fz_context *ctx, pdf_obj *field, pdf_obj *col)
938 {
939 /* col == NULL mean transparent, but we can simply pass it on as with
940 * non-NULL values because pdf_dict_putp interprets a NULL value as
941 * delete */
942 pdf_dict_putl(ctx, field, col, PDF_NAME(MK), PDF_NAME(BG), NULL);
943 pdf_field_mark_dirty(ctx, field);
944 }
945
946 void pdf_field_set_text_color(fz_context *ctx, pdf_obj *field, pdf_obj *col)
947 {
948 char buf[100];
949 const char *font;
950 float size, color[4];
951 /* TODO? */
952 const char *da = pdf_to_str_buf(ctx, pdf_dict_get_inheritable(ctx, field, PDF_NAME(DA)));
953 int n;
954
955 pdf_parse_default_appearance(ctx, da, &font, &size, &n, color);
956
957 switch (pdf_array_len(ctx, col))
958 {
959 default:
960 n = 0;
961 color[0] = color[1] = color[2] = color[3] = 0;
962 break;
963 case 1:
964 n = 1;
965 color[0] = pdf_array_get_real(ctx, col, 0);
966 break;
967 case 3:
968 n = 3;
969 color[0] = pdf_array_get_real(ctx, col, 0);
970 color[1] = pdf_array_get_real(ctx, col, 1);
971 color[2] = pdf_array_get_real(ctx, col, 2);
972 break;
973 case 4:
974 n = 4;
975 color[0] = pdf_array_get_real(ctx, col, 0);
976 color[1] = pdf_array_get_real(ctx, col, 1);
977 color[2] = pdf_array_get_real(ctx, col, 2);
978 color[3] = pdf_array_get_real(ctx, col, 3);
979 break;
980 }
981
982 pdf_print_default_appearance(ctx, buf, sizeof buf, font, size, n, color);
983 pdf_dict_put_string(ctx, field, PDF_NAME(DA), buf, strlen(buf));
984 pdf_field_mark_dirty(ctx, field);
985 }
986
987 pdf_annot *
988 pdf_keep_widget(fz_context *ctx, pdf_annot *widget)
989 {
990 return pdf_keep_annot(ctx, widget);
991 }
992
993 void
994 pdf_drop_widget(fz_context *ctx, pdf_annot *widget)
995 {
996 pdf_drop_annot(ctx, widget);
997 }
998
999 void
1000 pdf_drop_widgets(fz_context *ctx, pdf_annot *widget)
1001 {
1002 while (widget)
1003 {
1004 pdf_annot *next = widget->next;
1005 pdf_drop_widget(ctx, widget);
1006 widget = next;
1007 }
1008 }
1009
1010 pdf_annot *
1011 pdf_create_signature_widget(fz_context *ctx, pdf_page *page, char *name)
1012 {
1013 fz_rect rect = { 12, 12, 12+100, 12+50 };
1014 pdf_annot *annot;
1015
1016 pdf_begin_operation(ctx, page->doc, "Create signature");
1017
1018 annot = pdf_create_annot_raw(ctx, page, PDF_ANNOT_WIDGET);
1019
1020 fz_try(ctx)
1021 {
1022 pdf_obj *obj = annot->obj;
1023 pdf_obj *root = pdf_dict_get(ctx, pdf_trailer(ctx, page->doc), PDF_NAME(Root));
1024 pdf_obj *acroform = pdf_dict_get(ctx, root, PDF_NAME(AcroForm));
1025 pdf_obj *fields, *lock;
1026 if (!acroform)
1027 {
1028 acroform = pdf_new_dict(ctx, page->doc, 1);
1029 pdf_dict_put_drop(ctx, root, PDF_NAME(AcroForm), acroform);
1030 }
1031 fields = pdf_dict_get(ctx, acroform, PDF_NAME(Fields));
1032 if (!fields)
1033 {
1034 fields = pdf_new_array(ctx, page->doc, 1);
1035 pdf_dict_put_drop(ctx, acroform, PDF_NAME(Fields), fields);
1036 }
1037 pdf_set_annot_rect(ctx, annot, rect);
1038 pdf_dict_put(ctx, obj, PDF_NAME(FT), PDF_NAME(Sig));
1039 pdf_dict_put_int(ctx, obj, PDF_NAME(F), PDF_ANNOT_IS_PRINT);
1040 pdf_dict_put_text_string(ctx, obj, PDF_NAME(DA), "/Helv 0 Tf 0 g");
1041 pdf_dict_put_text_string(ctx, obj, PDF_NAME(T), name);
1042 pdf_array_push(ctx, fields, obj);
1043 lock = pdf_dict_put_dict(ctx, obj, PDF_NAME(Lock), 1);
1044 pdf_dict_put(ctx, lock, PDF_NAME(Action), PDF_NAME(All));
1045 pdf_end_operation(ctx, page->doc);
1046 }
1047 fz_catch(ctx)
1048 {
1049 pdf_abandon_operation(ctx, page->doc);
1050 pdf_delete_annot(ctx, page, annot);
1051 }
1052 return (pdf_annot *)annot;
1053 }
1054
1055 fz_rect
1056 pdf_bound_widget(fz_context *ctx, pdf_annot *widget)
1057 {
1058 return pdf_bound_annot(ctx, widget);
1059 }
1060
1061 int
1062 pdf_update_widget(fz_context *ctx, pdf_annot *widget)
1063 {
1064 return pdf_update_annot(ctx, widget);
1065 }
1066
1067 int pdf_text_widget_max_len(fz_context *ctx, pdf_annot *tw)
1068 {
1069 pdf_annot *annot = (pdf_annot *)tw;
1070 return pdf_dict_get_inheritable_int(ctx, annot->obj, PDF_NAME(MaxLen));
1071 }
1072
1073 int pdf_text_widget_format(fz_context *ctx, pdf_annot *tw)
1074 {
1075 pdf_annot *annot = (pdf_annot *)tw;
1076 int type = PDF_WIDGET_TX_FORMAT_NONE;
1077 pdf_obj *js = pdf_dict_getl(ctx, annot->obj, PDF_NAME(AA), PDF_NAME(F), PDF_NAME(JS), NULL);
1078 if (js)
1079 {
1080 char *code = pdf_load_stream_or_string_as_utf8(ctx, js);
1081 if (strstr(code, "AFNumber_Format"))
1082 type = PDF_WIDGET_TX_FORMAT_NUMBER;
1083 else if (strstr(code, "AFSpecial_Format"))
1084 type = PDF_WIDGET_TX_FORMAT_SPECIAL;
1085 else if (strstr(code, "AFDate_FormatEx"))
1086 type = PDF_WIDGET_TX_FORMAT_DATE;
1087 else if (strstr(code, "AFTime_FormatEx"))
1088 type = PDF_WIDGET_TX_FORMAT_TIME;
1089 fz_free(ctx, code);
1090 }
1091
1092 return type;
1093 }
1094
1095 static char *
1096 merge_changes(fz_context *ctx, const char *value, int start, int end, const char *change)
1097 {
1098 int changelen = change ? (int)strlen(change) : 0;
1099 int valuelen = value ? (int)strlen(value) : 0;
1100 int prelen = (start >= 0 ? (start < valuelen ? start : valuelen) : 0);
1101 int postlen = (end >= 0 && end <= valuelen ? valuelen - end : 0);
1102 int newlen = prelen + changelen + postlen + 1;
1103 char *merged = fz_malloc(ctx, newlen);
1104 char *m = merged;
1105
1106 if (prelen)
1107 {
1108 memcpy(m, value, prelen);
1109 m += prelen;
1110 }
1111 if (changelen)
1112 {
1113 memcpy(m, change, changelen);
1114 m += changelen;
1115 }
1116 if (postlen)
1117 {
1118 memcpy(m, &value[end], postlen);
1119 m += postlen;
1120 }
1121 *m = 0;
1122
1123 return merged;
1124 }
1125
1126 int pdf_set_text_field_value(fz_context *ctx, pdf_annot *widget, const char *update)
1127 {
1128 pdf_document *doc;
1129 pdf_keystroke_event evt = { 0 };
1130 char *new_change = NULL;
1131 char *new_value = NULL;
1132 char *merged_value = NULL;
1133 int rc = 1;
1134
1135 begin_annot_op(ctx, widget, "Edit text field");
1136 doc = widget->page->doc;
1137
1138 fz_var(new_value);
1139 fz_var(new_change);
1140 fz_var(merged_value);
1141 fz_try(ctx)
1142 {
1143 if (!widget->ignore_trigger_events)
1144 {
1145 evt.value = pdf_annot_field_value(ctx, widget);
1146 evt.change = update;
1147 evt.selStart = 0;
1148 evt.selEnd = (int)strlen(evt.value);
1149 evt.willCommit = 0;
1150 rc = pdf_annot_field_event_keystroke(ctx, doc, widget, &evt);
1151 new_change = evt.newChange;
1152 new_value = evt.newValue;
1153 evt.newValue = NULL;
1154 evt.newChange = NULL;
1155 if (rc)
1156 {
1157 merged_value = merge_changes(ctx, new_value, evt.selStart, evt.selEnd, new_change);
1158 evt.value = merged_value;
1159 evt.change = "";
1160 evt.selStart = -1;
1161 evt.selEnd = -1;
1162 evt.willCommit = 1;
1163 rc = pdf_annot_field_event_keystroke(ctx, doc, widget, &evt);
1164 if (rc)
1165 rc = pdf_set_annot_field_value(ctx, doc, widget, evt.newValue, 0);
1166 }
1167 }
1168 else
1169 {
1170 rc = pdf_set_annot_field_value(ctx, doc, widget, update, 1);
1171 }
1172 end_annot_op(ctx, widget);
1173 }
1174 fz_always(ctx)
1175 {
1176 fz_free(ctx, new_value);
1177 fz_free(ctx, evt.newValue);
1178 fz_free(ctx, new_change);
1179 fz_free(ctx, evt.newChange);
1180 fz_free(ctx, merged_value);
1181 }
1182 fz_catch(ctx)
1183 {
1184 abandon_annot_op(ctx, widget);
1185 fz_warn(ctx, "could not set widget text");
1186 rc = 0;
1187 }
1188 return rc;
1189 }
1190
1191 int pdf_edit_text_field_value(fz_context *ctx, pdf_annot *widget, const char *value, const char *change, int *selStart, int *selEnd, char **result)
1192 {
1193 pdf_document *doc = widget->page->doc;
1194 pdf_keystroke_event evt = {0};
1195 int rc = 1;
1196
1197 pdf_begin_operation(ctx, doc, "Text field keystroke");
1198
1199 fz_try(ctx)
1200 {
1201 if (!widget->ignore_trigger_events)
1202 {
1203 evt.value = value;
1204 evt.change = change;
1205 evt.selStart = *selStart;
1206 evt.selEnd = *selEnd;
1207 evt.willCommit = 0;
1208 rc = pdf_annot_field_event_keystroke(ctx, doc, widget, &evt);
1209 if (rc)
1210 {
1211 *result = merge_changes(ctx, evt.newValue, evt.selStart, evt.selEnd, evt.newChange);
1212 *selStart = evt.selStart + (int)strlen(evt.newChange);
1213 *selEnd = *selStart;
1214 }
1215 }
1216 else
1217 {
1218 *result = merge_changes(ctx, value, *selStart, *selEnd, change);
1219 *selStart = evt.selStart + (int)strlen(change);
1220 *selEnd = *selStart;
1221 }
1222 pdf_end_operation(ctx, doc);
1223 }
1224 fz_always(ctx)
1225 {
1226 fz_free(ctx, evt.newValue);
1227 fz_free(ctx, evt.newChange);
1228 }
1229 fz_catch(ctx)
1230 {
1231 pdf_abandon_operation(ctx, doc);
1232 fz_warn(ctx, "could not process text widget keystroke");
1233 rc = 0;
1234 }
1235 return rc;
1236 }
1237
1238 int pdf_set_choice_field_value(fz_context *ctx, pdf_annot *widget, const char *new_value)
1239 {
1240 /* Choice widgets use almost the same keystroke processing as text fields. */
1241 return pdf_set_text_field_value(ctx, widget, new_value);
1242 }
1243
1244 int pdf_choice_widget_options(fz_context *ctx, pdf_annot *tw, int exportval, const char *opts[])
1245 {
1246 pdf_annot *annot = (pdf_annot *)tw;
1247 pdf_obj *optarr;
1248 int i, n, m;
1249
1250 optarr = pdf_dict_get_inheritable(ctx, annot->obj, PDF_NAME(Opt));
1251 n = pdf_array_len(ctx, optarr);
1252
1253 if (opts)
1254 {
1255 for (i = 0; i < n; i++)
1256 {
1257 m = pdf_array_len(ctx, pdf_array_get(ctx, optarr, i));
1258 /* If it is a two element array, the second item is the one that we want if we want the listing value. */
1259 if (m == 2)
1260 if (exportval)
1261 opts[i] = pdf_array_get_text_string(ctx, pdf_array_get(ctx, optarr, i), 0);
1262 else
1263 opts[i] = pdf_array_get_text_string(ctx, pdf_array_get(ctx, optarr, i), 1);
1264 else
1265 opts[i] = pdf_array_get_text_string(ctx, optarr, i);
1266 }
1267 }
1268 return n;
1269 }
1270
1271 int pdf_choice_field_option_count(fz_context *ctx, pdf_obj *field)
1272 {
1273 pdf_obj *opt = pdf_dict_get_inheritable(ctx, field, PDF_NAME(Opt));
1274 return pdf_array_len(ctx, opt);
1275 }
1276
1277 const char *pdf_choice_field_option(fz_context *ctx, pdf_obj *field, int export, int i)
1278 {
1279 pdf_obj *opt = pdf_dict_get_inheritable(ctx, field, PDF_NAME(Opt));
1280 pdf_obj *ent = pdf_array_get(ctx, opt, i);
1281 if (pdf_array_len(ctx, ent) == 2)
1282 return pdf_array_get_text_string(ctx, ent, export ? 0 : 1);
1283 else
1284 return pdf_to_text_string(ctx, ent);
1285 }
1286
1287 int pdf_choice_widget_is_multiselect(fz_context *ctx, pdf_annot *tw)
1288 {
1289 pdf_annot *annot = (pdf_annot *)tw;
1290
1291 if (!annot) return 0;
1292
1293 switch (pdf_field_type(ctx, annot->obj))
1294 {
1295 case PDF_WIDGET_TYPE_LISTBOX:
1296 return (pdf_field_flags(ctx, annot->obj) & PDF_CH_FIELD_IS_MULTI_SELECT) != 0;
1297 default:
1298 return 0;
1299 }
1300 }
1301
1302 int pdf_choice_widget_value(fz_context *ctx, pdf_annot *tw, const char *opts[])
1303 {
1304 pdf_annot *annot = (pdf_annot *)tw;
1305 pdf_obj *optarr;
1306 int i, n;
1307
1308 if (!annot)
1309 return 0;
1310
1311 optarr = pdf_dict_get(ctx, annot->obj, PDF_NAME(V));
1312
1313 if (pdf_is_string(ctx, optarr))
1314 {
1315 if (opts)
1316 opts[0] = pdf_to_text_string(ctx, optarr);
1317 return 1;
1318 }
1319 else
1320 {
1321 n = pdf_array_len(ctx, optarr);
1322 if (opts)
1323 {
1324 for (i = 0; i < n; i++)
1325 {
1326 pdf_obj *elem = pdf_array_get(ctx, optarr, i);
1327 if (pdf_is_array(ctx, elem))
1328 elem = pdf_array_get(ctx, elem, 1);
1329 opts[i] = pdf_to_text_string(ctx, elem);
1330 }
1331 }
1332 return n;
1333 }
1334 }
1335
1336 void pdf_choice_widget_set_value(fz_context *ctx, pdf_annot *tw, int n, const char *opts[])
1337 {
1338 pdf_annot *annot = (pdf_annot *)tw;
1339 pdf_obj *optarr = NULL;
1340 int i;
1341
1342 if (!annot)
1343 return;
1344
1345 begin_annot_op(ctx, annot, "Set choice");
1346
1347 fz_var(optarr);
1348 fz_try(ctx)
1349 {
1350 if (n != 1)
1351 {
1352 optarr = pdf_new_array(ctx, annot->page->doc, n);
1353
1354 for (i = 0; i < n; i++)
1355 pdf_array_push_text_string(ctx, optarr, opts[i]);
1356
1357 pdf_dict_put_drop(ctx, annot->obj, PDF_NAME(V), optarr);
1358 }
1359 else
1360 pdf_dict_put_text_string(ctx, annot->obj, PDF_NAME(V), opts[0]);
1361
1362 /* FIXME: when n > 1, we should be regenerating the indexes */
1363 pdf_dict_del(ctx, annot->obj, PDF_NAME(I));
1364
1365 pdf_field_mark_dirty(ctx, annot->obj);
1366 end_annot_op(ctx, annot);
1367 }
1368 fz_catch(ctx)
1369 {
1370 abandon_annot_op(ctx, annot);
1371 pdf_drop_obj(ctx, optarr);
1372 fz_rethrow(ctx);
1373 }
1374 }
1375
1376 int pdf_signature_byte_range(fz_context *ctx, pdf_document *doc, pdf_obj *signature, fz_range *byte_range)
1377 {
1378 pdf_obj *br = pdf_dict_getl(ctx, signature, PDF_NAME(V), PDF_NAME(ByteRange), NULL);
1379 int i, n = pdf_array_len(ctx, br)/2;
1380
1381 if (byte_range)
1382 {
1383 for (i = 0; i < n; i++)
1384 {
1385 int64_t offset = pdf_array_get_int(ctx, br, 2*i);
1386 int length = pdf_array_get_int(ctx, br, 2*i+1);
1387
1388 if (offset < 0 || offset > doc->file_size)
1389 fz_throw(ctx, FZ_ERROR_FORMAT, "offset of signature byte range outside of file");
1390 else if (length < 0)
1391 fz_throw(ctx, FZ_ERROR_FORMAT, "length of signature byte range negative");
1392 else if (offset + length > doc->file_size)
1393 fz_throw(ctx, FZ_ERROR_FORMAT, "signature byte range extends past end of file");
1394
1395 byte_range[i].offset = offset;
1396 byte_range[i].length = length;
1397 }
1398 }
1399
1400 return n;
1401 }
1402
1403 static int is_white(int c)
1404 {
1405 return c == '\x00' || c == '\x09' || c == '\x0a' || c == '\x0c' || c == '\x0d' || c == '\x20';
1406 }
1407
1408 static int is_hex_or_white(int c)
1409 {
1410 return (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f') || (c >= '0' && c <= '9') || is_white(c);
1411 }
1412
1413 static void validate_certificate_data(fz_context *ctx, pdf_document *doc, fz_range *hole)
1414 {
1415 fz_stream *stm;
1416 int c;
1417
1418 stm = fz_open_range_filter(ctx, doc->file, hole, 1);
1419 fz_try(ctx)
1420 {
1421 while (is_white((c = fz_read_byte(ctx, stm))))
1422 ;
1423
1424 if (c == '<')
1425 c = fz_read_byte(ctx, stm);
1426
1427 while (is_hex_or_white(c))
1428 c = fz_read_byte(ctx, stm);
1429
1430 if (c == '>')
1431 c = fz_read_byte(ctx, stm);
1432
1433 while (is_white(c))
1434 c = fz_read_byte(ctx, stm);
1435
1436 if (c != EOF)
1437 fz_throw(ctx, FZ_ERROR_FORMAT, "signature certificate data contains invalid character");
1438 if ((size_t)fz_tell(ctx, stm) != hole->length)
1439 fz_throw(ctx, FZ_ERROR_FORMAT, "premature end of signature certificate data");
1440 }
1441 fz_always(ctx)
1442 fz_drop_stream(ctx, stm);
1443 fz_catch(ctx)
1444 fz_rethrow(ctx);
1445 }
1446
1447 static int rangecmp(const void *a_, const void *b_)
1448 {
1449 const fz_range *a = (const fz_range *) a_;
1450 const fz_range *b = (const fz_range *) b_;
1451 return (int) (a->offset - b->offset);
1452 }
1453
1454 static void validate_byte_ranges(fz_context *ctx, pdf_document *doc, fz_range *unsorted, int nranges)
1455 {
1456 int64_t offset = 0;
1457 fz_range *sorted;
1458 int i;
1459
1460 sorted = fz_calloc(ctx, nranges, sizeof(*sorted));
1461 memcpy(sorted, unsorted, nranges * sizeof(*sorted));
1462 qsort(sorted, nranges, sizeof(*sorted), rangecmp);
1463
1464 fz_try(ctx)
1465 {
1466 offset = 0;
1467
1468 for (i = 0; i < nranges; i++)
1469 {
1470 if (sorted[i].offset > offset)
1471 {
1472 fz_range hole;
1473
1474 hole.offset = offset;
1475 hole.length = sorted[i].offset - offset;
1476
1477 validate_certificate_data(ctx, doc, &hole);
1478 }
1479
1480 offset = fz_maxi64(offset, sorted[i].offset + sorted[i].length);
1481 }
1482 }
1483 fz_always(ctx)
1484 fz_free(ctx, sorted);
1485 fz_catch(ctx)
1486 fz_rethrow(ctx);
1487 }
1488
1489 fz_stream *pdf_signature_hash_bytes(fz_context *ctx, pdf_document *doc, pdf_obj *signature)
1490 {
1491 fz_range *byte_range = NULL;
1492 int byte_range_len;
1493 fz_stream *bytes = NULL;
1494
1495 fz_var(byte_range);
1496 fz_try(ctx)
1497 {
1498 byte_range_len = pdf_signature_byte_range(ctx, doc, signature, NULL);
1499 if (byte_range_len)
1500 {
1501 byte_range = fz_calloc(ctx, byte_range_len, sizeof(*byte_range));
1502 pdf_signature_byte_range(ctx, doc, signature, byte_range);
1503 }
1504
1505 validate_byte_ranges(ctx, doc, byte_range, byte_range_len);
1506 bytes = fz_open_range_filter(ctx, doc->file, byte_range, byte_range_len);
1507 }
1508 fz_always(ctx)
1509 {
1510 fz_free(ctx, byte_range);
1511 }
1512 fz_catch(ctx)
1513 {
1514 fz_rethrow(ctx);
1515 }
1516
1517 return bytes;
1518 }
1519
1520 int pdf_incremental_change_since_signing_widget(fz_context *ctx, pdf_annot *widget)
1521 {
1522 if (!widget->page)
1523 fz_throw(ctx, FZ_ERROR_ARGUMENT, "annotation not bound to any page");
1524 return pdf_signature_incremental_change_since_signing(ctx, widget->page->doc, widget->obj);
1525 }
1526
1527 int pdf_signature_incremental_change_since_signing(fz_context *ctx, pdf_document *doc, pdf_obj *signature)
1528 {
1529 fz_range *byte_range = NULL;
1530 int byte_range_len;
1531 int changed = 0;
1532
1533 if (pdf_dict_get_inheritable(ctx, signature, PDF_NAME(FT)) != PDF_NAME(Sig))
1534 fz_throw(ctx, FZ_ERROR_ARGUMENT, "annotation is not a signature widget");
1535 if (!pdf_signature_is_signed(ctx, doc, signature))
1536 return 0;
1537
1538 fz_var(byte_range);
1539 fz_try(ctx)
1540 {
1541 byte_range_len = pdf_signature_byte_range(ctx, doc, signature, NULL);
1542 if (byte_range_len)
1543 {
1544 fz_range *last_range;
1545 int64_t end_of_range;
1546
1547 byte_range = fz_calloc(ctx, byte_range_len, sizeof(*byte_range));
1548 pdf_signature_byte_range(ctx, doc, signature, byte_range);
1549
1550 last_range = &byte_range[byte_range_len -1];
1551 end_of_range = last_range->offset + last_range->length;
1552
1553 /* We can see how long the document was when signed by inspecting the byte
1554 * ranges of the signature. The document, when read in, may have already
1555 * had changes tagged on to it, past its extent when signed, or we may have
1556 * made changes since reading it, which will be held in a new incremental
1557 * xref section. */
1558 if (doc->file_size > end_of_range || doc->num_incremental_sections > 0)
1559 changed = 1;
1560 }
1561 }
1562 fz_always(ctx)
1563 {
1564 fz_free(ctx, byte_range);
1565 }
1566 fz_catch(ctx)
1567 {
1568 fz_rethrow(ctx);
1569 }
1570
1571 return changed;
1572 }
1573
1574 int pdf_signature_is_signed(fz_context *ctx, pdf_document *doc, pdf_obj *field)
1575 {
1576 pdf_obj *v;
1577 pdf_obj* vtype;
1578
1579 if (pdf_dict_get_inheritable(ctx, field, PDF_NAME(FT)) != PDF_NAME(Sig))
1580 return 0;
1581 /* Signatures can only be signed if the value is a dictionary,
1582 * and if the value has a Type, it should be Sig. */
1583 v = pdf_dict_get_inheritable(ctx, field, PDF_NAME(V));
1584 vtype = pdf_dict_get(ctx, v, PDF_NAME(Type));
1585 return pdf_is_dict(ctx, v) && (vtype ? pdf_name_eq(ctx, vtype, PDF_NAME(Sig)) : 1);
1586 }
1587
1588 int pdf_widget_is_signed(fz_context *ctx, pdf_annot *widget)
1589 {
1590 if (widget == NULL)
1591 return 0;
1592
1593 if (!widget->page)
1594 fz_throw(ctx, FZ_ERROR_ARGUMENT, "annotation not bound to any page");
1595
1596 return pdf_signature_is_signed(ctx, widget->page->doc, widget->obj);
1597 }
1598
1599 int pdf_widget_is_readonly(fz_context *ctx, pdf_annot *widget)
1600 {
1601 int fflags;
1602 if (widget == NULL)
1603 return 0;
1604 fflags = pdf_field_flags(ctx, ((pdf_annot *) widget)->obj);
1605 return fflags & PDF_FIELD_IS_READ_ONLY;
1606 }
1607
1608 size_t pdf_signature_contents(fz_context *ctx, pdf_document *doc, pdf_obj *signature, char **contents)
1609 {
1610 pdf_obj *v_ref = pdf_dict_get_inheritable(ctx, signature, PDF_NAME(V));
1611 pdf_obj *v_obj = pdf_load_unencrypted_object(ctx, doc, pdf_to_num(ctx, v_ref));
1612 char *copy = NULL;
1613 size_t len;
1614
1615 fz_var(copy);
1616 fz_try(ctx)
1617 {
1618 pdf_obj *c = pdf_dict_get(ctx, v_obj, PDF_NAME(Contents));
1619 char *s;
1620
1621 s = pdf_to_str_buf(ctx, c);
1622 len = pdf_to_str_len(ctx, c);
1623
1624 if (contents)
1625 {
1626 copy = Memento_label(fz_malloc(ctx, len), "sig_contents");
1627 memcpy(copy, s, len);
1628 }
1629 }
1630 fz_always(ctx)
1631 pdf_drop_obj(ctx, v_obj);
1632 fz_catch(ctx)
1633 {
1634 fz_free(ctx, copy);
1635 fz_rethrow(ctx);
1636 }
1637
1638 if (contents)
1639 *contents = copy;
1640 return len;
1641 }
1642
1643 static fz_xml_doc *load_xfa(fz_context *ctx, pdf_document *doc)
1644 {
1645 pdf_obj *xfa;
1646 fz_buffer *buf = NULL;
1647 fz_buffer *packet = NULL;
1648 int i;
1649
1650 if (doc->xfa)
1651 return doc->xfa; /* Already loaded, and present. */
1652
1653 xfa = pdf_dict_getp(ctx, pdf_trailer(ctx, doc), "Root/AcroForm/XFA");
1654 if (!pdf_is_array(ctx, xfa) && !pdf_is_stream(ctx, xfa))
1655 return NULL; /* No XFA */
1656
1657 fz_var(buf);
1658 fz_var(packet);
1659
1660 fz_try(ctx)
1661 {
1662 if (pdf_is_stream(ctx, xfa))
1663 {
1664 /* Load entire XFA resource */
1665 buf = pdf_load_stream(ctx, xfa);
1666 }
1667 else
1668 {
1669 /* Concatenate packets to create entire XFA resource */
1670 buf = fz_new_buffer(ctx, 1024);
1671 for(i = 0; i < pdf_array_len(ctx, xfa); ++i)
1672 {
1673 pdf_obj *ref = pdf_array_get(ctx, xfa, i);
1674 if (pdf_is_stream(ctx, ref))
1675 {
1676 packet = pdf_load_stream(ctx, ref);
1677 fz_append_buffer(ctx, buf, packet);
1678 fz_drop_buffer(ctx, packet);
1679 packet = NULL;
1680 }
1681 }
1682 }
1683
1684 /* Parse and stow away XFA resource in document */
1685 doc->xfa = fz_parse_xml(ctx, buf, 0);
1686 }
1687 fz_always(ctx)
1688 {
1689 fz_drop_buffer(ctx, packet);
1690 fz_drop_buffer(ctx, buf);
1691 }
1692 fz_catch(ctx)
1693 {
1694 fz_rethrow(ctx);
1695 }
1696
1697 return doc->xfa;
1698 }
1699
1700 static fz_xml *
1701 get_xfa_resource(fz_context *ctx, pdf_document *doc, const char *str)
1702 {
1703 fz_xml_doc *xfa;
1704
1705 xfa = load_xfa(ctx, doc);
1706 if (!xfa)
1707 return NULL;
1708
1709 return fz_xml_find_down(fz_xml_root(xfa), str);
1710 }
1711
1712 static int
1713 find_name_component(char **np, char **sp, char **ep)
1714 {
1715 char *n = *np;
1716 char *s, *e;
1717 int idx = 0;
1718
1719 if (*n == '.')
1720 n++;
1721
1722 /* Find the next name we are looking for. */
1723 s = e = n;
1724 while (*e && *e != '[' && *e != '.')
1725 e++;
1726
1727 /* So the next name is s..e */
1728 n = e;
1729 if (*n == '[')
1730 {
1731 n++;
1732 while (*n >= '0' && *n <= '9')
1733 idx = idx*10 + *n++ - '0';
1734 while (*n && *n != ']')
1735 n++;
1736 if (*n == ']')
1737 n++;
1738 }
1739 *np = n;
1740 *sp = s;
1741 *ep = e;
1742
1743 return idx;
1744 }
1745
1746 static pdf_obj *
1747 annot_from_name(fz_context *ctx, pdf_document *doc, const char *str)
1748 {
1749 pdf_obj *fields = pdf_dict_getp(ctx, pdf_trailer(ctx, doc), "Root/AcroForm/Fields");
1750
1751 if (strncmp(str, "xfa[0].", 7) == 0)
1752 str += 7;
1753 if (strncmp(str, "template[0].", 12) == 0)
1754 str += 12;
1755
1756 return pdf_lookup_field(ctx, fields, str);
1757 }
1758
1759 static pdf_obj *
1760 get_locked_fields_from_xfa(fz_context *ctx, pdf_document *doc, pdf_obj *field)
1761 {
1762 char *name = pdf_load_field_name(ctx, field);
1763 char *n = name;
1764 const char *use;
1765 fz_xml *node;
1766
1767 if (name == NULL)
1768 return NULL;
1769
1770 fz_try(ctx)
1771 {
1772 node = get_xfa_resource(ctx, doc, "template");
1773
1774 do
1775 {
1776 char c, *s, *e;
1777 int idx = 0;
1778 char *key;
1779
1780 idx = find_name_component(&n, &s, &e);
1781 /* We want the idx'th occurrence of s..e */
1782
1783 /* Hacky */
1784 c = *e;
1785 *e = 0;
1786 key = *n ? "subform" : "field";
1787 node = fz_xml_find_down_match(node, key, "name", s);
1788 while (node && idx > 0)
1789 {
1790 node = fz_xml_find_next_match(node, key, "name", s);
1791 idx--;
1792 }
1793 *e = c;
1794 }
1795 while (node && *n == '.');
1796 }
1797 fz_always(ctx)
1798 fz_free(ctx, name);
1799 fz_catch(ctx)
1800 fz_rethrow(ctx);
1801
1802 if (node == NULL)
1803 return NULL;
1804
1805 node = fz_xml_find_down(node, "ui");
1806 node = fz_xml_find_down(node, "signature");
1807 node = fz_xml_find_down(node, "manifest");
1808
1809 use = fz_xml_att(node, "use");
1810 if (use == NULL)
1811 return NULL;
1812 if (*use == '#')
1813 use++;
1814
1815 /* Now look for a variables entry in a subform that defines this. */
1816 while (node)
1817 {
1818 fz_xml *variables, *manifest, *ref;
1819 pdf_obj *arr;
1820
1821 /* Find the enclosing subform */
1822 do {
1823 node = fz_xml_up(node);
1824 } while (node && strcmp(fz_xml_tag(node), "subform"));
1825
1826 /* Look for a variables within that. */
1827 variables = fz_xml_find_down(node, "variables");
1828 if (variables == NULL)
1829 continue;
1830
1831 manifest = fz_xml_find_down_match(variables, "manifest", "id", use);
1832 if (manifest == NULL)
1833 continue;
1834
1835 arr = pdf_new_array(ctx, doc, 16);
1836 fz_try(ctx)
1837 {
1838 ref = fz_xml_find_down(manifest, "ref");
1839 while (ref)
1840 {
1841 const char *s = fz_xml_text(fz_xml_down(ref));
1842 pdf_array_push(ctx, arr, annot_from_name(ctx, doc, s));
1843 ref = fz_xml_find_next(ref, "ref");
1844 }
1845 }
1846 fz_catch(ctx)
1847 {
1848 pdf_drop_obj(ctx, arr);
1849 fz_rethrow(ctx);
1850 }
1851 return arr;
1852 }
1853
1854 return NULL;
1855 }
1856
1857 static void
1858 lock_field(fz_context *ctx, pdf_obj *f)
1859 {
1860 int ff = pdf_dict_get_inheritable_int(ctx, f, PDF_NAME(Ff));
1861
1862 if ((ff & PDF_FIELD_IS_READ_ONLY) ||
1863 !pdf_name_eq(ctx, pdf_dict_get(ctx, f, PDF_NAME(Type)), PDF_NAME(Annot)) ||
1864 !pdf_name_eq(ctx, pdf_dict_get(ctx, f, PDF_NAME(Subtype)), PDF_NAME(Widget)))
1865 return;
1866
1867 pdf_dict_put_int(ctx, f, PDF_NAME(Ff), ff | PDF_FIELD_IS_READ_ONLY);
1868 }
1869
1870 static void
1871 lock_xfa_locked_fields(fz_context *ctx, pdf_obj *a)
1872 {
1873 int i;
1874 int len = pdf_array_len(ctx, a);
1875
1876 for (i = 0; i < len; i++)
1877 {
1878 lock_field(ctx, pdf_array_get(ctx, a, i));
1879 }
1880 }
1881
1882
1883 void pdf_signature_set_value(fz_context *ctx, pdf_document *doc, pdf_obj *field, pdf_pkcs7_signer *signer, int64_t stime)
1884 {
1885 pdf_obj *v = NULL;
1886 pdf_obj *o = NULL;
1887 pdf_obj *r = NULL;
1888 pdf_obj *t = NULL;
1889 pdf_obj *a = NULL;
1890 pdf_obj *b = NULL;
1891 pdf_obj *l = NULL;
1892 pdf_obj *indv;
1893 int vnum;
1894 size_t max_digest_size;
1895 char *buf = NULL;
1896
1897 vnum = pdf_create_object(ctx, doc);
1898 indv = pdf_new_indirect(ctx, doc, vnum, 0);
1899 pdf_dict_put_drop(ctx, field, PDF_NAME(V), indv);
1900
1901 max_digest_size = signer->max_digest_size(ctx, signer);
1902
1903 fz_var(v);
1904 fz_var(o);
1905 fz_var(r);
1906 fz_var(t);
1907 fz_var(a);
1908 fz_var(b);
1909 fz_var(l);
1910 fz_var(buf);
1911 fz_try(ctx)
1912 {
1913 v = pdf_new_dict(ctx, doc, 4);
1914 pdf_update_object(ctx, doc, vnum, v);
1915
1916 buf = fz_calloc(ctx, max_digest_size, 1);
1917
1918 /* Ensure that the /Filter entry is the first entry in the
1919 dictionary after the digest contents since we look for
1920 this tag when completing signatures in pdf-write.c in order
1921 to generate the correct byte range. */
1922 pdf_dict_put_array(ctx, v, PDF_NAME(ByteRange), 4);
1923 pdf_dict_put_string(ctx, v, PDF_NAME(Contents), buf, max_digest_size);
1924 pdf_dict_put(ctx, v, PDF_NAME(Filter), PDF_NAME(Adobe_PPKLite));
1925 pdf_dict_put(ctx, v, PDF_NAME(SubFilter), PDF_NAME(adbe_pkcs7_detached));
1926 pdf_dict_put(ctx, v, PDF_NAME(Type), PDF_NAME(Sig));
1927 pdf_dict_put_date(ctx, v, PDF_NAME(M), stime);
1928
1929 o = pdf_dict_put_array(ctx, v, PDF_NAME(Reference), 1);
1930 r = pdf_array_put_dict(ctx, o, 0, 4);
1931 pdf_dict_put(ctx, r, PDF_NAME(Data), pdf_dict_get(ctx, pdf_trailer(ctx, doc), PDF_NAME(Root)));
1932 pdf_dict_put(ctx, r, PDF_NAME(TransformMethod), PDF_NAME(FieldMDP));
1933 pdf_dict_put(ctx, r, PDF_NAME(Type), PDF_NAME(SigRef));
1934 t = pdf_dict_put_dict(ctx, r, PDF_NAME(TransformParams), 5);
1935
1936 l = pdf_dict_getp(ctx, field, "Lock/Action");
1937 if (l)
1938 {
1939 a = pdf_dict_getp(ctx, field, "Lock/Fields");
1940 }
1941 else
1942 {
1943 /* Lock action wasn't specified so we need to encode an Include.
1944 * Before we just use an empty array, check in the XFA for locking
1945 * details. */
1946 a = get_locked_fields_from_xfa(ctx, doc, field);
1947 if (a)
1948 lock_xfa_locked_fields(ctx, a);
1949
1950 /* If we don't get a result from the XFA, just encode an empty array
1951 * (leave a == NULL), even if Lock/Fields exists because we don't really
1952 * know what to do with the information if the action isn't defined. */
1953 l = PDF_NAME(Include);
1954 }
1955
1956 pdf_dict_put(ctx, t, PDF_NAME(Action), l);
1957
1958 if (pdf_name_eq(ctx, l, PDF_NAME(Include)) || pdf_name_eq(ctx, l, PDF_NAME(Exclude)))
1959 {
1960 /* For action Include and Exclude, we need to encode a Fields array */
1961 if (!a)
1962 {
1963 /* If one wasn't defined or we chose to ignore it because no action
1964 * was defined then use an empty one. */
1965 b = pdf_new_array(ctx, doc, 0);
1966 a = b;
1967 }
1968
1969 pdf_dict_put_drop(ctx, t, PDF_NAME(Fields), pdf_copy_array(ctx, a));
1970 }
1971
1972 pdf_dict_put(ctx, t, PDF_NAME(Type), PDF_NAME(TransformParams));
1973 pdf_dict_put(ctx, t, PDF_NAME(V), PDF_NAME(1_2));
1974
1975 /* Record details within the document structure so that contents
1976 * and byte_range can be updated with their correct values at
1977 * saving time */
1978 pdf_xref_store_unsaved_signature(ctx, doc, field, signer);
1979 }
1980 fz_always(ctx)
1981 {
1982 pdf_drop_obj(ctx, v);
1983 pdf_drop_obj(ctx, b);
1984 fz_free(ctx, buf);
1985 }
1986 fz_catch(ctx)
1987 {
1988 fz_rethrow(ctx);
1989 }
1990 }
1991
1992 void pdf_set_widget_editing_state(fz_context *ctx, pdf_annot *widget, int editing)
1993 {
1994 widget->ignore_trigger_events = editing;
1995 }
1996
1997 int pdf_get_widget_editing_state(fz_context *ctx, pdf_annot *widget)
1998 {
1999 return widget->ignore_trigger_events;
2000 }
2001
2002 static void pdf_execute_js_action(fz_context *ctx, pdf_document *doc, pdf_obj *target, const char *path, pdf_obj *js)
2003 {
2004 if (js)
2005 {
2006 char *code = pdf_load_stream_or_string_as_utf8(ctx, js);
2007 int in_op = 0;
2008
2009 fz_var(in_op);
2010 fz_try(ctx)
2011 {
2012 char buf[100];
2013 fz_snprintf(buf, sizeof buf, "%d/%s", pdf_to_num(ctx, target), path);
2014 pdf_begin_operation(ctx, doc, "Javascript Event");
2015 in_op = 1;
2016 pdf_js_execute(doc->js, buf, code, NULL);
2017 pdf_end_operation(ctx, doc);
2018 }
2019 fz_always(ctx)
2020 {
2021 fz_free(ctx, code);
2022 }
2023 fz_catch(ctx)
2024 {
2025 if (in_op)
2026 pdf_abandon_operation(ctx, doc);
2027 fz_rethrow(ctx);
2028 }
2029 }
2030 }
2031
2032 static void pdf_execute_action_imp(fz_context *ctx, pdf_document *doc, pdf_obj *target, const char *path, pdf_obj *action)
2033 {
2034 pdf_obj *S = pdf_dict_get(ctx, action, PDF_NAME(S));
2035 if (pdf_name_eq(ctx, S, PDF_NAME(JavaScript)))
2036 {
2037 if (doc->js)
2038 pdf_execute_js_action(ctx, doc, target, path, pdf_dict_get(ctx, action, PDF_NAME(JS)));
2039 }
2040 if (pdf_name_eq(ctx, S, PDF_NAME(ResetForm)))
2041 {
2042 pdf_obj *fields = pdf_dict_get(ctx, action, PDF_NAME(Fields));
2043 int flags = pdf_dict_get_int(ctx, action, PDF_NAME(Flags));
2044 pdf_reset_form(ctx, doc, fields, flags & 1);
2045 }
2046 }
2047
2048 static void pdf_execute_action_chain(fz_context *ctx, pdf_document *doc, pdf_obj *target, const char *path, pdf_obj *action, pdf_cycle_list *cycle_up)
2049 {
2050 pdf_cycle_list cycle;
2051 pdf_obj *next;
2052
2053 if (pdf_cycle(ctx, &cycle, cycle_up, action))
2054 fz_throw(ctx, FZ_ERROR_FORMAT, "cycle in action chain");
2055
2056 if (pdf_is_array(ctx, action))
2057 {
2058 int i, n = pdf_array_len(ctx, action);
2059 for (i = 0; i < n; ++i)
2060 pdf_execute_action_chain(ctx, doc, target, path, pdf_array_get(ctx, action, i), &cycle);
2061 }
2062 else
2063 {
2064 pdf_execute_action_imp(ctx, doc, target, path, action);
2065 next = pdf_dict_get(ctx, action, PDF_NAME(Next));
2066 if (next)
2067 pdf_execute_action_chain(ctx, doc, target, path, next, &cycle);
2068 }
2069 }
2070
2071 static void pdf_execute_action(fz_context *ctx, pdf_document *doc, pdf_obj *target, const char *path)
2072 {
2073 pdf_obj *action = pdf_dict_getp_inheritable(ctx, target, path);
2074 if (action)
2075 pdf_execute_action_chain(ctx, doc, target, path, action, NULL);
2076 }
2077
2078 void pdf_document_event_will_close(fz_context *ctx, pdf_document *doc)
2079 {
2080 pdf_execute_action(ctx, doc, pdf_trailer(ctx, doc), "Root/AA/WC");
2081 }
2082
2083 void pdf_document_event_will_save(fz_context *ctx, pdf_document *doc)
2084 {
2085 pdf_execute_action(ctx, doc, pdf_trailer(ctx, doc), "Root/AA/WS");
2086 }
2087
2088 void pdf_document_event_did_save(fz_context *ctx, pdf_document *doc)
2089 {
2090 pdf_execute_action(ctx, doc, pdf_trailer(ctx, doc), "Root/AA/DS");
2091 }
2092
2093 void pdf_document_event_will_print(fz_context *ctx, pdf_document *doc)
2094 {
2095 pdf_execute_action(ctx, doc, pdf_trailer(ctx, doc), "Root/AA/WP");
2096 }
2097
2098 void pdf_document_event_did_print(fz_context *ctx, pdf_document *doc)
2099 {
2100 pdf_execute_action(ctx, doc, pdf_trailer(ctx, doc), "Root/AA/DP");
2101 }
2102
2103 void pdf_page_event_open(fz_context *ctx, pdf_page *page)
2104 {
2105 pdf_execute_action(ctx, page->doc, page->obj, "AA/O");
2106 }
2107
2108 void pdf_page_event_close(fz_context *ctx, pdf_page *page)
2109 {
2110 pdf_execute_action(ctx, page->doc, page->obj, "AA/C");
2111 }
2112
2113 static void
2114 annot_execute_action(fz_context *ctx, pdf_annot *annot, const char *act)
2115 {
2116 begin_annot_op(ctx, annot, "JavaScript action");
2117
2118 fz_try(ctx)
2119 {
2120 pdf_execute_action(ctx, annot->page->doc, annot->obj, act);
2121 end_annot_op(ctx, annot);
2122 }
2123 fz_catch(ctx)
2124 {
2125 abandon_annot_op(ctx, annot);
2126 fz_rethrow(ctx);
2127 }
2128 }
2129
2130 void pdf_annot_event_enter(fz_context *ctx, pdf_annot *annot)
2131 {
2132 annot_execute_action(ctx, annot, "AA/E");
2133 }
2134
2135 void pdf_annot_event_exit(fz_context *ctx, pdf_annot *annot)
2136 {
2137 annot_execute_action(ctx, annot, "AA/X");
2138 }
2139
2140 void pdf_annot_event_down(fz_context *ctx, pdf_annot *annot)
2141 {
2142 annot_execute_action(ctx, annot, "AA/D");
2143 }
2144
2145 void pdf_annot_event_up(fz_context *ctx, pdf_annot *annot)
2146 {
2147 pdf_obj *action;
2148
2149 begin_annot_op(ctx, annot, "JavaScript action");
2150
2151 fz_try(ctx)
2152 {
2153 action = pdf_dict_get(ctx, annot->obj, PDF_NAME(A));
2154 if (action)
2155 pdf_execute_action_chain(ctx, annot->page->doc, annot->obj, "A", action, NULL);
2156 else
2157 pdf_execute_action(ctx, annot->page->doc, annot->obj, "AA/U");
2158 end_annot_op(ctx, annot);
2159 }
2160 fz_catch(ctx)
2161 {
2162 abandon_annot_op(ctx, annot);
2163 fz_rethrow(ctx);
2164 }
2165 }
2166
2167 void pdf_annot_event_focus(fz_context *ctx, pdf_annot *annot)
2168 {
2169 annot_execute_action(ctx, annot, "AA/Fo");
2170 }
2171
2172 void pdf_annot_event_blur(fz_context *ctx, pdf_annot *annot)
2173 {
2174 annot_execute_action(ctx, annot, "AA/Bl");
2175 }
2176
2177 void pdf_annot_event_page_open(fz_context *ctx, pdf_annot *annot)
2178 {
2179 annot_execute_action(ctx, annot, "AA/PO");
2180 }
2181
2182 void pdf_annot_event_page_close(fz_context *ctx, pdf_annot *annot)
2183 {
2184 annot_execute_action(ctx, annot, "AA/PC");
2185 }
2186
2187 void pdf_annot_event_page_visible(fz_context *ctx, pdf_annot *annot)
2188 {
2189 annot_execute_action(ctx, annot, "AA/PV");
2190 }
2191
2192 void pdf_annot_event_page_invisible(fz_context *ctx, pdf_annot *annot)
2193 {
2194 annot_execute_action(ctx, annot, "AA/PI");
2195 }
2196
2197 int pdf_field_event_keystroke(fz_context *ctx, pdf_document *doc, pdf_obj *field, pdf_keystroke_event *evt)
2198 {
2199 pdf_js *js = doc->js;
2200 if (js)
2201 {
2202 pdf_obj *action = pdf_dict_getp_inheritable(ctx, field, "AA/K/JS");
2203 if (action)
2204 {
2205 pdf_js_event_init_keystroke(js, field, evt);
2206 pdf_execute_js_action(ctx, doc, field, "AA/K/JS", action);
2207 return pdf_js_event_result_keystroke(js, evt);
2208 }
2209 }
2210 evt->newChange = fz_strdup(ctx, evt->change);
2211 evt->newValue = fz_strdup(ctx, evt->value);
2212 return 1;
2213 }
2214
2215 int pdf_annot_field_event_keystroke(fz_context *ctx, pdf_document *doc, pdf_annot *annot, pdf_keystroke_event *evt)
2216 {
2217 int ret;
2218
2219 pdf_annot_push_local_xref(ctx, annot);
2220
2221 fz_try(ctx)
2222 ret = pdf_field_event_keystroke(ctx, doc, annot->obj, evt);
2223 fz_always(ctx)
2224 pdf_annot_pop_local_xref(ctx, annot);
2225 fz_catch(ctx)
2226 fz_rethrow(ctx);
2227
2228 return ret;
2229 }
2230
2231 char *pdf_field_event_format(fz_context *ctx, pdf_document *doc, pdf_obj *field)
2232 {
2233 pdf_js *js = doc->js;
2234 if (js)
2235 {
2236 pdf_obj *action = pdf_dict_getp_inheritable(ctx, field, "AA/F/JS");
2237 if (action)
2238 {
2239 const char *value = pdf_field_value(ctx, field);
2240 pdf_js_event_init(js, field, value, 1);
2241 pdf_execute_js_action(ctx, doc, field, "AA/F/JS", action);
2242 return pdf_js_event_value(js);
2243 }
2244 }
2245 return NULL;
2246 }
2247
2248 int pdf_field_event_validate(fz_context *ctx, pdf_document *doc, pdf_obj *field, const char *value, char **newvalue)
2249 {
2250 pdf_js *js = doc->js;
2251
2252 *newvalue = NULL;
2253 if (js)
2254 {
2255 pdf_obj *action = pdf_dict_getp_inheritable(ctx, field, "AA/V/JS");
2256 if (action)
2257 {
2258 pdf_js_event_init(js, field, value, 1);
2259 pdf_execute_js_action(ctx, doc, field, "AA/V/JS", action);
2260 return pdf_js_event_result_validate(js, newvalue);
2261 }
2262 }
2263 return 1;
2264 }
2265
2266 void pdf_field_event_calculate(fz_context *ctx, pdf_document *doc, pdf_obj *field)
2267 {
2268 pdf_js *js = doc->js;
2269 if (js)
2270 {
2271 pdf_obj *action = pdf_dict_getp_inheritable(ctx, field, "AA/C/JS");
2272 if (action)
2273 {
2274 char *old_value = fz_strdup(ctx, pdf_field_value(ctx, field));
2275 char *new_value = NULL;
2276 fz_var(new_value);
2277 fz_try(ctx)
2278 {
2279 pdf_js_event_init(js, field, old_value, 1);
2280 pdf_execute_js_action(ctx, doc, field, "AA/C/JS", action);
2281 if (pdf_js_event_result(js))
2282 {
2283 new_value = pdf_js_event_value(js);
2284 if (strcmp(old_value, new_value))
2285 pdf_set_field_value(ctx, doc, field, new_value, 0);
2286 }
2287 }
2288 fz_always(ctx)
2289 {
2290 fz_free(ctx, old_value);
2291 fz_free(ctx, new_value);
2292 }
2293 fz_catch(ctx)
2294 fz_rethrow(ctx);
2295 }
2296 }
2297 }
2298
2299 static void
2300 count_sigs(fz_context *ctx, pdf_obj *field, void *arg, pdf_obj **ft)
2301 {
2302 int *n = (int *)arg;
2303
2304 if (!pdf_name_eq(ctx, pdf_dict_get(ctx, field, PDF_NAME(Type)), PDF_NAME(Annot)) ||
2305 !pdf_name_eq(ctx, pdf_dict_get(ctx, field, PDF_NAME(Subtype)), PDF_NAME(Widget)) ||
2306 !pdf_name_eq(ctx, *ft, PDF_NAME(Sig)))
2307 return;
2308
2309 (*n)++;
2310 }
2311
2312 static pdf_obj *ft_name[2] = { PDF_NAME(FT), NULL };
2313
2314 int pdf_count_signatures(fz_context *ctx, pdf_document *doc)
2315 {
2316 int n = 0;
2317 pdf_obj *ft = NULL;
2318 pdf_obj *form_fields = pdf_dict_getp(ctx, pdf_trailer(ctx, doc), "Root/AcroForm/Fields");
2319 pdf_walk_tree(ctx, form_fields, PDF_NAME(Kids), count_sigs, NULL, &n, ft_name, &ft);
2320 return n;
2321 }
2322
2323 /*
2324 * Bake interactive form fields into static content.
2325 */
2326
2327 static pdf_obj *get_annot_ap(fz_context *ctx, pdf_obj *annot)
2328 {
2329 pdf_obj *ap = pdf_dict_get(ctx, annot, PDF_NAME(AP));
2330 pdf_obj *as = pdf_dict_get(ctx, annot, PDF_NAME(AS));
2331 if (ap)
2332 {
2333 as = pdf_resolve_indirect_chain(ctx, as);
2334 ap = pdf_dict_get(ctx, ap, PDF_NAME(N));
2335 if (pdf_is_stream(ctx, ap))
2336 return ap;
2337 ap = pdf_dict_get(ctx, ap, as);
2338 if (pdf_is_stream(ctx, ap))
2339 return ap;
2340 }
2341 return NULL;
2342 }
2343
2344 static fz_matrix get_annot_transform(fz_context *ctx, pdf_obj *annot, pdf_obj *ap)
2345 {
2346 float w, h, x, y;
2347 fz_matrix transform;
2348 fz_rect bbox;
2349 fz_rect rect;
2350
2351 rect = pdf_dict_get_rect(ctx, annot, PDF_NAME(Rect));
2352 bbox = pdf_dict_get_rect(ctx, ap, PDF_NAME(BBox));
2353 transform = pdf_dict_get_matrix(ctx, ap, PDF_NAME(Matrix));
2354
2355 bbox = fz_transform_rect(bbox, transform);
2356 w = (rect.x1 - rect.x0) / (bbox.x1 - bbox.x0);
2357 h = (rect.y1 - rect.y0) / (bbox.y1 - bbox.y0);
2358 x = rect.x0 - bbox.x0 * w;
2359 y = rect.y0 - bbox.y0 * h;
2360
2361 return fz_make_matrix(w, 0, 0, h, x, y);
2362 }
2363
2364 static void pdf_bake_annot(fz_context *ctx, fz_buffer *buf, pdf_document *doc, pdf_obj *page, pdf_obj *res_xobj, pdf_obj *annot)
2365 {
2366 fz_matrix m;
2367 pdf_obj *ap;
2368 char name[20];
2369
2370 ap = get_annot_ap(ctx, annot);
2371 if (ap)
2372 {
2373 fz_snprintf(name, sizeof name, "Annot%d", pdf_to_num(ctx, annot));
2374 pdf_dict_puts(ctx, res_xobj, name, ap);
2375 pdf_dict_put(ctx, ap, PDF_NAME(Type), PDF_NAME(XObject));
2376 pdf_dict_put(ctx, ap, PDF_NAME(Subtype), PDF_NAME(Form));
2377 m = get_annot_transform(ctx, annot, ap);
2378 fz_append_printf(ctx, buf,
2379 "q\n%g %g %g %g %g %g cm\n/%s Do\nQ\n",
2380 m.a, m.b, m.c, m.d, m.e, m.f,
2381 name
2382 );
2383 }
2384 }
2385
2386 static void pdf_bake_page(fz_context *ctx, pdf_document *doc, pdf_obj *page, int bake_annots, int bake_widgets)
2387 {
2388 pdf_obj *res;
2389 pdf_obj *res_xobj;
2390 pdf_obj *contents;
2391 pdf_obj *new_contents = NULL;
2392 pdf_obj *annots;
2393 pdf_obj *annot;
2394 pdf_obj *subtype;
2395 pdf_obj *prologue = NULL;
2396 fz_buffer *buf = NULL;
2397 int prepend, append;
2398 int i;
2399
2400 fz_var(buf);
2401 fz_var(prologue);
2402 fz_var(new_contents);
2403
2404 annots = pdf_dict_get(ctx, page, PDF_NAME(Annots));
2405 if (pdf_array_len(ctx, annots) == 0)
2406 return;
2407
2408 res = pdf_dict_get(ctx, page, PDF_NAME(Resources));
2409 if (!res)
2410 res = pdf_dict_put_dict(ctx, page, PDF_NAME(Resources), 4);
2411
2412 res_xobj = pdf_dict_get(ctx, res, PDF_NAME(XObject));
2413 if (!res_xobj)
2414 res_xobj = pdf_dict_put_dict(ctx, res, PDF_NAME(XObject), 8);
2415
2416 fz_try(ctx)
2417 {
2418 // Ensure that the graphics state is balanced.
2419 contents = pdf_dict_get(ctx, page, PDF_NAME(Contents));
2420 pdf_count_q_balance(ctx, doc, res, contents, &prepend, &append);
2421
2422 if (prepend)
2423 {
2424 // Prepend enough 'q' to ensure we can get back to initial state.
2425 buf = fz_new_buffer(ctx, 1024);
2426 while (prepend-- > 0)
2427 fz_append_string(ctx, buf, "q\n");
2428
2429 prologue = pdf_add_stream(ctx, doc, buf, NULL, 0);
2430 fz_drop_buffer(ctx, buf);
2431 buf = NULL;
2432 }
2433
2434 // Append enough 'Q' to get back to initial state.
2435 buf = fz_new_buffer(ctx, 1024);
2436 while (append-- > 0)
2437 fz_append_string(ctx, buf, "Q\n");
2438
2439 for (i = 0; i < pdf_array_len(ctx, annots); )
2440 {
2441 annot = pdf_array_get(ctx, annots, i);
2442 subtype = pdf_dict_get(ctx, annot, PDF_NAME(Subtype));
2443 if (subtype == PDF_NAME(Link))
2444 {
2445 ++i;
2446 }
2447 else if (subtype == PDF_NAME(Widget))
2448 {
2449 if (bake_widgets)
2450 {
2451 pdf_bake_annot(ctx, buf, doc, page, res_xobj, annot);
2452 pdf_array_delete(ctx, annots, i);
2453 }
2454 else
2455 {
2456 ++i;
2457 }
2458 }
2459 else
2460 {
2461 if (bake_annots)
2462 {
2463 pdf_bake_annot(ctx, buf, doc, page, res_xobj, annot);
2464 pdf_array_delete(ctx, annots, i);
2465 }
2466 else
2467 {
2468 ++i;
2469 }
2470 }
2471 }
2472
2473 if (!pdf_is_array(ctx, contents))
2474 {
2475 new_contents = pdf_new_array(ctx, doc, 10);
2476 if (prologue)
2477 pdf_array_push(ctx, new_contents, prologue);
2478 if (contents)
2479 pdf_array_push(ctx, new_contents, contents);
2480 pdf_dict_put(ctx, page, PDF_NAME(Contents), new_contents);
2481 pdf_drop_obj(ctx, new_contents);
2482 contents = new_contents;
2483 new_contents = NULL;
2484 }
2485 else if (prologue)
2486 {
2487 pdf_array_insert(ctx, contents, prologue, 0);
2488 }
2489
2490 pdf_array_push_drop(ctx, contents, pdf_add_stream(ctx, doc, buf, NULL, 0));
2491 }
2492 fz_always(ctx)
2493 {
2494 fz_drop_buffer(ctx, buf);
2495 pdf_drop_obj(ctx, prologue);
2496 pdf_drop_obj(ctx, new_contents);
2497 }
2498 fz_catch(ctx)
2499 {
2500 fz_rethrow(ctx);
2501 }
2502 }
2503
2504 void pdf_bake_document(fz_context *ctx, pdf_document *doc, int bake_annots, int bake_widgets)
2505 {
2506 pdf_page *page = NULL;
2507 pdf_annot *annot;
2508 int i, n;
2509
2510 fz_var(page);
2511
2512 pdf_begin_operation(ctx, doc, "Bake interactive content");
2513 fz_try(ctx)
2514 {
2515 n = pdf_count_pages(ctx, doc);
2516 for (i = 0; i < n; ++i)
2517 {
2518 page = pdf_load_page(ctx, doc, i);
2519
2520 if (bake_annots)
2521 for (annot = pdf_first_annot(ctx, page); annot; annot = pdf_next_annot(ctx, annot))
2522 pdf_annot_request_synthesis(ctx, annot);
2523 if (bake_widgets)
2524 for (annot = pdf_first_widget(ctx, page); annot; annot = pdf_next_widget(ctx, annot))
2525 pdf_annot_request_synthesis(ctx, annot);
2526 pdf_update_page(ctx, page);
2527
2528 pdf_bake_page(ctx, doc, page->obj, bake_annots, bake_widgets);
2529
2530 fz_drop_page(ctx, (fz_page*)page);
2531 page = NULL;
2532 }
2533
2534 if (bake_widgets)
2535 {
2536 pdf_obj *trailer = pdf_trailer(ctx, doc);
2537 pdf_obj *root = pdf_dict_get(ctx, trailer, PDF_NAME(Root));
2538 pdf_dict_del(ctx, root, PDF_NAME(AcroForm));
2539 }
2540 pdf_end_operation(ctx, doc);
2541 }
2542 fz_always(ctx)
2543 {
2544 fz_drop_page(ctx, (fz_page*)page);
2545 }
2546 fz_catch(ctx)
2547 {
2548 pdf_abandon_operation(ctx, doc);
2549 }
2550 }