]> www.fi.muni.cz Git - evince.git/blob - pdf/xpdf/pdfinfo.cc
Import of Xpdf 2.02 for merge
[evince.git] / pdf / xpdf / pdfinfo.cc
1 //========================================================================
2 //
3 // pdfinfo.cc
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
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;
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 #if HAVE_FSEEKO
187     fseeko(f, 0, SEEK_END);
188     printf("File size:    %u bytes\n", (Guint)ftello(f));
189 #elif HAVE_FSEEK64
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
230 static 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
267 static 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 }