Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
7639 views
1
/*
2
* pdfshow -- the ultimate pdf debugging tool
3
*/
4
5
#include "mupdf/pdf.h"
6
7
static FILE *out = NULL;
8
9
static pdf_document *doc = NULL;
10
static fz_context *ctx = NULL;
11
static int showbinary = 0;
12
static int showdecode = 1;
13
static int showcolumn;
14
15
static void usage(void)
16
{
17
fprintf(stderr, "usage: mutool show [options] file.pdf [grep] [xref] [trailer] [pagetree] [outline] [object numbers]\n");
18
fprintf(stderr, "\t-p -\tpassword\n");
19
fprintf(stderr, "\t-o -\toutput file\n");
20
fprintf(stderr, "\t-b\tprint streams as binary data\n");
21
fprintf(stderr, "\t-e\tprint encoded streams (don't decode)\n");
22
exit(1);
23
}
24
25
static void showtrailer(void)
26
{
27
if (!doc)
28
fz_throw(ctx, FZ_ERROR_GENERIC, "no file specified");
29
fprintf(out, "trailer\n");
30
pdf_fprint_obj(ctx, out, pdf_trailer(ctx, doc), 0);
31
fprintf(out, "\n");
32
}
33
34
static void showencrypt(void)
35
{
36
pdf_obj *encrypt;
37
38
if (!doc)
39
fz_throw(ctx, FZ_ERROR_GENERIC, "no file specified");
40
encrypt = pdf_dict_get(ctx, pdf_trailer(ctx, doc), PDF_NAME_Encrypt);
41
if (!encrypt)
42
fz_throw(ctx, FZ_ERROR_GENERIC, "document not encrypted");
43
fprintf(out, "encryption dictionary\n");
44
pdf_fprint_obj(ctx, out, pdf_resolve_indirect(ctx, encrypt), 0);
45
fprintf(out, "\n");
46
}
47
48
static void showxref(void)
49
{
50
if (!doc)
51
fz_throw(ctx, FZ_ERROR_GENERIC, "no file specified");
52
pdf_print_xref(ctx, doc);
53
fprintf(out, "\n");
54
}
55
56
static void showpagetree(void)
57
{
58
pdf_obj *ref;
59
int count;
60
int i;
61
62
if (!doc)
63
fz_throw(ctx, FZ_ERROR_GENERIC, "no file specified");
64
65
count = pdf_count_pages(ctx, doc);
66
for (i = 0; i < count; i++)
67
{
68
ref = pdf_lookup_page_obj(ctx, doc, i);
69
fprintf(out, "page %d = %d %d R\n", i + 1, pdf_to_num(ctx, ref), pdf_to_gen(ctx, ref));
70
}
71
fprintf(out, "\n");
72
}
73
74
static void showsafe(unsigned char *buf, int n)
75
{
76
int i;
77
for (i = 0; i < n; i++) {
78
if (buf[i] == '\r' || buf[i] == '\n') {
79
putchar('\n');
80
showcolumn = 0;
81
}
82
else if (buf[i] < 32 || buf[i] > 126) {
83
putchar('.');
84
showcolumn ++;
85
}
86
else {
87
putchar(buf[i]);
88
showcolumn ++;
89
}
90
if (showcolumn == 79) {
91
putchar('\n');
92
showcolumn = 0;
93
}
94
}
95
}
96
97
static void showstream(int num, int gen)
98
{
99
fz_stream *stm;
100
unsigned char buf[2048];
101
int n;
102
103
showcolumn = 0;
104
105
if (showdecode)
106
stm = pdf_open_stream(ctx, doc, num, gen);
107
else
108
stm = pdf_open_raw_stream(ctx, doc, num, gen);
109
110
while (1)
111
{
112
n = fz_read(ctx, stm, buf, sizeof buf);
113
if (n == 0)
114
break;
115
if (showbinary)
116
fwrite(buf, 1, n, out);
117
else
118
showsafe(buf, n);
119
}
120
121
fz_drop_stream(ctx, stm);
122
}
123
124
static void showobject(int num, int gen)
125
{
126
pdf_obj *obj;
127
128
if (!doc)
129
fz_throw(ctx, FZ_ERROR_GENERIC, "no file specified");
130
131
obj = pdf_load_object(ctx, doc, num, gen);
132
133
if (pdf_is_stream(ctx, doc, num, gen))
134
{
135
if (showbinary)
136
{
137
showstream(num, gen);
138
}
139
else
140
{
141
fprintf(out, "%d %d obj\n", num, gen);
142
pdf_fprint_obj(ctx, out, obj, 0);
143
fprintf(out, "stream\n");
144
showstream(num, gen);
145
fprintf(out, "endstream\n");
146
fprintf(out, "endobj\n\n");
147
}
148
}
149
else
150
{
151
fprintf(out, "%d %d obj\n", num, gen);
152
pdf_fprint_obj(ctx, out, obj, 0);
153
fprintf(out, "endobj\n\n");
154
}
155
156
pdf_drop_obj(ctx, obj);
157
}
158
159
static void showgrep(char *filename)
160
{
161
pdf_obj *obj;
162
int i, len;
163
164
len = pdf_count_objects(ctx, doc);
165
for (i = 0; i < len; i++)
166
{
167
pdf_xref_entry *entry = pdf_get_xref_entry(ctx, doc, i);
168
if (entry->type == 'n' || entry->type == 'o')
169
{
170
fz_try(ctx)
171
{
172
obj = pdf_load_object(ctx, doc, i, 0);
173
}
174
fz_catch(ctx)
175
{
176
fz_warn(ctx, "skipping object (%d 0 R)", i);
177
continue;
178
}
179
180
pdf_sort_dict(ctx, obj);
181
182
fprintf(out, "%s:%d: ", filename, i);
183
pdf_fprint_obj(ctx, out, obj, 1);
184
185
pdf_drop_obj(ctx, obj);
186
}
187
}
188
189
fprintf(out, "%s:trailer: ", filename);
190
pdf_fprint_obj(ctx, out, pdf_trailer(ctx, doc), 1);
191
}
192
193
static void showoutline(void)
194
{
195
fz_outline *outline = fz_load_outline(ctx, (fz_document*)doc);
196
fz_output *out = NULL;
197
198
fz_var(out);
199
fz_try(ctx)
200
{
201
out = fz_new_output_with_file(ctx, stdout, 0);
202
fz_print_outline(ctx, out, outline);
203
}
204
fz_always(ctx)
205
{
206
fz_drop_output(ctx, out);
207
fz_drop_outline(ctx, outline);
208
}
209
fz_catch(ctx)
210
{
211
fz_rethrow(ctx);
212
}
213
}
214
215
int pdfshow_main(int argc, char **argv)
216
{
217
char *password = NULL; /* don't throw errors if encrypted */
218
char *filename = NULL;
219
char *output = NULL;
220
int c;
221
222
while ((c = fz_getopt(argc, argv, "p:o:be")) != -1)
223
{
224
switch (c)
225
{
226
case 'p': password = fz_optarg; break;
227
case 'o': output = fz_optarg; break;
228
case 'b': showbinary = 1; break;
229
case 'e': showdecode = 0; break;
230
default: usage(); break;
231
}
232
}
233
234
if (fz_optind == argc)
235
usage();
236
237
filename = argv[fz_optind++];
238
239
out = stdout;
240
if (output)
241
{
242
out = fopen(output, "wb");
243
if (!out)
244
{
245
fprintf(stderr, "cannot open output file: '%s'\n", output);
246
exit(1);
247
}
248
}
249
250
ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED);
251
if (!ctx)
252
{
253
fprintf(stderr, "cannot initialise context\n");
254
exit(1);
255
}
256
257
fz_var(doc);
258
fz_try(ctx)
259
{
260
doc = pdf_open_document(ctx, filename);
261
if (pdf_needs_password(ctx, doc))
262
if (!pdf_authenticate_password(ctx, doc, password))
263
fz_warn(ctx, "cannot authenticate password: %s", filename);
264
265
if (fz_optind == argc)
266
showtrailer();
267
268
while (fz_optind < argc)
269
{
270
switch (argv[fz_optind][0])
271
{
272
case 't': showtrailer(); break;
273
case 'e': showencrypt(); break;
274
case 'x': showxref(); break;
275
case 'p': showpagetree(); break;
276
case 'g': showgrep(filename); break;
277
case 'o': showoutline(); break;
278
default: showobject(atoi(argv[fz_optind]), 0); break;
279
}
280
fz_optind++;
281
}
282
}
283
fz_catch(ctx)
284
{
285
}
286
287
if (out != stdout)
288
fclose(out);
289
290
pdf_close_document(ctx, doc);
291
fz_drop_context(ctx);
292
return 0;
293
}
294
295