diff options
Diffstat (limited to 'apps/pdfshow.c')
-rw-r--r-- | apps/pdfshow.c | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/apps/pdfshow.c b/apps/pdfshow.c new file mode 100644 index 00000000..b3239978 --- /dev/null +++ b/apps/pdfshow.c @@ -0,0 +1,217 @@ +/* + * pdfshow -- the ultimate pdf debugging tool + */ + +#include "fitz.h" +#include "mupdf.h" + +pdf_xref *xref = NULL; + +void die(fz_error *eo) +{ + fflush(stdout); + fz_printerror(eo); + fz_droperror(eo); + fflush(stderr); + exit(1); +} + +void openxref(char *filename, char *password) +{ + fz_error *error; + fz_obj *obj; + + error = pdf_newxref(&xref); + if (error) + die(error); + + error = pdf_loadxref(xref, filename); + if (error) + { + fz_printerror(error); + fz_droperror(error); + fz_warn("trying to repair"); + error = pdf_repairxref(xref, filename); + if (error) + die(error); + } + + error = pdf_decryptxref(xref); + if (error) + die(error); + + if (xref->crypt) + { + int okay = pdf_setpassword(xref->crypt, password); + if (!okay) + die(fz_throw("invalid password")); + } + + /* TODO: move into mupdf lib, see pdfapp_open in pdfapp.c */ + obj = fz_dictgets(xref->trailer, "Root"); + if (!obj) + die(error); + + error = pdf_loadindirect(&xref->root, xref, obj); + if (error) + die(error); + + obj = fz_dictgets(xref->trailer, "Info"); + if (obj) + { + error = pdf_loadindirect(&xref->info, xref, obj); + if (error) + die(error); + } +} + +int showbinary = 0; +int showdecode = 0; +int showcolumn; + +void showusage(void) +{ + fprintf(stderr, "usage: pdfshow [-bd] [-p password] <file> [xref] [trailer] [object numbers]\n"); + fprintf(stderr, " -b \tprint streams as raw binary data\n"); + fprintf(stderr, " -x \tdecompress streams\n"); + fprintf(stderr, " -d \tdecrypt password\n"); + exit(1); +} + +void showtrailer(void) +{ + if (!xref) + die(fz_throw("no file specified")); + printf("trailer\n"); + fz_debugobj(xref->trailer); + printf("\n"); +} + +void showxref(void) +{ + if (!xref) + die(fz_throw("no file specified")); + pdf_debugxref(xref); + printf("\n"); +} + +void showsafe(unsigned char *buf, int n) +{ + int i; + for (i = 0; i < n; i++) { + if (buf[i] == '\r' || buf[i] == '\n') { + putchar('\n'); + showcolumn = 0; + } + else if (buf[i] < 32 || buf[i] > 126) { + putchar('.'); + showcolumn ++; + } + else { + putchar(buf[i]); + showcolumn ++; + } + if (showcolumn == 79) { + putchar('\n'); + showcolumn = 0; + } + } +} + +void showstream(int num, int gen) +{ + fz_error *error; + fz_stream *stm; + unsigned char buf[2048]; + int n; + + showcolumn = 0; + + if (showdecode) + error = pdf_openstream(&stm, xref, num, gen); + else + error = pdf_openrawstream(&stm, xref, num, gen); + if (error) + die(error); + + while (1) + { + error = fz_read(&n, stm, buf, sizeof buf); + if (error) + die(error); + if (n == 0) + break; + if (showbinary) + fwrite(buf, 1, n, stdout); + else + showsafe(buf, n); + } + + fz_dropstream(stm); +} + +void showobject(int num, int gen) +{ + fz_error *error; + fz_obj *obj; + + if (!xref) + die(fz_throw("no file specified")); + + error = pdf_loadobject(&obj, xref, num, gen); + if (error) + die(error); + + printf("%d %d obj\n", num, gen); + fz_debugobj(obj); + + if (pdf_isstream(xref, num, gen)) + { + printf("stream\n"); + showstream(num, gen); + printf("endstream\n"); + } + + printf("endobj\n\n"); + + fz_dropobj(obj); +} + +int main(int argc, char **argv) +{ + char *password = ""; + int c; + + while ((c = getopt(argc, argv, "bdp:")) != -1) + { + switch (c) + { + case 'd': password = optarg; break; + case 'b': showbinary ++; break; + case 'x': showdecode ++; break; + default: + showusage(); + break; + } + } + + if (optind == argc) + showusage(); + + openxref(argv[optind++], password); + + if (optind == argc) + showtrailer(); + + while (optind < argc) + { + if (!strcmp(argv[optind], "trailer")) + showtrailer(); + else if (!strcmp(argv[optind], "xref")) + showxref(); + else + showobject(atoi(argv[optind]), 0); + optind++; + } +} + |