1 //========================================================================
5 // Copyright 1998-2003 Glyph & Cog, LLC
7 //========================================================================
16 #include "parseargs.h"
19 #include "GlobalParams.h"
28 #include "CharTypes.h"
29 #include "UnicodeMap.h"
30 #include "PDFDocEncoding.h"
34 static void printInfoString(Dict
*infoDict
, char *key
, char *text
,
36 static void printInfoDate(Dict
*infoDict
, char *key
, char *text
);
37 static void printBox(char *text
, PDFRectangle
*box
);
39 static int firstPage
= 1;
40 static int lastPage
= 0;
41 static GBool printBoxes
= gFalse
;
42 static GBool printMetadata
= gFalse
;
43 static char textEncName
[128] = "";
44 static char ownerPassword
[33] = "\001";
45 static char userPassword
[33] = "\001";
46 static char cfgFileName
[256] = "";
47 static GBool printVersion
= gFalse
;
48 static GBool printHelp
= gFalse
;
50 static ArgDesc argDesc
[] = {
51 {"-f", argInt
, &firstPage
, 0,
52 "first page to convert"},
53 {"-l", argInt
, &lastPage
, 0,
54 "last page to convert"},
55 {"-box", argFlag
, &printBoxes
, 0,
56 "print the page bounding boxes"},
57 {"-meta", argFlag
, &printMetadata
, 0,
58 "print the document metadata (XML)"},
59 {"-enc", argString
, textEncName
, sizeof(textEncName
),
60 "output text encoding name"},
61 {"-opw", argString
, ownerPassword
, sizeof(ownerPassword
),
62 "owner password (for encrypted files)"},
63 {"-upw", argString
, userPassword
, sizeof(userPassword
),
64 "user password (for encrypted files)"},
65 {"-cfg", argString
, cfgFileName
, sizeof(cfgFileName
),
66 "configuration file to use in place of .xpdfrc"},
67 {"-v", argFlag
, &printVersion
, 0,
68 "print copyright and version info"},
69 {"-h", argFlag
, &printHelp
, 0,
70 "print usage information"},
71 {"-help", argFlag
, &printHelp
, 0,
72 "print usage information"},
73 {"--help", argFlag
, &printHelp
, 0,
74 "print usage information"},
75 {"-?", argFlag
, &printHelp
, 0,
76 "print usage information"},
80 int main(int argc
, char *argv
[]) {
83 GString
*ownerPW
, *userPW
;
88 double w
, h
, wISO
, hISO
;
99 ok
= parseArgs(argDesc
, &argc
, argv
);
100 if (!ok
|| argc
!= 2 || printVersion
|| printHelp
) {
101 fprintf(stderr
, "pdfinfo version %s\n", xpdfVersion
);
102 fprintf(stderr
, "%s\n", xpdfCopyright
);
104 printUsage("pdfinfo", "<PDF-file>", argDesc
);
108 fileName
= new GString(argv
[1]);
111 globalParams
= new GlobalParams(cfgFileName
);
112 if (textEncName
[0]) {
113 globalParams
->setTextEncoding(textEncName
);
116 // get mapping to output encoding
117 if (!(uMap
= globalParams
->getTextEncoding())) {
118 error(-1, "Couldn't get text encoding");
124 if (ownerPassword
[0] != '\001') {
125 ownerPW
= new GString(ownerPassword
);
129 if (userPassword
[0] != '\001') {
130 userPW
= new GString(userPassword
);
134 doc
= new PDFDoc(fileName
, ownerPW
, userPW
);
156 if (lastPage
< 1 || lastPage
> doc
->getNumPages()) {
157 lastPage
= doc
->getNumPages();
161 doc
->getDocInfo(&info
);
163 printInfoString(info
.getDict(), "Title", "Title: ", uMap
);
164 printInfoString(info
.getDict(), "Subject", "Subject: ", uMap
);
165 printInfoString(info
.getDict(), "Keywords", "Keywords: ", uMap
);
166 printInfoString(info
.getDict(), "Author", "Author: ", uMap
);
167 printInfoString(info
.getDict(), "Creator", "Creator: ", uMap
);
168 printInfoString(info
.getDict(), "Producer", "Producer: ", uMap
);
169 printInfoDate(info
.getDict(), "CreationDate", "CreationDate: ");
170 printInfoDate(info
.getDict(), "ModDate", "ModDate: ");
174 // print tagging info
175 printf("Tagged: %s\n",
176 doc
->getStructTreeRoot()->isDict() ? "yes" : "no");
179 printf("Pages: %d\n", doc
->getNumPages());
181 // print encryption info
182 printf("Encrypted: ");
183 if (doc
->isEncrypted()) {
184 printf("yes (print:%s copy:%s change:%s addNotes:%s)\n",
185 doc
->okToPrint(gTrue
) ? "yes" : "no",
186 doc
->okToCopy(gTrue
) ? "yes" : "no",
187 doc
->okToChange(gTrue
) ? "yes" : "no",
188 doc
->okToAddNotes(gTrue
) ? "yes" : "no");
194 for (pg
= firstPage
; pg
<= lastPage
; ++pg
) {
195 w
= doc
->getPageCropWidth(pg
);
196 h
= doc
->getPageCropHeight(pg
);
198 printf("Page %4d size: %g x %g pts", pg
, w
, h
);
200 printf("Page size: %g x %g pts", w
, h
);
202 if ((fabs(w
- 612) < 0.1 && fabs(h
- 792) < 0.1) ||
203 (fabs(w
- 792) < 0.1 && fabs(h
- 612) < 0.1)) {
206 hISO
= sqrt(sqrt(2.0)) * 7200 / 2.54;
207 wISO
= hISO
/ sqrt(2.0);
208 for (i
= 0; i
<= 6; ++i
) {
209 if ((fabs(w
- wISO
) < 1 && fabs(h
- hISO
) < 1) ||
210 (fabs(w
- hISO
) < 1 && fabs(h
- wISO
) < 1)) {
224 for (pg
= firstPage
; pg
<= lastPage
; ++pg
) {
225 page
= doc
->getCatalog()->getPage(pg
);
226 sprintf(buf
, "Page %4d MediaBox: ", pg
);
227 printBox(buf
, page
->getMediaBox());
228 sprintf(buf
, "Page %4d CropBox: ", pg
);
229 printBox(buf
, page
->getCropBox());
230 sprintf(buf
, "Page %4d BleedBox: ", pg
);
231 printBox(buf
, page
->getBleedBox());
232 sprintf(buf
, "Page %4d TrimBox: ", pg
);
233 printBox(buf
, page
->getTrimBox());
234 sprintf(buf
, "Page %4d ArtBox: ", pg
);
235 printBox(buf
, page
->getArtBox());
238 page
= doc
->getCatalog()->getPage(firstPage
);
239 printBox("MediaBox: ", page
->getMediaBox());
240 printBox("CropBox: ", page
->getCropBox());
241 printBox("BleedBox: ", page
->getBleedBox());
242 printBox("TrimBox: ", page
->getTrimBox());
243 printBox("ArtBox: ", page
->getArtBox());
249 f
= fopen(fileName
->getCString(), "rb", "ctx=stm");
251 f
= fopen(fileName
->getCString(), "rb");
255 fseeko(f
, 0, SEEK_END
);
256 printf("File size: %u bytes\n", (Guint
)ftello(f
));
258 fseek64(f
, 0, SEEK_END
);
259 printf("File size: %u bytes\n", (Guint
)ftell64(f
));
261 fseek(f
, 0, SEEK_END
);
262 printf("File size: %d bytes\n", (int)ftell(f
));
267 // print linearization info
268 printf("Optimized: %s\n", doc
->isLinearized() ? "yes" : "no");
271 printf("PDF version: %.1f\n", doc
->getPDFVersion());
273 // print the metadata
274 if (printMetadata
&& (metadata
= doc
->readMetadata())) {
275 fputs("Metadata:\n", stdout
);
276 fputs(metadata
->getCString(), stdout
);
291 // check for memory leaks
292 xObject::memCheck(stderr
);
298 static void printInfoString(Dict
*infoDict
, char *key
, char *text
,
307 if (infoDict
->lookup(key
, &obj
)->isString()) {
309 s1
= obj
.getString();
310 if ((s1
->getChar(0) & 0xff) == 0xfe &&
311 (s1
->getChar(1) & 0xff) == 0xff) {
318 while (i
< obj
.getString()->getLength()) {
320 u
= ((s1
->getChar(i
) & 0xff) << 8) |
321 (s1
->getChar(i
+1) & 0xff);
324 u
= pdfDocEncoding
[s1
->getChar(i
) & 0xff];
327 n
= uMap
->mapUnicode(u
, buf
, sizeof(buf
));
328 fwrite(buf
, 1, n
, stdout
);
335 static void printInfoDate(Dict
*infoDict
, char *key
, char *text
) {
338 int year
, mon
, day
, hour
, min
, sec
, n
;
342 if (infoDict
->lookup(key
, &obj
)->isString()) {
344 s
= obj
.getString()->getCString();
345 if (s
[0] == 'D' && s
[1] == ':') {
348 if ((n
= sscanf(s
, "%4d%2d%2d%2d%2d%2d",
349 &year
, &mon
, &day
, &hour
, &min
, &sec
)) >= 1) {
357 tmStruct
.tm_year
= year
- 1900;
358 tmStruct
.tm_mon
= mon
- 1;
359 tmStruct
.tm_mday
= day
;
360 tmStruct
.tm_hour
= hour
;
361 tmStruct
.tm_min
= min
;
362 tmStruct
.tm_sec
= sec
;
363 tmStruct
.tm_wday
= -1;
364 tmStruct
.tm_yday
= -1;
365 tmStruct
.tm_isdst
= -1;
366 // compute the tm_wday and tm_yday fields
367 if (mktime(&tmStruct
) != (time_t)-1 &&
368 strftime(buf
, sizeof(buf
), "%c", &tmStruct
)) {
384 static void printBox(char *text
, PDFRectangle
*box
) {
385 printf("%s%8.2f %8.2f %8.2f %8.2f\n",
386 text
, box
->x1
, box
->y1
, box
->x2
, box
->y2
);