1 //========================================================================
5 // Copyright 1996-2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
26 Parser::Parser(XRef *xrefA, Lexer *lexerA) {
41 Object *Parser::getObj(Object *obj,
42 Guchar *fileKey, int keyLength,
43 int objNum, int objGen) {
45 Object *Parser::getObj(Object *obj) {
58 // refill buffer after inline image data
68 if (buf1.isCmd("[")) {
71 while (!buf1.isCmd("]") && !buf1.isEOF())
73 obj->arrayAdd(getObj(&obj2, fileKey, keyLength, objNum, objGen));
75 obj->arrayAdd(getObj(&obj2));
78 error(getPos(), "End of file inside array");
81 // dictionary or stream
82 } else if (buf1.isCmd("<<")) {
85 while (!buf1.isCmd(">>") && !buf1.isEOF()) {
87 error(getPos(), "Dictionary key must be a name object");
90 key = copyString(buf1.getName());
92 if (buf1.isEOF() || buf1.isError()) {
97 obj->dictAdd(key, getObj(&obj2, fileKey, keyLength, objNum, objGen));
99 obj->dictAdd(key, getObj(&obj2));
104 error(getPos(), "End of file inside dictionary");
105 if (buf2.isCmd("stream")) {
106 if ((str = makeStream(obj))) {
107 obj->initStream(str);
108 #ifndef NO_DECRYPTION
110 str->getBaseStream()->doDecryption(fileKey, keyLength,
122 // indirect reference or integer
123 } else if (buf1.isInt()) {
126 if (buf1.isInt() && buf2.isCmd("R")) {
127 obj->initRef(num, buf1.getInt());
134 #ifndef NO_DECRYPTION
136 } else if (buf1.isString() && fileKey) {
138 s = obj->getString();
139 decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
140 for (i = 0, p = obj->getString()->getCString();
143 *p = decrypt->decryptByte(*p);
158 Stream *Parser::makeStream(Object *dict) {
161 Guint pos, endPos, length;
163 // get stream start position
164 lexer->skipToNextLine();
165 pos = lexer->getPos();
168 dict->dictLookup("Length", &obj);
170 length = (Guint)obj.getInt();
173 error(getPos(), "Bad 'Length' attribute in stream");
178 // check for length in damaged file
179 if (xref && xref->getStreamEnd(pos, &endPos)) {
180 length = endPos - pos;
183 // in badly damaged PDF files, we can run off the end of the input
184 // stream immediately after the "stream" token
185 if (!lexer->getStream()) {
190 str = lexer->getStream()->getBaseStream()->makeSubStream(pos, gTrue,
194 str = str->addFilters(dict);
196 // skip over stream data
197 lexer->setPos(pos + length);
199 // refill token buffers and check for 'endstream'
200 shift(); // kill '>>'
201 shift(); // kill 'stream'
202 if (buf1.isCmd("endstream")) {
205 error(getPos(), "Missing 'endstream'");
212 void Parser::shift() {
217 // in a damaged content stream, if 'ID' shows up in the middle
218 // of a dictionary, we need to reset
221 } else if (buf2.isCmd("ID")) {
222 lexer->skipChar(); // skip char after 'ID' command
227 if (inlineImg > 0) // don't buffer inline image data
230 lexer->getObj(&buf2);