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