diff options
Diffstat (limited to 'pdf/pdf_file.c')
-rw-r--r-- | pdf/pdf_file.c | 137 |
1 files changed, 122 insertions, 15 deletions
diff --git a/pdf/pdf_file.c b/pdf/pdf_file.c index 5698866e..7f06a046 100644 --- a/pdf/pdf_file.c +++ b/pdf/pdf_file.c @@ -334,7 +334,7 @@ static int pdfi_Flate_filter(pdf_context *ctx, pdf_dict *d, stream *source, stre (*new_stream)->strm = source; source = *new_stream; - if (d && d->type == PDF_DICT) { + if (d && pdfi_type_of(d) == PDF_DICT) { Flate_source = (*new_stream)->strm; code = pdfi_Predictor_filter(ctx, d, source, new_stream); if (code < 0) @@ -403,7 +403,7 @@ static int pdfi_LZW_filter(pdf_context *ctx, pdf_dict *d, stream *source, stream /* s_zlibD_template defined in base/szlibd.c */ s_LZW_set_defaults_inline(&lzs); - if (d && d->type == PDF_DICT) { + if (d && pdfi_type_of(d) == PDF_DICT) { code = pdfi_dict_get_int(ctx, d, "EarlyChange", &i); if (code < 0 && code != gs_error_undefined) return code; @@ -421,7 +421,7 @@ static int pdfi_LZW_filter(pdf_context *ctx, pdf_dict *d, stream *source, stream (*new_stream)->strm = source; source = *new_stream; - if (d && d->type == PDF_DICT) + if (d && pdfi_type_of(d) == PDF_DICT) pdfi_Predictor_filter(ctx, d, source, new_stream); return 0; } @@ -473,21 +473,25 @@ pdfi_JPX_filter(pdf_context *ctx, pdf_dict *dict, pdf_dict *decode, } if (dict && pdfi_dict_get(ctx, dict, "ColorSpace", &csobj) == 0) { /* parse the value */ - if (csobj->type == PDF_ARRAY) { + switch (pdfi_type_of(csobj)) { + case PDF_ARRAY: /* assume it's the first array element */ code = pdfi_array_get(ctx, (pdf_array *)csobj, (uint64_t)0, (pdf_obj **)&csname); if (code < 0) { pdfi_countdown(csobj); return code; } - } else if (csobj->type == PDF_NAME) { + break; + case PDF_NAME: /* use the name directly */ csname = (pdf_name *)csobj; csobj = NULL; /* To keep ref counting straight */ - } else { + break; + default: dmprintf(ctx->memory, "warning: JPX ColorSpace value is an unhandled type!\n"); + break; } - if (csname != NULL && csname->type == PDF_NAME) { + if (csname != NULL && pdfi_type_of(csname) == PDF_NAME) { /* request raw index values if the colorspace is /Indexed */ if (pdfi_name_is(csname, "Indexed")) state.colorspace = gs_jpx_cs_indexed; @@ -613,7 +617,7 @@ static int pdfi_DCT_filter(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *de return code; } - if (decode && decode->type == PDF_DICT) { + if (decode && pdfi_type_of(decode) == PDF_DICT) { /* TODO: Why is this here? 'i' never gets used? */ code = pdfi_dict_get_int(ctx, decode, "ColorTransform", &i); if (code < 0 && code != gs_error_undefined) @@ -674,7 +678,7 @@ static int pdfi_CCITTFax_filter(pdf_context *ctx, pdf_dict *d, stream *source, s s_CF_set_defaults_inline(&ss); - if (d && d->type == PDF_DICT) { + if (d && pdfi_type_of(d) == PDF_DICT) { code = pdfi_dict_get_int(ctx, d, "K", &i); if (code < 0 && code != gs_error_undefined) return code; @@ -922,12 +926,11 @@ int pdfi_filter_no_decryption(pdf_context *ctx, pdf_stream *stream_obj, goto exit; } - if (Filter->type != PDF_ARRAY && Filter->type != PDF_NAME) { + switch (pdfi_type_of(Filter)) { + default: code = gs_note_error(gs_error_typecheck); goto exit; - } - - if (Filter->type == PDF_NAME) { + case PDF_NAME: code = pdfi_dict_knownget(ctx, stream_dict, "DecodeParms", &decode); if (code == 0 && inline_image) code = pdfi_dict_knownget(ctx, stream_dict, "DP", &decode); @@ -940,7 +943,9 @@ int pdfi_filter_no_decryption(pdf_context *ctx, pdf_stream *stream_obj, goto exit; code = pdfi_alloc_stream(ctx, new_s, source->s, new_stream); - } else { + break; + case PDF_ARRAY: + { pdf_array *filter_array = (pdf_array *)Filter; code = pdfi_dict_knownget_type(ctx, stream_dict, "DecodeParms", PDF_ARRAY, (pdf_obj **)&DecodeParams); @@ -1003,11 +1008,15 @@ int pdfi_filter_no_decryption(pdf_context *ctx, pdf_stream *stream_obj, goto error; } } - if (decode && decode->type != PDF_NULL && decode->type != PDF_DICT) { + if (decode && decode != PDF_NULL_OBJ && pdfi_type_of(decode) != PDF_DICT) { pdfi_countdown(decode); decode = NULL; pdfi_set_warning(ctx, 0, NULL, W_PDF_STREAM_BAD_DECODEPARMS, "pdfi_filter_no_decryption", NULL); } + if (decode && decode == PDF_NULL_OBJ) { + pdfi_countdown(decode); + decode = NULL; + } code = pdfi_apply_filter(ctx, stream_dict, (pdf_name *)o, (pdf_dict *)decode, s, &new_s, inline_image); @@ -1022,6 +1031,7 @@ int pdfi_filter_no_decryption(pdf_context *ctx, pdf_stream *stream_obj, } code = pdfi_alloc_stream(ctx, s, source->s, new_stream); } + } exit: pdfi_countdown(o); @@ -1050,6 +1060,9 @@ int pdfi_filter(pdf_context *ctx, pdf_stream *stream_obj, pdf_c_stream *source, pdf_c_stream *crypt_stream = NULL, *SubFile_stream = NULL; pdf_string *StreamKey = NULL; pdf_dict *stream_dict = NULL; + pdf_obj *FileSpec = NULL; + pdf_stream *NewStream = NULL; + bool known = false; *new_stream = NULL; @@ -1057,6 +1070,98 @@ int pdfi_filter(pdf_context *ctx, pdf_stream *stream_obj, pdf_c_stream *source, if (code < 0) goto error; + /* Horrifyingly, any stream dictionary can contain a file specification, which means that + * instead of using the stream from the PDF file we must use an external file. + * So much for portability! + * Note: We must not do this for inline images as an inline image dictionary can + * contain the abbreviation /F for the Filter, and an inline image is never a + * separate stream, it is (obviously) contained in the current stream. + */ + if (!inline_image) { + code = pdfi_dict_known(ctx, stream_dict, "F", &known); + if (code >= 0 && known) { + pdf_obj *FS = NULL, *o = NULL; + pdf_dict *dict = NULL; + stream *gstream = NULL; + + code = pdfi_dict_get(ctx, stream_dict, "F", &FileSpec); + if (code < 0) + goto error; + if (pdfi_type_of(FileSpec) == PDF_DICT) { + /* We don't really support FileSpec dictionaries, partly because we + * don't really know which platform to use. If there is a /F string + * then we will use that, just as if we had been given a string in + * the first place. + */ + code = pdfi_dict_knownget(ctx, (pdf_dict *)FileSpec, "F", &FS); + if (code < 0) { + goto error; + } + pdfi_countdown(FileSpec); + FileSpec = FS; + FS = NULL; + } + if (pdfi_type_of(FileSpec) != PDF_STRING) { + code = gs_note_error(gs_error_typecheck); + goto error; + } + /* We should now have a string with the filename (or URL). We need + * to open the file and create a stream, if that succeeds. + */ + gstream = sfopen((const char *)((pdf_string *)FileSpec)->data, "r", ctx->memory); + if (gstream == NULL) { + emprintf1(ctx->memory, "Failed to open file %s\n", (const char *)((pdf_string *)FileSpec)->data); + code = gs_note_error(gs_error_ioerror); + goto error; + } + + source = (pdf_c_stream *)gs_alloc_bytes(ctx->memory, sizeof(pdf_c_stream), "external stream"); + if (source == NULL) { + code = gs_note_error(gs_error_VMerror); + goto error; + } + memset(source, 0x00, sizeof(pdf_c_stream)); + source->s = gstream; + + code = pdfi_object_alloc(ctx, PDF_STREAM, 0, (pdf_obj **)&NewStream); + if (code < 0) + goto error; + pdfi_countup(NewStream); + code = pdfi_dict_alloc(ctx, 32, &dict); + if (code < 0){ + pdfi_countdown(NewStream); + goto error; + } + pdfi_countup(dict); + NewStream->stream_dict = dict; + code = pdfi_dict_get(ctx, stream_dict, "FFilter", &o); + if (code >= 0) { + code = pdfi_dict_put(ctx, NewStream->stream_dict, "Filter", o); + if (code < 0) { + pdfi_countdown(NewStream); + goto error; + } + } + code = pdfi_dict_get(ctx, stream_dict, "FPredictor", &o); + if (code >= 0) { + code = pdfi_dict_put(ctx, NewStream->stream_dict, "Predictor", o); + if (code < 0) { + pdfi_countdown(NewStream); + goto error; + } + } + pdfi_countup(NewStream->stream_dict); + NewStream->stream_offset = 0; + NewStream->Length = 0; + NewStream->length_valid = 0; + NewStream->stream_written = 0; + NewStream->is_marking = 0; + NewStream->parent_obj = NULL; + stream_obj = NewStream; + stream_dict = NewStream->stream_dict; + } + } + /* If the file isn't encrypted, don't apply encryption. If this is an inline * image then its in a content stream and will already be decrypted, so don't * apply decryption again. @@ -1143,7 +1248,9 @@ int pdfi_filter(pdf_context *ctx, pdf_stream *stream_obj, pdf_c_stream *source, code = pdfi_filter_no_decryption(ctx, stream_obj, source, new_stream, inline_image); } error: + pdfi_countdown(NewStream); pdfi_countdown(StreamKey); + pdfi_countdown(FileSpec); return code; } |