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