diff options
Diffstat (limited to 'pdf/pdf_annot.c')
-rw-r--r-- | pdf/pdf_annot.c | 189 |
1 files changed, 138 insertions, 51 deletions
diff --git a/pdf/pdf_annot.c b/pdf/pdf_annot.c index 7b96be1c..83b79293 100644 --- a/pdf/pdf_annot.c +++ b/pdf/pdf_annot.c @@ -269,7 +269,7 @@ static int pdfi_annot_draw_AP(pdf_context *ctx, pdf_dict *annot, pdf_obj *NormAP if (NormAP == NULL) return 0; - if (NormAP->type != PDF_STREAM) + if (pdfi_type_of(NormAP) != PDF_STREAM) return_error(gs_error_typecheck); code = pdfi_op_q(ctx); @@ -649,11 +649,55 @@ static int pdfi_form_get_inheritable(pdf_context *ctx, pdf_dict *field, const ch { int code = 0; pdf_dict *Parent = NULL; + bool known = false; /* Check this field */ code = pdfi_dict_knownget_type(ctx, field, Key, type, o); - if (code != 0) goto exit; + if (code != 0) goto exit1; + code = pdfi_loop_detector_mark(ctx); + if (code < 0) + goto exit; + + /* Check for Parent. Do not store the dereferenced Parent back to the dictionary + * as this can cause circular references. + */ + code = pdfi_dict_known(ctx, field, "Parent", &known); + if (code >= 0 && known == true) + { + code = pdfi_dict_get_no_store_R(ctx, field, "Parent", (pdf_obj **)&Parent); + if (code < 0) + goto exit; + + if (pdfi_type_of(Parent) != PDF_DICT) { + if (pdfi_type_of(Parent) == PDF_INDIRECT) { + pdf_indirect_ref *o = (pdf_indirect_ref *)Parent; + + code = pdfi_dereference(ctx, o->ref_object_num, o->ref_generation_num, (pdf_obj **)&Parent); + pdfi_countdown(o); + goto exit; + } else { + code = gs_note_error(gs_error_typecheck); + goto exit; + } + } + if (Parent->object_num != 0) { + code = pdfi_loop_detector_add_object(ctx, Parent->object_num); + if (code < 0) + goto exit; + } + code = pdfi_form_get_inheritable(ctx, Parent, Key, type, o); + if (code <= 0) { + if (ctx->AcroForm) + code = pdfi_dict_knownget_type(ctx, ctx->AcroForm, Key, type, o); + } + } else { + /* No Parent, so check AcroForm, if any */ + if (ctx->AcroForm) + code = pdfi_dict_knownget_type(ctx, ctx->AcroForm, Key, type, o); + } + +#if 0 /* If not found, recursively check Parent, if any */ code = pdfi_dict_knownget_type(ctx, field, "Parent", PDF_DICT, (pdf_obj **)&Parent); if (code < 0) goto exit; @@ -665,8 +709,12 @@ static int pdfi_form_get_inheritable(pdf_context *ctx, pdf_dict *field, const ch if (ctx->AcroForm) code = pdfi_dict_knownget_type(ctx, ctx->AcroForm, Key, type, o); } +#endif - exit: +exit: + (void)pdfi_loop_detector_cleartomark(ctx); + +exit1: pdfi_countdown(Parent); return code; } @@ -1475,11 +1523,13 @@ static int pdfi_annot_draw_LE(pdf_context *ctx, pdf_dict *annot, double dx, dy; double angle; int code; + pdf_obj_type type; code = pdfi_dict_knownget(ctx, annot, "LE", (pdf_obj **)&LE); if (code <= 0) goto exit; - if (LE->type != PDF_ARRAY && LE->type != PDF_NAME) { + type = pdfi_type_of(LE); + if (type != PDF_ARRAY && type != PDF_NAME) { code = gs_note_error(gs_error_typecheck); goto exit; } @@ -1490,7 +1540,7 @@ static int pdfi_annot_draw_LE(pdf_context *ctx, pdf_dict *annot, if (code < 0) angle = 0; - if (LE->type == PDF_ARRAY) { + if (type == PDF_ARRAY) { code = pdfi_array_get_type(ctx, (pdf_array *)LE, 0, PDF_NAME, (pdf_obj **)&LE1); if (code < 0) goto exit; @@ -1554,34 +1604,35 @@ static int pdfi_annot_get_NormAP(pdf_context *ctx, pdf_dict *annot, pdf_obj **No /* Nothing found */ if (code == 0) goto exit; - if (baseAP->type == PDF_STREAM) { - /* Use baseAP for the AP */ - AP = (pdf_stream *)baseAP; - baseAP = NULL; - } else { - if (baseAP->type != PDF_DICT) { - code = gs_error_typecheck; - goto exit; - } - - code = pdfi_dict_knownget_type(ctx, annot, "AS", PDF_NAME, (pdf_obj **)&AS); - if (code < 0) goto exit; - if (code == 0) { - pdfi_set_warning(ctx, 0, NULL, W_PDF_ANNOT_AP_ERROR, "pdfi_annot_get_NormAP", "WARNING Annotation has non-stream AP but no AS. Don't know what to render"); - goto exit; - } + switch (pdfi_type_of(baseAP)) { + case PDF_STREAM: + /* Use baseAP for the AP */ + AP = (pdf_stream *)baseAP; + baseAP = NULL; + break; + case PDF_DICT: + code = pdfi_dict_knownget_type(ctx, annot, "AS", PDF_NAME, (pdf_obj **)&AS); + if (code < 0) goto exit; + if (code == 0) { + pdfi_set_warning(ctx, 0, NULL, W_PDF_ANNOT_AP_ERROR, "pdfi_annot_get_NormAP", "WARNING Annotation has non-stream AP but no AS. Don't know what to render"); + goto exit; + } - /* Lookup the AS in the NormAP and use that as the AP */ - code = pdfi_dict_get_by_key(ctx, (pdf_dict *)baseAP, AS, (pdf_obj **)&AP); - if (code < 0) { - /* Apparently this is not an error, just silently don't have an AP */ - code = 0; - goto exit; - } - if (AP->type != PDF_STREAM) { - code = gs_note_error(gs_error_typecheck); + /* Lookup the AS in the NormAP and use that as the AP */ + code = pdfi_dict_get_by_key(ctx, (pdf_dict *)baseAP, AS, (pdf_obj **)&AP); + if (code < 0) { + /* Apparently this is not an error, just silently don't have an AP */ + code = 0; + goto exit; + } + if (pdfi_type_of(AP) != PDF_STREAM) { + code = gs_note_error(gs_error_typecheck); + goto exit; + } + break; + default: + code = gs_error_typecheck; goto exit; - } } *NormAP = (pdf_obj *)AP; @@ -3630,9 +3681,9 @@ static int pdfi_annot_draw_Widget(pdf_context *ctx, pdf_dict *annot, pdf_obj *No { int code = 0; bool found_T = false; - bool found_TF = false; + bool found_FT = false, known = false; pdf_obj *T = NULL; - pdf_obj *TF = NULL; + pdf_obj *FT = NULL; pdf_dict *Parent = NULL; pdf_dict *currdict = NULL; @@ -3651,33 +3702,71 @@ static int pdfi_annot_draw_Widget(pdf_context *ctx, pdf_dict *annot, pdf_obj *No /* TODO: See top part of pdf_draw.ps/drawwidget * check for /FT and /T and stuff */ + code = pdfi_loop_detector_mark(ctx); + if (code < 0) + goto exit; + currdict = annot; pdfi_countup(currdict); while (true) { + if (currdict->object_num != 0) { + code = pdfi_loop_detector_add_object(ctx, currdict->object_num); + if (code < 0) + break; + } + code = pdfi_dict_knownget(ctx, currdict, "T", &T); if (code < 0) goto exit; if (code > 0) { found_T = true; - break; + pdfi_countdown(T); + T = NULL; + if (found_FT) + break; } - code = pdfi_dict_knownget(ctx, currdict, "TF", &TF); + code = pdfi_dict_knownget(ctx, currdict, "FT", &FT); if (code < 0) goto exit; if (code > 0) { - found_TF = true; - break; + found_FT = true; + pdfi_countdown(FT); + FT = NULL; + if (found_T) + break; } - /* Check for Parent */ - code = pdfi_dict_knownget_type(ctx, currdict, "Parent", PDF_DICT, (pdf_obj **)&Parent); - if (code < 0) goto exit; - if (code == 0) + /* Check for Parent. Do not store the dereferenced Parent back to the dictionary + * as this can cause circular references. + */ + code = pdfi_dict_known(ctx, currdict, "Parent", &known); + if (code >= 0 && known == true) + { + code = pdfi_dict_get_no_store_R(ctx, currdict, "Parent", (pdf_obj **)&Parent); + if (code < 0) { + (void)pdfi_loop_detector_cleartomark(ctx); + goto exit; + } + if (pdfi_type_of(Parent) != PDF_DICT) { + if (pdfi_type_of(Parent) == PDF_INDIRECT) { + pdf_indirect_ref *o = (pdf_indirect_ref *)Parent; + + code = pdfi_dereference(ctx, o->ref_object_num, o->ref_generation_num, (pdf_obj **)&Parent); + pdfi_countdown(o); + if (code < 0) + break; + } else { + break; + } + } + pdfi_countdown(currdict); + currdict = Parent; + Parent = NULL; + } else break; - pdfi_countdown(currdict); - currdict = Parent; - pdfi_countup(currdict); } + (void)pdfi_loop_detector_cleartomark(ctx); + code = 0; - if (!found_T && !found_TF) { + if (!found_T || !found_FT) { *render_done = true; dmprintf(ctx->memory, "**** Warning: A Widget annotation dictionary lacks either the FT or T key.\n"); dmprintf(ctx->memory, " Acrobat ignores such annoataions, annotation will not be rendered.\n"); @@ -3696,8 +3785,6 @@ static int pdfi_annot_draw_Widget(pdf_context *ctx, pdf_dict *annot, pdf_obj *No *render_done = true; exit: - pdfi_countdown(T); - pdfi_countdown(TF); pdfi_countdown(Parent); pdfi_countdown(currdict); return code; @@ -3950,7 +4037,7 @@ static int pdfi_annot_preserve_modQP(pdf_context *ctx, pdf_dict *annot, pdf_name code = pdfi_dict_get(ctx, annot, "QuadPoints", (pdf_obj **)&QP); if (code < 0) goto exit; - if (QP->type != PDF_ARRAY) { + if (pdfi_type_of(QP) != PDF_ARRAY) { /* Invalid QuadPoints, just delete it because I dunno what to do... * TODO: Should flag a warning here */ @@ -4024,7 +4111,7 @@ static int pdfi_annot_preserve_modAP(pdf_context *ctx, pdf_dict *annot, pdf_name code = pdfi_dict_get(ctx, annot, "AP", (pdf_obj **)&AP); if (code < 0) goto exit; - if (AP->type != PDF_DICT) { + if (pdfi_type_of(AP) != PDF_DICT) { /* This is an invalid AP, we will flag and delete it below */ found_ap = false; goto exit; @@ -4037,14 +4124,14 @@ static int pdfi_annot_preserve_modAP(pdf_context *ctx, pdf_dict *annot, pdf_name if (code < 0) goto exit; /* Handle indirect object */ - if (Value->type != PDF_INDIRECT) + if (pdfi_type_of(Value) != PDF_INDIRECT) goto loop_continue; /* Dereference it */ code = pdfi_dereference(ctx, Value->ref_object_num, Value->ref_generation_num, &object); if (code < 0) goto exit; - if (object->type == PDF_STREAM) { + if (pdfi_type_of(object) == PDF_STREAM) { /* Get a form label */ code = pdfi_annot_preserve_nextformlabel(ctx, &labeldata, &labellen); if (code < 0) goto exit; |