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"
33 static void printInfoString(Dict
*infoDict
, char *key
, char *text
,
35 static void printInfoDate(Dict
*infoDict
, char *key
, char *text
);
36 static void printBox(char *text
, PDFRectangle
*box
);
38 static int firstPage
= 1;
39 static int lastPage
= 0;
40 static GBool printBoxes
= gFalse
;
41 static GBool printMetadata
= gFalse
;
42 static char textEncName
[128] = "";
43 static char ownerPassword
[33] = "\001";
44 static char userPassword
[33] = "\001";
45 static char cfgFileName
[256] = "";
46 static GBool printVersion
= gFalse
;
47 static GBool printHelp
= gFalse
;
49 static ArgDesc argDesc
[] = {
50 {"-f", argInt
, &firstPage
, 0,
51 "first page to convert"},
52 {"-l", argInt
, &lastPage
, 0,
53 "last page to convert"},
54 {"-box", argFlag
, &printBoxes
, 0,
55 "print the page bounding boxes"},
56 {"-meta", argFlag
, &printMetadata
, 0,
57 "print the document metadata (XML)"},
58 {"-enc", argString
, textEncName
, sizeof(textEncName
),
59 "output text encoding name"},
60 {"-opw", argString
, ownerPassword
, sizeof(ownerPassword
),
61 "owner password (for encrypted files)"},
62 {"-upw", argString
, userPassword
, sizeof(userPassword
),
63 "user password (for encrypted files)"},
64 {"-cfg", argString
, cfgFileName
, sizeof(cfgFileName
),
65 "configuration file to use in place of .xpdfrc"},
66 {"-v", argFlag
, &printVersion
, 0,
67 "print copyright and version info"},
68 {"-h", argFlag
, &printHelp
, 0,
69 "print usage information"},
70 {"-help", argFlag
, &printHelp
, 0,
71 "print usage information"},
72 {"--help", argFlag
, &printHelp
, 0,
73 "print usage information"},
74 {"-?", argFlag
, &printHelp
, 0,
75 "print usage information"},
79 int main(int argc
, char *argv
[]) {
82 GString
*ownerPW
, *userPW
;
87 double w
, h
, wISO
, hISO
;
98 ok
= parseArgs(argDesc
, &argc
, argv
);
99 if (!ok
|| argc
!= 2 || printVersion
|| printHelp
) {
100 fprintf(stderr
, "pdfinfo version %s\n", xpdfVersion
);
101 fprintf(stderr
, "%s\n", xpdfCopyright
);
103 printUsage("pdfinfo", "<PDF-file>", argDesc
);
107 fileName
= new GString(argv
[1]);
110 globalParams
= new GlobalParams(cfgFileName
);
111 if (textEncName
[0]) {
112 globalParams
->setTextEncoding(textEncName
);
115 // get mapping to output encoding
116 if (!(uMap
= globalParams
->getTextEncoding())) {
117 error(-1, "Couldn't get text encoding");
123 if (ownerPassword
[0] != '\001') {
124 ownerPW
= new GString(ownerPassword
);
128 if (userPassword
[0] != '\001') {
129 userPW
= new GString(userPassword
);
133 doc
= new PDFDoc(fileName
, ownerPW
, userPW
);
155 if (lastPage
< 1 || lastPage
> doc
->getNumPages()) {
156 lastPage
= doc
->getNumPages();
160 doc
->getDocInfo(&info
);
162 printInfoString(info
.getDict(), "Title", "Title: ", uMap
);
163 printInfoString(info
.getDict(), "Subject", "Subject: ", uMap
);
164 printInfoString(info
.getDict(), "Keywords", "Keywords: ", uMap
);
165 printInfoString(info
.getDict(), "Author", "Author: ", uMap
);
166 printInfoString(info
.getDict(), "Creator", "Creator: ", uMap
);
167 printInfoString(info
.getDict(), "Producer", "Producer: ", uMap
);
168 printInfoDate(info
.getDict(), "CreationDate", "CreationDate: ");
169 printInfoDate(info
.getDict(), "ModDate", "ModDate: ");
173 // print tagging info
174 printf("Tagged: %s\n",
175 doc
->getStructTreeRoot()->isDict() ? "yes" : "no");
178 printf("Pages: %d\n", doc
->getNumPages());
180 // print encryption info
181 printf("Encrypted: ");
182 if (doc
->isEncrypted()) {
183 printf("yes (print:%s copy:%s change:%s addNotes:%s)\n",
184 doc
->okToPrint(gTrue
) ? "yes" : "no",
185 doc
->okToCopy(gTrue
) ? "yes" : "no",
186 doc
->okToChange(gTrue
) ? "yes" : "no",
187 doc
->okToAddNotes(gTrue
) ? "yes" : "no");
193 for (pg
= firstPage
; pg
<= lastPage
; ++pg
) {
194 w
= doc
->getPageMediaWidth(pg
);
195 h
= doc
->getPageMediaHeight(pg
);
197 printf("Page %4d size: %g x %g pts", pg
, w
, h
);
199 printf("Page size: %g x %g pts", w
, h
);
201 if ((fabs(w
- 612) < 0.1 && fabs(h
- 792) < 0.1) ||
202 (fabs(w
- 792) < 0.1 && fabs(h
- 612) < 0.1)) {
205 hISO
= sqrt(sqrt(2.0)) * 7200 / 2.54;
206 wISO
= hISO
/ sqrt(2.0);
207 for (i
= 0; i
<= 6; ++i
) {
208 if ((fabs(w
- wISO
) < 1 && fabs(h
- hISO
) < 1) ||
209 (fabs(w
- hISO
) < 1 && fabs(h
- wISO
) < 1)) {
223 for (pg
= firstPage
; pg
<= lastPage
; ++pg
) {
224 page
= doc
->getCatalog()->getPage(pg
);
225 sprintf(buf
, "Page %4d MediaBox: ", pg
);
226 printBox(buf
, page
->getMediaBox());
227 sprintf(buf
, "Page %4d CropBox: ", pg
);
228 printBox(buf
, page
->getCropBox());
229 sprintf(buf
, "Page %4d BleedBox: ", pg
);
230 printBox(buf
, page
->getBleedBox());
231 sprintf(buf
, "Page %4d TrimBox: ", pg
);
232 printBox(buf
, page
->getTrimBox());
233 sprintf(buf
, "Page %4d ArtBox: ", pg
);
234 printBox(buf
, page
->getArtBox());
237 page
= doc
->getCatalog()->getPage(firstPage
);
238 printBox("MediaBox: ", page
->getMediaBox());
239 printBox("CropBox: ", page
->getCropBox());
240 printBox("BleedBox: ", page
->getBleedBox());
241 printBox("TrimBox: ", page
->getTrimBox());
242 printBox("ArtBox: ", page
->getArtBox());
248 f
= fopen(fileName
->getCString(), "rb", "ctx=stm");
250 f
= fopen(fileName
->getCString(), "rb");
254 fseeko(f
, 0, SEEK_END
);
255 printf("File size: %u bytes\n", (Guint
)ftello(f
));
257 fseek64(f
, 0, SEEK_END
);
258 printf("File size: %u bytes\n", (Guint
)ftell64(f
));
260 fseek(f
, 0, SEEK_END
);
261 printf("File size: %d bytes\n", (int)ftell(f
));
266 // print linearization info
267 printf("Optimized: %s\n", doc
->isLinearized() ? "yes" : "no");
270 printf("PDF version: %.1f\n", doc
->getPDFVersion());
272 // print the metadata
273 if (printMetadata
&& (metadata
= doc
->readMetadata())) {
274 fputs("Metadata:\n", stdout
);
275 fputs(metadata
->getCString(), stdout
);
290 // check for memory leaks
291 Object::memCheck(stderr
);
297 static void printInfoString(Dict
*infoDict
, char *key
, char *text
,
306 if (infoDict
->lookup(key
, &obj
)->isString()) {
308 s1
= obj
.getString();
309 if ((s1
->getChar(0) & 0xff) == 0xfe &&
310 (s1
->getChar(1) & 0xff) == 0xff) {
317 while (i
< obj
.getString()->getLength()) {
319 u
= ((s1
->getChar(i
) & 0xff) << 8) |
320 (s1
->getChar(i
+1) & 0xff);
323 u
= s1
->getChar(i
) & 0xff;
326 n
= uMap
->mapUnicode(u
, buf
, sizeof(buf
));
327 fwrite(buf
, 1, n
, stdout
);
334 static void printInfoDate(Dict
*infoDict
, char *key
, char *text
) {
337 int year
, mon
, day
, hour
, min
, sec
;
341 if (infoDict
->lookup(key
, &obj
)->isString()) {
343 s
= obj
.getString()->getCString();
344 if (s
[0] == 'D' && s
[1] == ':') {
347 if (sscanf(s
, "%4d%2d%2d%2d%2d%2d",
348 &year
, &mon
, &day
, &hour
, &min
, &sec
) == 6) {
349 tmStruct
.tm_year
= year
- 1900;
350 tmStruct
.tm_mon
= mon
- 1;
351 tmStruct
.tm_mday
= day
;
352 tmStruct
.tm_hour
= hour
;
353 tmStruct
.tm_min
= min
;
354 tmStruct
.tm_sec
= sec
;
355 tmStruct
.tm_wday
= -1;
356 tmStruct
.tm_yday
= -1;
357 tmStruct
.tm_isdst
= -1;
358 // compute the tm_wday and tm_yday fields
359 if (mktime(&tmStruct
) != (time_t)-1 &&
360 strftime(buf
, sizeof(buf
), "%c", &tmStruct
)) {
373 static void printBox(char *text
, PDFRectangle
*box
) {
374 printf("%s%8.2f %8.2f %8.2f %8.2f\n",
375 text
, box
->x1
, box
->y1
, box
->x2
, box
->y2
);