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