summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'pdf/pdf_file.c')
-rw-r--r--pdf/pdf_file.c137
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;
}