diff options
Diffstat (limited to 'pdf/ghostpdf.c')
-rw-r--r-- | pdf/ghostpdf.c | 222 |
1 files changed, 198 insertions, 24 deletions
diff --git a/pdf/ghostpdf.c b/pdf/ghostpdf.c index 8d88b090..2dd4c63c 100644 --- a/pdf/ghostpdf.c +++ b/pdf/ghostpdf.c @@ -79,10 +79,15 @@ static int pdfi_output_metadata(pdf_context *ctx) { int code = 0; + if (ctx->filename != NULL) + dmprintf2(ctx->memory, "\n %s has %"PRIi64" ", ctx->filename, ctx->num_pages); + else + dmprintf1(ctx->memory, "\n File has %"PRIi64" ", ctx->num_pages); + if (ctx->num_pages > 1) - dmprintf2(ctx->memory, "\n %s has %"PRIi64" pages\n\n", ctx->filename, ctx->num_pages); + dmprintf(ctx->memory, "pages\n\n"); else - dmprintf2(ctx->memory, "\n %s has %"PRIi64" page.\n\n", ctx->filename, ctx->num_pages); + dmprintf(ctx->memory, "page.\n\n"); if (ctx->Info != NULL) { pdf_name *n = NULL; @@ -151,6 +156,7 @@ static int pdfi_output_metadata(pdf_context *ctx) pdfi_countdown(n); n = NULL; } + dmprintf(ctx->memory, "\n"); return code; } @@ -177,7 +183,7 @@ static int pdfi_dump_box(pdf_context *ctx, pdf_dict *page_dict, const char *Key) if (i != 0) dmprintf(ctx->memory, " "); if (code == 0) { - if (a->values[i]->type == PDF_INT) + if (pdfi_type_of(a->values[i]) == PDF_INT) dmprintf1(ctx->memory, "%"PRIi64"", ((pdf_num *)a->values[i])->value.i); else dmprintf1(ctx->memory, "%f", ((pdf_num *)a->values[i])->value.d); @@ -192,6 +198,90 @@ static int pdfi_dump_box(pdf_context *ctx, pdf_dict *page_dict, const char *Key) return code; } +static int dump_font(pdf_context *ctx, pdf_dict *font_dict, bool space_name) +{ + pdf_obj *obj = NULL; + char *str = NULL; + int len = 0, code = 0, i; + bool known = false, type0 = false; + + code = pdfi_dict_get_type(ctx, font_dict, "BaseFont", PDF_NAME, &obj); + if (code >= 0) { + code = pdfi_string_from_name(ctx, (pdf_name *)obj, &str, &len); + if (code >= 0) { + dmprintf1(ctx->memory, "%s", str); + if (len < 32 && space_name) { + for (i = 0; i < 32 - len;i++) + dmprintf(ctx->memory, " "); + } else + dmprintf(ctx->memory, " "); + (void)pdfi_free_string_from_name(ctx, str); + } + pdfi_countdown(obj); + obj = NULL; + } + + code = pdfi_dict_get_type(ctx, font_dict, "Subtype", PDF_NAME, &obj); + if (code >= 0) { + code = pdfi_string_from_name(ctx, (pdf_name *)obj, &str, &len); + if (code >= 0) { + dmprintf1(ctx->memory, "%s", str); + for (i = 0; i < 16 - len;i++) + dmprintf(ctx->memory, " "); + (void)pdfi_free_string_from_name(ctx, str); + } + if (pdfi_name_is((pdf_name *)obj, "Type0")) + type0 = true; + pdfi_countdown(obj); + obj = NULL; + } + + if (!type0) { + code = pdfi_dict_get_type(ctx, font_dict, "Embedded", PDF_BOOL, &obj); + if (code >= 0) { + if (obj == PDF_FALSE_OBJ) + dmprintf(ctx->memory, "Not embedded "); + else + dmprintf(ctx->memory, "Embedded "); + pdfi_countdown(obj); + obj = NULL; + } + else + dmprintf(ctx->memory, "Not embedded "); + } else + dmprintf(ctx->memory, " "); + + code = pdfi_dict_get_type(ctx, font_dict, "ToUnicode", PDF_BOOL, &obj); + if (code >= 0) { + if (obj == PDF_TRUE_OBJ) + dmprintf(ctx->memory, "Has ToUnicode "); + else + dmprintf(ctx->memory, "No ToUnicode "); + pdfi_countdown(obj); + obj = NULL; + } + else + dmprintf(ctx->memory, "No ToUnicode "); + + code = pdfi_dict_known(ctx, font_dict, "Descendants", &known); + if (code >= 0 && known) { + code = pdfi_dict_get_type(ctx, font_dict, "Descendants", PDF_ARRAY, &obj); + if (code >= 0) { + pdf_obj *desc = NULL; + + code = pdfi_array_get_type(ctx, (pdf_array *)obj, 0, PDF_DICT, &desc); + if (code >= 0) { + dmprintf(ctx->memory, "\n Descendants: ["); + (void)dump_font(ctx, (pdf_dict *)desc, false); + dmprintf(ctx->memory, "]"); + } + pdfi_countdown(obj); + obj = NULL; + } + } + return 0; +} + /* * This routine along with pdfi_output_metadtaa above, dumps certain kinds * of metadata from the PDF file, and from each page in the PDF file. It is @@ -202,12 +292,13 @@ static int pdfi_dump_box(pdf_context *ctx, pdf_dict *page_dict, const char *Key) * we always emit them, and the switches -dDumpFontsNeeded, -dDumpXML, * -dDumpFontsUsed and -dShowEmbeddedFonts are not implemented at all yet. */ -static int pdfi_output_page_info(pdf_context *ctx, uint64_t page_num) +int pdfi_output_page_info(pdf_context *ctx, uint64_t page_num) { int code; bool known = false; double f; pdf_dict *page_dict = NULL; + pdf_array *fonts_array = NULL, *spots_array = NULL; code = pdfi_page_get_dict(ctx, page_num, &page_dict); if (code < 0) @@ -271,7 +362,7 @@ static int pdfi_output_page_info(pdf_context *ctx, uint64_t page_num) return code; } - code = pdfi_check_page(ctx, page_dict, false); + code = pdfi_check_page(ctx, page_dict, &fonts_array, &spots_array, false); if (code < 0) { if (ctx->args.pdfstoponerror) return code; @@ -283,16 +374,62 @@ static int pdfi_output_page_info(pdf_context *ctx, uint64_t page_num) code = pdfi_dict_known(ctx, page_dict, "Annots", &known); if (code < 0) { if (code != gs_error_undefined && ctx->args.pdfstoponerror) - return code; + goto error; } else { if (known == true) dmprintf(ctx->memory, " Page contains Annotations"); + code = 0; + } + + if (spots_array != NULL) { + uint64_t index = 0; + pdf_name *spot = NULL; + char *str = NULL; + int len; + + dmprintf(ctx->memory, "\n Page Spot colors: \n"); + for (index = 0;index < pdfi_array_size(spots_array);index++) { + code = pdfi_array_get(ctx, spots_array, index, (pdf_obj **)&spot); + if (code >= 0) { + if (pdfi_type_of(spot) == PDF_NAME) { + code = pdfi_string_from_name(ctx, spot, &str, &len); + if (code >= 0) { + dmprintf1(ctx->memory, " '%s'\n", str); + (void)pdfi_free_string_from_name(ctx, str); + } + } + pdfi_countdown(spot); + spot = NULL; + } + } + code = 0; } + if (fonts_array != NULL && pdfi_array_size(fonts_array) != 0) { + uint64_t index = 0; + pdf_dict *font_dict = NULL; + + dmprintf(ctx->memory, "\n Fonts used: \n"); + for (index = 0;index < pdfi_array_size(fonts_array);index++) { + code = pdfi_array_get_type(ctx, fonts_array, index, PDF_DICT, (pdf_obj **)&font_dict); + if (code >= 0) { + dmprintf(ctx->memory, " "); + (void)dump_font(ctx, font_dict, true); + dmprintf(ctx->memory, "\n"); + pdfi_countdown(font_dict); + font_dict = NULL; + } + } + code = 0; + } + +error: + pdfi_countdown(fonts_array); + pdfi_countdown(spots_array); dmprintf(ctx->memory, "\n\n"); pdfi_countdown(page_dict); - return 0; + return code; } /* Error and warning string tables. There should be a string for each error and warning @@ -347,6 +484,8 @@ const char *gs_error_strings[] = { "unregistered", "invalidcontext", "invalidid", + "pdf_stackoverflow", + "circular reference" }; const char *gs_internal_error_strings[] = { @@ -358,16 +497,15 @@ const char *gs_internal_error_strings[] = { "exec stack underflow", "VMreclaim", "Need input", + "need file", "No defined error", "No defined error (2)", - "need file", "error info", "handled", - "circular reference" }; -#define LASTNORMALGSERROR gs_error_invalidid * -1 +#define LASTNORMALGSERROR gs_error_circular_reference * -1 #define FIRSTINTERNALERROR gs_error_hit_detected * -1 -#define LASTGSERROR gs_error_circular_reference * -1 +#define LASTGSERROR gs_error_handled * -1 void pdfi_verbose_error(pdf_context *ctx, int gs_error, const char *gs_lib_function, int pdfi_error, const char *pdfi_function_name, const char *extra_info) { @@ -784,7 +922,7 @@ int pdfi_prep_collection(pdf_context *ctx, uint64_t *TotalFiles, char ***names_a if (code < 0) goto exit; - if (File->type == PDF_DICT) { + if (pdfi_type_of(File) == PDF_DICT) { if (pdfi_dict_knownget_type(ctx, (pdf_dict *)File, "EF", PDF_DICT, &EF)) { if (pdfi_dict_knownget_type(ctx, (pdf_dict *)EF, "F", PDF_STREAM, &F)) { pdf_dict *stream_dict = NULL; @@ -859,7 +997,7 @@ int pdfi_prep_collection(pdf_context *ctx, uint64_t *TotalFiles, char ***names_a /* Create an entry for the Description in the names array */ code = pdfi_array_get(ctx, FileNames, ix * 2, (pdf_obj **)&Name); if (code >= 0) { - if (Name->type == PDF_STRING) { + if (pdfi_type_of((pdf_obj *)Name) == PDF_STRING) { working_array[(index * 2) + 1] = (char *)gs_alloc_bytes(ctx->memory, Name->length + 3, "Collection file names array entry"); if (working_array[(index * 2) + 1] != NULL) { memset(working_array[(index * 2) + 1], 0x00, Name->length + 3); @@ -999,6 +1137,13 @@ int pdfi_process_pdf_file(pdf_context *ctx, char *filename) else code = pdfi_process(ctx); + /* Pdfmark_InitialPage is the offset for Page Dests in + * /Outlines and Link annotations. It is the count of pages + * processed so far. Update it by the number of pages in + * this file. + */ + ctx->Pdfmark_InitialPage += ctx->num_pages; + pdfi_close_pdf_file(ctx); return code; } @@ -1037,9 +1182,14 @@ static int pdfi_init_file(pdf_context *ctx) if (code < 0 && code != gs_error_undefined) goto exit; if (code == 0) { - code = pdfi_initialise_Decryption(ctx); - if (code < 0) - goto exit; + if (pdfi_type_of(o) == PDF_DICT) { + code = pdfi_initialise_Decryption(ctx); + if (code < 0) + goto exit; + } else { + if (pdfi_type_of(o) != PDF_NULL) + pdfi_set_error(ctx, code, NULL, E_PDF_BADENCRYPT, "pdfi_init_file", NULL); + } } } @@ -1144,6 +1294,7 @@ int pdfi_set_input_stream(pdf_context *ctx, stream *stm) } /* Determine file size */ + pdfi_seek(ctx, ctx->main_stream, 0, SEEK_SET); pdfi_seek(ctx, ctx->main_stream, 0, SEEK_END); ctx->main_stream_length = pdfi_tell(ctx->main_stream); Offset = BUF_SIZE; @@ -1268,8 +1419,15 @@ int pdfi_set_input_stream(pdf_context *ctx, stream *stm) */ if (last_lineend) { leftover = last_lineend - Buffer; - memmove(Buffer + bytes - leftover, last_lineend, leftover); - bytes -= leftover; + /* Ensure we don't try to copy more than half a buffer, because that will + * end up overrunning the buffer end. Since we are only doing this to + * ensure we don't drop a partial 'startxref' that's far more than enough. + */ + if (leftover < BUF_SIZE / 2) { + memmove(Buffer + bytes - leftover, last_lineend, leftover); + bytes -= leftover; + } else + leftover = 0; } else leftover = 0; } @@ -1757,6 +1915,15 @@ int pdfi_clear_context(pdf_context *ctx) dmprintf1(ctx->memory, "Normal object cache hit rate: %f\n", hit_rate); dmprintf1(ctx->memory, "Compressed object cache hit rate: %f\n", compressed_hit_rate); #endif + if (ctx->PathSegments != NULL) { + gs_free_object(ctx->memory, ctx->PathSegments, "pdfi_clear_context"); + ctx->PathSegments = NULL; + } + if (ctx->PathPts != NULL) { + gs_free_object(ctx->memory, ctx->PathPts, "pdfi_clear_context"); + ctx->PathPts = NULL; + } + if (ctx->args.PageList) { gs_free_object(ctx->memory, ctx->args.PageList, "pdfi_clear_context"); ctx->args.PageList = NULL; @@ -1786,14 +1953,19 @@ int pdfi_clear_context(pdf_context *ctx) ctx->PagesTree = NULL; } - if (ctx->args.cidsubstpath.data != NULL) { - gs_free_object(ctx->memory, ctx->args.cidsubstpath.data, "cidsubstpath.data"); - ctx->args.cidsubstpath.data = NULL; + if (ctx->args.cidfsubstpath.data != NULL) { + gs_free_object(ctx->memory, ctx->args.cidfsubstpath.data, "cidfsubstpath.data"); + ctx->args.cidfsubstpath.data = NULL; + } + + if (ctx->args.cidfsubstfont.data != NULL) { + gs_free_object(ctx->memory, ctx->args.cidfsubstfont.data, "cidfsubstfont.data"); + ctx->args.cidfsubstfont.data = NULL; } - if (ctx->args.cidsubstfont.data != NULL) { - gs_free_object(ctx->memory, ctx->args.cidsubstfont.data, "cidsubstpath.data"); - ctx->args.cidsubstfont.data = NULL; + if (ctx->args.defaultfont.data != NULL) { + gs_free_object(ctx->memory, ctx->args.defaultfont.data, "cidfsubstfont.data"); + ctx->args.defaultfont.data = NULL; } pdfi_free_cstring_array(ctx, &ctx->args.showannottypes); @@ -1923,6 +2095,8 @@ int pdfi_clear_context(pdf_context *ctx) ctx->pdffontmap = NULL; pdfi_countdown(ctx->pdfnativefontmap); ctx->pdfnativefontmap = NULL; + pdfi_countdown(ctx->pdf_substitute_fonts); + ctx->pdf_substitute_fonts = NULL; return 0; } |