filters

pdfinfo.cpp
1//========================================================================
2//
3// pdfinfo.cpp
4//
5// Copyright 1998-2002 Glyph & Cog, LLC
6//
7//========================================================================
8
9#include <aconf.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <stddef.h>
13#include <string.h>
14#include <time.h>
15#include <math.h>
16#include "parseargs.h"
17#include "GString.h"
18#include "gmem.h"
19#include "GlobalParams.h"
20#include "Object.h"
21#include "Stream.h"
22#include "Array.h"
23#include "Dict.h"
24#include "XRef.h"
25#include "Catalog.h"
26#include "Page.h"
27#include "PDFDoc.h"
28#include "CharTypes.h"
29#include "UnicodeMap.h"
30#include "Error.h"
31#include "config.h"
32
33static void printInfoString(Dict *infoDict, char *key, char *text,
34 UnicodeMap *uMap);
35static void printInfoDate(Dict *infoDict, char *key, char *text);
36
37static GBool printMetadata = gFalse;
38static char textEncName[128] = "";
39static char ownerPassword[33] = "";
40static char userPassword[33] = "";
41static char cfgFileName[256] = "";
42static GBool printVersion = gFalse;
43static GBool printHelp = gFalse;
44
45static ArgDesc argDesc[] = {
46 {"-meta", argFlag, &printMetadata, 0,
47 "print the document metadata (XML)"},
48 {"-enc", argString, textEncName, sizeof(textEncName),
49 "output text encoding name"},
50 {"-opw", argString, ownerPassword, sizeof(ownerPassword),
51 "owner password (for encrypted files)"},
52 {"-upw", argString, userPassword, sizeof(userPassword),
53 "user password (for encrypted files)"},
54 {"-cfg", argString, cfgFileName, sizeof(cfgFileName),
55 "configuration file to use in place of .xpdfrc"},
56 {"-v", argFlag, &printVersion, 0,
57 "print copyright and version info"},
58 {"-h", argFlag, &printHelp, 0,
59 "print usage information"},
60 {"-help", argFlag, &printHelp, 0,
61 "print usage information"},
62 {"--help", argFlag, &printHelp, 0,
63 "print usage information"},
64 {"-?", argFlag, &printHelp, 0,
65 "print usage information"},
66 {NULL}
67};
68
69int main(int argc, char *argv[]) {
70 PDFDoc *doc;
71 GString *fileName;
72 GString *ownerPW, *userPW;
73 UnicodeMap *uMap;
74 Object info;
75 double w, h;
76 FILE *f;
77 GString *metadata;
78 GBool ok;
79 int exitCode;
80
81 exitCode = 99;
82
83 // parse args
84 ok = parseArgs(argDesc, &argc, argv);
85 if (!ok || argc != 2 || printVersion || printHelp) {
86 fprintf(stderr, "pdfinfo version %s\n", xpdfVersion);
87 fprintf(stderr, "%s\n", xpdfCopyright);
88 if (!printVersion) {
89 printUsage("pdfinfo", "<PDF-file>", argDesc);
90 }
91 goto err0;
92 }
93 fileName = new GString(argv[1]);
94
95 // read config file
96 globalParams = new GlobalParams(cfgFileName);
97 if (textEncName[0]) {
98 globalParams->setTextEncoding(textEncName);
99 }
100
101 // get mapping to output encoding
102 if (!(uMap = globalParams->getTextEncoding())) {
103 error(-1, "Couldn't get text encoding");
104 delete fileName;
105 goto err1;
106 }
107
108 // open PDF file
109 if (ownerPassword[0]) {
110 ownerPW = new GString(ownerPassword);
111 } else {
112 ownerPW = NULL;
113 }
114 if (userPassword[0]) {
115 userPW = new GString(userPassword);
116 } else {
117 userPW = NULL;
118 }
119 doc = new PDFDoc(fileName, ownerPW, userPW);
120 if (userPW) {
121 delete userPW;
122 }
123 if (ownerPW) {
124 delete ownerPW;
125 }
126 if (!doc->isOk()) {
127 exitCode = 1;
128 goto err2;
129 }
130
131 // print doc info
132 doc->getDocInfo(&info);
133 if (info.isDict()) {
134 printInfoString(info.getDict(), "Title", "Title: ", uMap);
135 printInfoString(info.getDict(), "Subject", "Subject: ", uMap);
136 printInfoString(info.getDict(), "Keywords", "Keywords: ", uMap);
137 printInfoString(info.getDict(), "Author", "Author: ", uMap);
138 printInfoString(info.getDict(), "Creator", "Creator: ", uMap);
139 printInfoString(info.getDict(), "Producer", "Producer: ", uMap);
140 printInfoDate(info.getDict(), "CreationDate", "CreationDate: ");
141 printInfoDate(info.getDict(), "ModDate", "ModDate: ");
142 }
143 info.free();
144
145 // print tagging info
146 printf("Tagged: %s\n",
147 doc->getStructTreeRoot()->isDict() ? "yes" : "no");
148
149 // print page count
150 printf("Pages: %d\n", doc->getNumPages());
151
152 // print encryption info
153 printf("Encrypted: ");
154 if (doc->isEncrypted()) {
155 printf("yes (print:%s copy:%s change:%s addNotes:%s)\n",
156 doc->okToPrint(gTrue) ? "yes" : "no",
157 doc->okToCopy(gTrue) ? "yes" : "no",
158 doc->okToChange(gTrue) ? "yes" : "no",
159 doc->okToAddNotes(gTrue) ? "yes" : "no");
160 } else {
161 printf("no\n");
162 }
163
164 // print page size
165 if (doc->getNumPages() >= 1) {
166 w = doc->getPageWidth(1);
167 h = doc->getPageHeight(1);
168 printf("Page size: %g x %g pts", w, h);
169 if ((fabs(w - 612) < 0.1 && fabs(h - 792) < 0.1) ||
170 (fabs(w - 792) < 0.1 && fabs(h - 612) < 0.1)) {
171 printf(" (letter)");
172 } else if ((fabs(w - 595) < 0.1 && fabs(h - 842) < 0.1) ||
173 (fabs(w - 842) < 0.1 && fabs(h - 595) < 0.1)) {
174 printf(" (A4)");
175 }
176 printf("\n");
177 }
178
179 // print file size
180#ifdef VMS
181 f = fopen(fileName->getCString(), "rb", "ctx=stm");
182#else
183 f = fopen(fileName->getCString(), "rb");
184#endif
185 if (f) {
186#ifdef HAVE_FSEEKO
187 fseeko(f, 0, SEEK_END);
188 printf("File size: %u bytes\n", (Guint)ftello(f));
189#elif defined(HAVE_FSEEK64) && defined(HAVE_FTELL64)
190 fseek64(f, 0, SEEK_END);
191 printf("File size: %u bytes\n", (Guint)ftell64(f));
192#else
193 fseek(f, 0, SEEK_END);
194 printf("File size: %d bytes\n", (int)ftell(f));
195#endif
196 fclose(f);
197 }
198
199 // print linearization info
200 printf("Optimized: %s\n", doc->isLinearized() ? "yes" : "no");
201
202 // print PDF version
203 printf("PDF version: %.1f\n", doc->getPDFVersion());
204
205 // print the metadata
206 if (printMetadata && (metadata = doc->readMetadata())) {
207 fputs("Metadata:\n", stdout);
208 fputs(metadata->getCString(), stdout);
209 fputc('\n', stdout);
210 delete metadata;
211 }
212
213 exitCode = 0;
214
215 // clean up
216 err2:
217 uMap->decRefCnt();
218 delete doc;
219 err1:
220 delete globalParams;
221 err0:
222
223 // check for memory leaks
224 Object::memCheck(stderr);
225 gMemReport(stderr);
226
227 return exitCode;
228}
229
230static void printInfoString(Dict *infoDict, char *key, char *text,
231 UnicodeMap *uMap) {
232 Object obj;
233 GString *s1;
234 GBool isUnicode;
235 Unicode u;
236 char buf[8];
237 int i, n;
238
239 if (infoDict->lookup(key, &obj)->isString()) {
240 fputs(text, stdout);
241 s1 = obj.getString();
242 if ((s1->getChar(0) & 0xff) == 0xfe &&
243 (s1->getChar(1) & 0xff) == 0xff) {
244 isUnicode = gTrue;
245 i = 2;
246 } else {
247 isUnicode = gFalse;
248 i = 0;
249 }
250 while (i < obj.getString()->getLength()) {
251 if (isUnicode) {
252 u = ((s1->getChar(i) & 0xff) << 8) |
253 (s1->getChar(i+1) & 0xff);
254 i += 2;
255 } else {
256 u = s1->getChar(i) & 0xff;
257 ++i;
258 }
259 n = uMap->mapUnicode(u, buf, sizeof(buf));
260 fwrite(buf, 1, n, stdout);
261 }
262 fputc('\n', stdout);
263 }
264 obj.free();
265}
266
267static void printInfoDate(Dict *infoDict, char *key, char *text) {
268 Object obj;
269 char *s;
270 int year, mon, day, hour, min, sec;
271 struct tm tmStruct;
272 char buf[256];
273
274 if (infoDict->lookup(key, &obj)->isString()) {
275 fputs(text, stdout);
276 s = obj.getString()->getCString();
277 if (s[0] == 'D' && s[1] == ':') {
278 s += 2;
279 }
280 if (sscanf(s, "%4d%2d%2d%2d%2d%2d",
281 &year, &mon, &day, &hour, &min, &sec) == 6) {
282 tmStruct.tm_year = year - 1900;
283 tmStruct.tm_mon = mon - 1;
284 tmStruct.tm_mday = day;
285 tmStruct.tm_hour = hour;
286 tmStruct.tm_min = min;
287 tmStruct.tm_sec = sec;
288 tmStruct.tm_wday = -1;
289 tmStruct.tm_yday = -1;
290 tmStruct.tm_isdst = -1;
291 // compute the tm_wday and tm_yday fields
292 if (mktime(&tmStruct) != (time_t)-1 &&
293 strftime(buf, sizeof(buf), "%c", &tmStruct)) {
294 fputs(buf, stdout);
295 } else {
296 fputs(s, stdout);
297 }
298 } else {
299 fputs(s, stdout);
300 }
301 fputc('\n', stdout);
302 }
303 obj.free();
304}