Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

Parser.cc

Go to the documentation of this file.
00001 //========================================================================
00002 //
00003 // Parser.cc
00004 //
00005 // Copyright 1996-2002 Glyph & Cog, LLC
00006 //
00007 //========================================================================
00008 
00009 #ifdef __GNUC__
00010 #pragma implementation
00011 #endif
00012 
00013 #include <aconf.h>
00014 #include <stddef.h>
00015 #include "Object.h"
00016 #include "Array.h"
00017 #include "Dict.h"
00018 #include "Parser.h"
00019 #include "XRef.h"
00020 #include "Error.h"
00021 #ifndef NO_DECRYPTION
00022 #include "Decrypt.h"
00023 #endif
00024 
00025 Parser::Parser(XRef *xrefA, Lexer *lexerA) {
00026   xref = xrefA;
00027   lexer = lexerA;
00028   inlineImg = 0;
00029   lexer->getObj(&buf1);
00030   lexer->getObj(&buf2);
00031 }
00032 
00033 Parser::~Parser() {
00034   buf1.free();
00035   buf2.free();
00036   delete lexer;
00037 }
00038 
00039 #ifndef NO_DECRYPTION
00040 Object *Parser::getObj(Object *obj,
00041                        Guchar *fileKey, int keyLength,
00042                        int objNum, int objGen) {
00043 #else
00044 Object *Parser::getObj(Object *obj) {
00045 #endif
00046   char *key;
00047   Stream *str;
00048   Object obj2;
00049   int num;
00050 #ifndef NO_DECRYPTION
00051   Decrypt *decrypt;
00052   GString *s;
00053   char *p;
00054   int i;
00055 #endif
00056 
00057   // refill buffer after inline image data
00058   if (inlineImg == 2) {
00059     buf1.free();
00060     buf2.free();
00061     lexer->getObj(&buf1);
00062     lexer->getObj(&buf2);
00063     inlineImg = 0;
00064   }
00065 
00066   // array
00067   if (buf1.isCmd("[")) {
00068     shift();
00069     obj->initArray(xref);
00070     while (!buf1.isCmd("]") && !buf1.isEOF())
00071 #ifndef NO_DECRYPTION
00072       obj->arrayAdd(getObj(&obj2, fileKey, keyLength, objNum, objGen));
00073 #else
00074       obj->arrayAdd(getObj(&obj2));
00075 #endif
00076     if (buf1.isEOF())
00077       error(getPos(), "End of file inside array");
00078     shift();
00079 
00080   // dictionary or stream
00081   } else if (buf1.isCmd("<<")) {
00082     shift();
00083     obj->initDict(xref);
00084     while (!buf1.isCmd(">>") && !buf1.isEOF()) {
00085       if (!buf1.isName()) {
00086         error(getPos(), "Dictionary key must be a name object");
00087         shift();
00088       } else {
00089         key = copyString(buf1.getName());
00090         shift();
00091         if (buf1.isEOF() || buf1.isError())
00092           break;
00093 #ifndef NO_DECRYPTION
00094         obj->dictAdd(key, getObj(&obj2, fileKey, keyLength, objNum, objGen));
00095 #else
00096         obj->dictAdd(key, getObj(&obj2));
00097 #endif
00098       }
00099     }
00100     if (buf1.isEOF())
00101       error(getPos(), "End of file inside dictionary");
00102     if (buf2.isCmd("stream")) {
00103       if ((str = makeStream(obj))) {
00104         obj->initStream(str);
00105 #ifndef NO_DECRYPTION
00106         if (fileKey) {
00107           str->getBaseStream()->doDecryption(fileKey, keyLength,
00108                                              objNum, objGen);
00109         }
00110 #endif
00111       } else {
00112         obj->free();
00113         obj->initError();
00114       }
00115     } else {
00116       shift();
00117     }
00118 
00119   // indirect reference or integer
00120   } else if (buf1.isInt()) {
00121     num = buf1.getInt();
00122     shift();
00123     if (buf1.isInt() && buf2.isCmd("R")) {
00124       obj->initRef(num, buf1.getInt());
00125       shift();
00126       shift();
00127     } else {
00128       obj->initInt(num);
00129     }
00130 
00131 #ifndef NO_DECRYPTION
00132   // string
00133   } else if (buf1.isString() && fileKey) {
00134     buf1.copy(obj);
00135     s = obj->getString();
00136     decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
00137     for (i = 0, p = obj->getString()->getCString();
00138          i < s->getLength();
00139          ++i, ++p) {
00140       *p = decrypt->decryptByte(*p);
00141     }
00142     delete decrypt;
00143     shift();
00144 #endif
00145 
00146   // simple object
00147   } else {
00148     buf1.copy(obj);
00149     shift();
00150   }
00151 
00152   return obj;
00153 }
00154 
00155 Stream *Parser::makeStream(Object *dict) {
00156   Object obj;
00157   Stream *str;
00158   Guint pos, endPos, length;
00159 
00160   // get stream start position
00161   lexer->skipToNextLine();
00162   pos = lexer->getPos();
00163 
00164   // get length
00165   dict->dictLookup("Length", &obj);
00166   if (obj.isInt()) {
00167     length = (Guint)obj.getInt();
00168     obj.free();
00169   } else {
00170     error(getPos(), "Bad 'Length' attribute in stream");
00171     obj.free();
00172     return NULL;
00173   }
00174 
00175   // check for length in damaged file
00176   if (xref->getStreamEnd(pos, &endPos)) {
00177     length = endPos - pos;
00178   }
00179 
00180   // make base stream
00181   str = lexer->getStream()->getBaseStream()->makeSubStream(pos, gTrue,
00182                                                            length, dict);
00183 
00184   // get filters
00185   str = str->addFilters(dict);
00186 
00187   // skip over stream data
00188   lexer->setPos(pos + length);
00189 
00190   // refill token buffers and check for 'endstream'
00191   shift();  // kill '>>'
00192   shift();  // kill 'stream'
00193   if (buf1.isCmd("endstream"))
00194     shift();
00195   else
00196     error(getPos(), "Missing 'endstream'");
00197 
00198   return str;
00199 }
00200 
00201 void Parser::shift() {
00202   if (inlineImg > 0) {
00203     ++inlineImg;
00204   } else if (buf2.isCmd("ID")) {
00205     lexer->skipChar();          // skip char after 'ID' command
00206     inlineImg = 1;
00207   }
00208   buf1.free();
00209   buf1 = buf2;
00210   if (inlineImg > 0)            // don't buffer inline image data
00211     buf2.initNull();
00212   else
00213     lexer->getObj(&buf2);
00214 }

Generated on Sat Nov 5 16:18:16 2005 for OPIE by  doxygen 1.4.2