~ubuntu-branches/ubuntu/dapper/poppler/dapper-security

« back to all changes in this revision

Viewing changes to utils/pdftohtml.cc

  • Committer: Bazaar Package Importer
  • Author(s): Ondřej Surý
  • Date: 2005-12-30 11:34:07 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20051230113407-8grizsk0ar874uoi
Tags: 0.4.3-1
* New upstream release.
* New maintainer (Closes: #344738)
* CVE-2005-3191 and CAN-2005-2097 fixes merged upstream.
* Fixed some rendering bugs and disabled Cairo output
  (Closes: #314556, #322964, #328211)
* Acknowledge NMU (Closes: #342288)
* Add 001-selection-crash-bug.patch (Closes: #330544)
* Add poppler-utils (merge patch from Ubuntu)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//========================================================================
2
 
//
3
 
// pdftohtml.cc
4
 
//
5
 
//
6
 
// Copyright 1999-2000 G. Ovtcharov
7
 
//========================================================================
8
 
 
9
 
#include <stdio.h>
10
 
#include <stdlib.h>
11
 
#include <stddef.h>
12
 
#include <string.h>
13
 
#include <dirent.h>
14
 
#include <poppler-config.h>
15
 
#include <time.h>
16
 
#include "parseargs.h"
17
 
#include "goo/GooString.h"
18
 
#include "goo/gmem.h"
19
 
#include "Object.h"
20
 
#include "Stream.h"
21
 
#include "Array.h"
22
 
#include "Dict.h"
23
 
#include "XRef.h"
24
 
#include "Catalog.h"
25
 
#include "Page.h"
26
 
#include "PDFDoc.h"
27
 
#include "HtmlOutputDev.h"
28
 
#include "PSOutputDev.h"
29
 
#include "GlobalParams.h"
30
 
#include "Error.h"
31
 
#include "config.h"
32
 
#include "goo/gfile.h"
33
 
 
34
 
#ifndef GHOSTSCRIPT
35
 
# define GHOSTSCRIPT "gs"
36
 
#endif
37
 
 
38
 
static int firstPage = 1;
39
 
static int lastPage = 0;
40
 
static GBool rawOrder = gTrue;
41
 
GBool printCommands = gTrue;
42
 
static GBool printHelp = gFalse;
43
 
GBool printHtml = gFalse;
44
 
GBool complexMode=gFalse;
45
 
GBool ignore=gFalse;
46
 
//char extension[5]=".png";
47
 
double scale=1.5;
48
 
GBool noframes=gFalse;
49
 
GBool stout=gFalse;
50
 
GBool xml=gFalse;
51
 
GBool errQuiet=gFalse;
52
 
GBool noDrm=gFalse;
53
 
 
54
 
GBool showHidden = gFalse;
55
 
GBool noMerge = gFalse;
56
 
static char ownerPassword[33] = "";
57
 
static char userPassword[33] = "";
58
 
static char gsDevice[33] = "png16m";
59
 
static GBool printVersion = gFalse;
60
 
 
61
 
static GooString* getInfoString(Dict *infoDict, char *key);
62
 
static GooString* getInfoDate(Dict *infoDict, char *key);
63
 
 
64
 
static char textEncName[128] = "";
65
 
 
66
 
static ArgDesc argDesc[] = {
67
 
  {"-f",      argInt,      &firstPage,     0,
68
 
   "first page to convert"},
69
 
  {"-l",      argInt,      &lastPage,      0,
70
 
   "last page to convert"},
71
 
  /*{"-raw",    argFlag,     &rawOrder,      0,
72
 
    "keep strings in content stream order"},*/
73
 
  {"-q",      argFlag,     &errQuiet,      0,
74
 
   "don't print any messages or errors"},
75
 
  {"-h",      argFlag,     &printHelp,     0,
76
 
   "print usage information"},
77
 
  {"-help",   argFlag,     &printHelp,     0,
78
 
   "print usage information"},
79
 
  {"-p",      argFlag,     &printHtml,     0,
80
 
   "exchange .pdf links by .html"}, 
81
 
  {"-c",      argFlag,     &complexMode,          0,
82
 
   "generate complex document"},
83
 
  {"-i",      argFlag,     &ignore,        0,
84
 
   "ignore images"},
85
 
  {"-noframes", argFlag,   &noframes,      0,
86
 
   "generate no frames"},
87
 
  {"-stdout"  ,argFlag,    &stout,         0,
88
 
   "use standard output"},
89
 
  {"-zoom",   argFP,    &scale,         0,
90
 
   "zoom the pdf document (default 1.5)"},
91
 
  {"-xml",    argFlag,    &xml,         0,
92
 
   "output for XML post-processing"},
93
 
  {"-hidden", argFlag,   &showHidden,   0,
94
 
   "output hidden text"},
95
 
  {"-nomerge", argFlag, &noMerge, 0,
96
 
   "do not merge paragraphs"},   
97
 
  {"-enc",    argString,   textEncName,    sizeof(textEncName),
98
 
   "output text encoding name"},
99
 
  {"-dev",    argString,   gsDevice,       sizeof(gsDevice),
100
 
   "output device name for Ghostscript (png16m, jpeg etc)"},
101
 
  {"-v",      argFlag,     &printVersion,  0,
102
 
   "print copyright and version info"},
103
 
  {"-opw",    argString,   ownerPassword,  sizeof(ownerPassword),
104
 
   "owner password (for encrypted files)"},
105
 
  {"-upw",    argString,   userPassword,   sizeof(userPassword),
106
 
   "user password (for encrypted files)"},
107
 
  {"-nodrm", argFlag, &noDrm, 0,
108
 
   "override document DRM settings"},
109
 
  {NULL}
110
 
};
111
 
 
112
 
int main(int argc, char *argv[]) {
113
 
  PDFDoc *doc = NULL;
114
 
  GooString *fileName = NULL;
115
 
  GooString *docTitle = NULL;
116
 
  GooString *author = NULL, *keywords = NULL, *subject = NULL, *date = NULL;
117
 
  GooString *htmlFileName = NULL;
118
 
  GooString *psFileName = NULL;
119
 
  HtmlOutputDev *htmlOut = NULL;
120
 
  PSOutputDev *psOut = NULL;
121
 
  GBool ok;
122
 
  char *p;
123
 
  char extension[16] = "png";
124
 
  GooString *ownerPW, *userPW;
125
 
  Object info;
126
 
  char * extsList[] = {"png", "jpeg", "bmp", "pcx", "tiff", "pbm", NULL};
127
 
 
128
 
  // parse args
129
 
  ok = parseArgs(argDesc, &argc, argv);
130
 
  if (!ok || argc < 2 || argc > 3 || printHelp || printVersion) {
131
 
    fprintf(stderr, "pdftohtml version %s http://pdftohtml.sourceforge.net/, based on Xpdf version %s\n", "0.36", xpdfVersion);
132
 
    fprintf(stderr, "%s\n", "Copyright 1999-2003 Gueorgui Ovtcharov and Rainer Dorsch");
133
 
    fprintf(stderr, "%s\n\n", xpdfCopyright);
134
 
    if (!printVersion) {
135
 
      printUsage("pdftohtml", "<PDF-file> [<html-file> <xml-file>]", argDesc);
136
 
    }
137
 
    exit(1);
138
 
  }
139
 
 
140
 
  // init error file
141
 
  //errorInit();
142
 
 
143
 
  // read config file
144
 
  globalParams = new GlobalParams("");
145
 
 
146
 
  if (errQuiet) {
147
 
    globalParams->setErrQuiet(errQuiet);
148
 
    printCommands = gFalse; // I'm not 100% what is the differecne between them
149
 
  }
150
 
 
151
 
  if (textEncName[0]) {
152
 
    globalParams->setTextEncoding(textEncName);
153
 
    if( !globalParams->getTextEncoding() )  {
154
 
        goto error;    
155
 
    }
156
 
  }
157
 
 
158
 
  // open PDF file
159
 
  if (ownerPassword[0]) {
160
 
    ownerPW = new GooString(ownerPassword);
161
 
  } else {
162
 
    ownerPW = NULL;
163
 
  }
164
 
  if (userPassword[0]) {
165
 
    userPW = new GooString(userPassword);
166
 
  } else {
167
 
    userPW = NULL;
168
 
  }
169
 
 
170
 
  fileName = new GooString(argv[1]);
171
 
 
172
 
  doc = new PDFDoc(fileName, ownerPW, userPW);
173
 
  if (userPW) {
174
 
    delete userPW;
175
 
  }
176
 
  if (ownerPW) {
177
 
    delete ownerPW;
178
 
  }
179
 
  if (!doc->isOk()) {
180
 
    goto error;
181
 
  }
182
 
 
183
 
  // check for copy permission
184
 
  if (!doc->okToCopy()) {
185
 
    if (!noDrm) {
186
 
      error(-1, "Copying of text from this document is not allowed.");
187
 
      goto error;
188
 
    }
189
 
    fprintf(stderr, "Document has copy-protection bit set.\n");
190
 
  }
191
 
 
192
 
  // construct text file name
193
 
  if (argc == 3) {
194
 
    GooString* tmp = new GooString(argv[2]);
195
 
    p=tmp->getCString()+tmp->getLength()-5;
196
 
    if (!xml)
197
 
      if (!strcmp(p, ".html") || !strcmp(p, ".HTML"))
198
 
        htmlFileName = new GooString(tmp->getCString(),
199
 
                                   tmp->getLength() - 5);
200
 
      else htmlFileName =new GooString(tmp);
201
 
    else   
202
 
      if (!strcmp(p, ".xml") || !strcmp(p, ".XML"))
203
 
        htmlFileName = new GooString(tmp->getCString(),
204
 
                                   tmp->getLength() - 5);
205
 
      else htmlFileName =new GooString(tmp);
206
 
    
207
 
    delete tmp;
208
 
  } else {
209
 
    p = fileName->getCString() + fileName->getLength() - 4;
210
 
    if (!strcmp(p, ".pdf") || !strcmp(p, ".PDF"))
211
 
      htmlFileName = new GooString(fileName->getCString(),
212
 
                                 fileName->getLength() - 4);
213
 
    else
214
 
      htmlFileName = fileName->copy();
215
 
    //   htmlFileName->append(".html");
216
 
  }
217
 
  
218
 
   if (scale>3.0) scale=3.0;
219
 
   if (scale<0.5) scale=0.5;
220
 
   
221
 
   if (complexMode) {
222
 
     //noframes=gFalse;
223
 
     stout=gFalse;
224
 
   } 
225
 
 
226
 
   if (stout) {
227
 
     noframes=gTrue;
228
 
     complexMode=gFalse;
229
 
   }
230
 
 
231
 
   if (xml)
232
 
   { 
233
 
       complexMode = gTrue;
234
 
       noframes = gTrue;
235
 
       noMerge = gTrue;
236
 
   }
237
 
 
238
 
  // get page range
239
 
  if (firstPage < 1)
240
 
    firstPage = 1;
241
 
  if (lastPage < 1 || lastPage > doc->getNumPages())
242
 
    lastPage = doc->getNumPages();
243
 
 
244
 
  doc->getDocInfo(&info);
245
 
  if (info.isDict()) {
246
 
    docTitle = getInfoString(info.getDict(), "Title");
247
 
    author = getInfoString(info.getDict(), "Author");
248
 
    keywords = getInfoString(info.getDict(), "Keywords");
249
 
    subject = getInfoString(info.getDict(), "Subject");
250
 
    date = getInfoDate(info.getDict(), "ModDate");
251
 
    if( !date )
252
 
        date = getInfoDate(info.getDict(), "CreationDate");
253
 
  }
254
 
  info.free();
255
 
  if( !docTitle ) docTitle = new GooString(htmlFileName);
256
 
 
257
 
  /* determine extensions of output backgroun images */
258
 
  {int i;
259
 
  for(i = 0; extsList[i]; i++)
260
 
  {
261
 
          if( strstr(gsDevice, extsList[i]) != (char *) NULL )
262
 
          {
263
 
                  strncpy(extension, extsList[i], sizeof(extension));
264
 
                  break;
265
 
          }
266
 
  }}
267
 
 
268
 
  rawOrder = complexMode; // todo: figure out what exactly rawOrder do :)
269
 
 
270
 
  // write text file
271
 
  htmlOut = new HtmlOutputDev(htmlFileName->getCString(), 
272
 
          docTitle->getCString(), 
273
 
          author ? author->getCString() : NULL,
274
 
          keywords ? keywords->getCString() : NULL, 
275
 
          subject ? subject->getCString() : NULL, 
276
 
          date ? date->getCString() : NULL,
277
 
          extension,
278
 
          rawOrder, 
279
 
          firstPage,
280
 
          doc->getCatalog()->getOutline()->isDict());
281
 
  delete docTitle;
282
 
  if( author )
283
 
  {   
284
 
      delete author;
285
 
  }
286
 
  if( keywords )
287
 
  {
288
 
      delete keywords;
289
 
  }
290
 
  if( subject )
291
 
  {
292
 
      delete subject;
293
 
  }
294
 
  if( date )
295
 
  {
296
 
      delete date;
297
 
  }
298
 
 
299
 
  if (htmlOut->isOk())
300
 
  {
301
 
    doc->displayPages(htmlOut, firstPage, lastPage, 72, 72, static_cast<int>(72*scale), 0, gTrue);
302
 
        if (!xml)
303
 
        {
304
 
                htmlOut->dumpDocOutline(doc->getCatalog());
305
 
        }
306
 
  }
307
 
  
308
 
  if( complexMode && !xml && !ignore ) {
309
 
    int h=xoutRound(htmlOut->getPageHeight()/scale);
310
 
    int w=xoutRound(htmlOut->getPageWidth()/scale);
311
 
    //int h=xoutRound(doc->getPageHeight(1)/scale);
312
 
    //int w=xoutRound(doc->getPageWidth(1)/scale);
313
 
 
314
 
    psFileName = new GooString(htmlFileName->getCString());
315
 
    psFileName->append(".ps");
316
 
 
317
 
    globalParams->setPSPaperWidth(w);
318
 
    globalParams->setPSPaperHeight(h);
319
 
    // XXX
320
 
    // globalParams->setPSNoText(gTrue);
321
 
    psOut = new PSOutputDev(psFileName->getCString(), doc->getXRef(),
322
 
                            doc->getCatalog(), firstPage, lastPage, psModePS);
323
 
    doc->displayPages(psOut, firstPage, lastPage, 72, 72,
324
 
            static_cast<int>(72*scale), 0, gFalse);
325
 
    delete psOut;
326
 
 
327
 
    /*sprintf(buf, "%s -sDEVICE=png16m -dBATCH -dNOPROMPT -dNOPAUSE -r72 -sOutputFile=%s%%03d.png -g%dx%d -q %s", GHOSTSCRIPT, htmlFileName->getCString(), w, h,
328
 
      psFileName->getCString());*/
329
 
    
330
 
    GooString *gsCmd = new GooString(GHOSTSCRIPT);
331
 
    GooString *tw, *th, *sc;
332
 
    gsCmd->append(" -sDEVICE=");
333
 
        gsCmd->append(gsDevice);
334
 
        gsCmd->append(" -dBATCH -dNOPROMPT -dNOPAUSE -r");
335
 
    sc = GooString::fromInt(static_cast<int>(72*scale));
336
 
    gsCmd->append(sc);
337
 
    gsCmd->append(" -sOutputFile=");
338
 
    gsCmd->append("\"");
339
 
    gsCmd->append(htmlFileName);
340
 
    gsCmd->append("%03d.");
341
 
        gsCmd->append(extension);
342
 
        gsCmd->append("\" -g");
343
 
    tw = GooString::fromInt(static_cast<int>(scale*w));
344
 
    gsCmd->append(tw);
345
 
    gsCmd->append("x");
346
 
    th = GooString::fromInt(static_cast<int>(scale*h));
347
 
    gsCmd->append(th);
348
 
    gsCmd->append(" -q \"");
349
 
    gsCmd->append(psFileName);
350
 
    gsCmd->append("\"");
351
 
//    printf("running: %s\n", gsCmd->getCString());
352
 
    if( !executeCommand(gsCmd->getCString()) && !errQuiet) {
353
 
      error(-1, "Failed to launch Ghostscript!\n");
354
 
    }
355
 
    unlink(psFileName->getCString());
356
 
    delete tw;
357
 
    delete th;
358
 
    delete sc;
359
 
    delete gsCmd;
360
 
    delete psFileName;
361
 
  }
362
 
  
363
 
  delete htmlOut;
364
 
 
365
 
  // clean up
366
 
 error:
367
 
  if(doc) delete doc;
368
 
  if(globalParams) delete globalParams;
369
 
 
370
 
  if(htmlFileName) delete htmlFileName;
371
 
  HtmlFont::clear();
372
 
  
373
 
  // check for memory leaks
374
 
  Object::memCheck(stderr);
375
 
  gMemReport(stderr);
376
 
 
377
 
  return 0;
378
 
}
379
 
 
380
 
static GooString* getInfoString(Dict *infoDict, char *key) {
381
 
  Object obj;
382
 
  GooString *s1 = NULL;
383
 
 
384
 
  if (infoDict->lookup(key, &obj)->isString()) {
385
 
    s1 = new GooString(obj.getString());
386
 
  }
387
 
  obj.free();
388
 
  return s1;
389
 
}
390
 
 
391
 
static GooString* getInfoDate(Dict *infoDict, char *key) {
392
 
  Object obj;
393
 
  char *s;
394
 
  int year, mon, day, hour, min, sec;
395
 
  struct tm tmStruct;
396
 
  GooString *result = NULL;
397
 
  char buf[256];
398
 
 
399
 
  if (infoDict->lookup(key, &obj)->isString()) {
400
 
    s = obj.getString()->getCString();
401
 
    if (s[0] == 'D' && s[1] == ':') {
402
 
      s += 2;
403
 
    }
404
 
    if (sscanf(s, "%4d%2d%2d%2d%2d%2d",
405
 
               &year, &mon, &day, &hour, &min, &sec) == 6) {
406
 
      tmStruct.tm_year = year - 1900;
407
 
      tmStruct.tm_mon = mon - 1;
408
 
      tmStruct.tm_mday = day;
409
 
      tmStruct.tm_hour = hour;
410
 
      tmStruct.tm_min = min;
411
 
      tmStruct.tm_sec = sec;
412
 
      tmStruct.tm_wday = -1;
413
 
      tmStruct.tm_yday = -1;
414
 
      tmStruct.tm_isdst = -1;
415
 
      mktime(&tmStruct); // compute the tm_wday and tm_yday fields
416
 
      if (strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S+00:00", &tmStruct)) {
417
 
        result = new GooString(buf);
418
 
      } else {
419
 
        result = new GooString(s);
420
 
      }
421
 
    } else {
422
 
      result = new GooString(s);
423
 
    }
424
 
  }
425
 
  obj.free();
426
 
  return result;
427
 
}
428