upgrade to xpdf 3.00.
[swftools.git] / pdf2swf / xpdf / Parser.cc
index 6ad0c5a..0aa66d3 100644 (file)
@@ -2,11 +2,13 @@
 //
 // Parser.cc
 //
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
 #pragma implementation
 #endif
 
@@ -21,8 +23,9 @@
 #include "Decrypt.h"
 #endif
 
-Parser::Parser(Lexer *lexer1) {
-  lexer = lexer1;
+Parser::Parser(XRef *xrefA, Lexer *lexerA) {
+  xref = xrefA;
+  lexer = lexerA;
   inlineImg = 0;
   lexer->getObj(&buf1);
   lexer->getObj(&buf2);
@@ -36,7 +39,8 @@ Parser::~Parser() {
 
 #ifndef NO_DECRYPTION
 Object *Parser::getObj(Object *obj,
-                      Guchar *fileKey, int objNum, int objGen) {
+                      Guchar *fileKey, int keyLength,
+                      int objNum, int objGen) {
 #else
 Object *Parser::getObj(Object *obj) {
 #endif
@@ -63,10 +67,10 @@ Object *Parser::getObj(Object *obj) {
   // array
   if (buf1.isCmd("[")) {
     shift();
-    obj->initArray();
+    obj->initArray(xref);
     while (!buf1.isCmd("]") && !buf1.isEOF())
 #ifndef NO_DECRYPTION
-      obj->arrayAdd(getObj(&obj2, fileKey, objNum, objGen));
+      obj->arrayAdd(getObj(&obj2, fileKey, keyLength, objNum, objGen));
 #else
       obj->arrayAdd(getObj(&obj2));
 #endif
@@ -77,7 +81,7 @@ Object *Parser::getObj(Object *obj) {
   // dictionary or stream
   } else if (buf1.isCmd("<<")) {
     shift();
-    obj->initDict();
+    obj->initDict(xref);
     while (!buf1.isCmd(">>") && !buf1.isEOF()) {
       if (!buf1.isName()) {
        error(getPos(), "Dictionary key must be a name object");
@@ -85,10 +89,12 @@ Object *Parser::getObj(Object *obj) {
       } else {
        key = copyString(buf1.getName());
        shift();
-       if (buf1.isEOF() || buf1.isError())
+       if (buf1.isEOF() || buf1.isError()) {
+         gfree(key);
          break;
+       }
 #ifndef NO_DECRYPTION
-       obj->dictAdd(key, getObj(&obj2, fileKey, objNum, objGen));
+       obj->dictAdd(key, getObj(&obj2, fileKey, keyLength, objNum, objGen));
 #else
        obj->dictAdd(key, getObj(&obj2));
 #endif
@@ -101,7 +107,8 @@ Object *Parser::getObj(Object *obj) {
        obj->initStream(str);
 #ifndef NO_DECRYPTION
        if (fileKey) {
-         str->getBaseStream()->doDecryption(fileKey, objNum, objGen);
+         str->getBaseStream()->doDecryption(fileKey, keyLength,
+                                            objNum, objGen);
        }
 #endif
       } else {
@@ -129,7 +136,7 @@ Object *Parser::getObj(Object *obj) {
   } else if (buf1.isString() && fileKey) {
     buf1.copy(obj);
     s = obj->getString();
-    decrypt = new Decrypt(fileKey, objNum, objGen);
+    decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
     for (i = 0, p = obj->getString()->getCString();
         i < s->getLength();
         ++i, ++p) {
@@ -151,7 +158,7 @@ Object *Parser::getObj(Object *obj) {
 Stream *Parser::makeStream(Object *dict) {
   Object obj;
   Stream *str;
-  int pos, endPos, length;
+  Guint pos, endPos, length;
 
   // get stream start position
   lexer->skipToNextLine();
@@ -160,7 +167,7 @@ Stream *Parser::makeStream(Object *dict) {
   // get length
   dict->dictLookup("Length", &obj);
   if (obj.isInt()) {
-    length = obj.getInt();
+    length = (Guint)obj.getInt();
     obj.free();
   } else {
     error(getPos(), "Bad 'Length' attribute in stream");
@@ -169,12 +176,19 @@ Stream *Parser::makeStream(Object *dict) {
   }
 
   // check for length in damaged file
-  if ((endPos = xref->getStreamEnd(pos)) >= 0) {
+  if (xref && xref->getStreamEnd(pos, &endPos)) {
     length = endPos - pos;
   }
 
+  // in badly damaged PDF files, we can run off the end of the input
+  // stream immediately after the "stream" token
+  if (!lexer->getStream()) {
+    return NULL;
+  }
+
   // make base stream
-  str = lexer->getStream()->getBaseStream()->makeSubStream(pos, length, dict);
+  str = lexer->getStream()->getBaseStream()->makeSubStream(pos, gTrue,
+                                                          length, dict);
 
   // get filters
   str = str->addFilters(dict);
@@ -185,17 +199,25 @@ Stream *Parser::makeStream(Object *dict) {
   // refill token buffers and check for 'endstream'
   shift();  // kill '>>'
   shift();  // kill 'stream'
-  if (buf1.isCmd("endstream"))
+  if (buf1.isCmd("endstream")) {
     shift();
-  else
+  } else {
     error(getPos(), "Missing 'endstream'");
+    str->ignoreLength();
+  }
 
   return str;
 }
 
 void Parser::shift() {
   if (inlineImg > 0) {
-    ++inlineImg;
+    if (inlineImg < 2) {
+      ++inlineImg;
+    } else {
+      // in a damaged content stream, if 'ID' shows up in the middle
+      // of a dictionary, we need to reset
+      inlineImg = 0;
+    }
   } else if (buf2.isCmd("ID")) {
     lexer->skipChar();         // skip char after 'ID' command
     inlineImg = 1;