Initial revision
[swftools.git] / pdf2swf / xpdf / Parser.cc
1 //========================================================================
2 //
3 // Parser.cc
4 //
5 // Copyright 1996 Derek B. Noonburg
6 //
7 //========================================================================
8
9 #ifdef __GNUC__
10 #pragma implementation
11 #endif
12
13 #include <stddef.h>
14 #include "Object.h"
15 #include "Array.h"
16 #include "Dict.h"
17 #include "Parser.h"
18 #include "XRef.h"
19 #include "Error.h"
20 #ifndef NO_DECRYPTION
21 #include "Decrypt.h"
22 #endif
23
24 Parser::Parser(Lexer *lexer1) {
25   lexer = lexer1;
26   inlineImg = 0;
27   lexer->getObj(&buf1);
28   lexer->getObj(&buf2);
29 }
30
31 Parser::~Parser() {
32   buf1.free();
33   buf2.free();
34   delete lexer;
35 }
36
37 #ifndef NO_DECRYPTION
38 Object *Parser::getObj(Object *obj,
39                        Guchar *fileKey, int objNum, int objGen) {
40 #else
41 Object *Parser::getObj(Object *obj) {
42 #endif
43   char *key;
44   Stream *str;
45   Object obj2;
46   int num;
47 #ifndef NO_DECRYPTION
48   Decrypt *decrypt;
49   GString *s;
50   char *p;
51   int i;
52 #endif
53
54   // refill buffer after inline image data
55   if (inlineImg == 2) {
56     buf1.free();
57     buf2.free();
58     lexer->getObj(&buf1);
59     lexer->getObj(&buf2);
60     inlineImg = 0;
61   }
62
63   // array
64   if (buf1.isCmd("[")) {
65     shift();
66     obj->initArray();
67     while (!buf1.isCmd("]") && !buf1.isEOF())
68 #ifndef NO_DECRYPTION
69       obj->arrayAdd(getObj(&obj2, fileKey, objNum, objGen));
70 #else
71       obj->arrayAdd(getObj(&obj2));
72 #endif
73     if (buf1.isEOF())
74       error(getPos(), "End of file inside array");
75     shift();
76
77   // dictionary or stream
78   } else if (buf1.isCmd("<<")) {
79     shift();
80     obj->initDict();
81     while (!buf1.isCmd(">>") && !buf1.isEOF()) {
82       if (!buf1.isName()) {
83         error(getPos(), "Dictionary key must be a name object");
84         shift();
85       } else {
86         key = copyString(buf1.getName());
87         shift();
88         if (buf1.isEOF() || buf1.isError())
89           break;
90 #ifndef NO_DECRYPTION
91         obj->dictAdd(key, getObj(&obj2, fileKey, objNum, objGen));
92 #else
93         obj->dictAdd(key, getObj(&obj2));
94 #endif
95       }
96     }
97     if (buf1.isEOF())
98       error(getPos(), "End of file inside dictionary");
99     if (buf2.isCmd("stream")) {
100       if ((str = makeStream(obj))) {
101         obj->initStream(str);
102 #ifndef NO_DECRYPTION
103         if (fileKey) {
104           str->getBaseStream()->doDecryption(fileKey, objNum, objGen);
105         }
106 #endif
107       } else {
108         obj->free();
109         obj->initError();
110       }
111     } else {
112       shift();
113     }
114
115   // indirect reference or integer
116   } else if (buf1.isInt()) {
117     num = buf1.getInt();
118     shift();
119     if (buf1.isInt() && buf2.isCmd("R")) {
120       obj->initRef(num, buf1.getInt());
121       shift();
122       shift();
123     } else {
124       obj->initInt(num);
125     }
126
127 #ifndef NO_DECRYPTION
128   // string
129   } else if (buf1.isString() && fileKey) {
130     buf1.copy(obj);
131     s = obj->getString();
132     decrypt = new Decrypt(fileKey, objNum, objGen);
133     for (i = 0, p = obj->getString()->getCString();
134          i < s->getLength();
135          ++i, ++p) {
136       *p = decrypt->decryptByte(*p);
137     }
138     delete decrypt;
139     shift();
140 #endif
141
142   // simple object
143   } else {
144     buf1.copy(obj);
145     shift();
146   }
147
148   return obj;
149 }
150
151 Stream *Parser::makeStream(Object *dict) {
152   Object obj;
153   Stream *str;
154   int pos, endPos, length;
155
156   // get stream start position
157   lexer->skipToNextLine();
158   pos = lexer->getPos();
159
160   // get length
161   dict->dictLookup("Length", &obj);
162   if (obj.isInt()) {
163     length = obj.getInt();
164     obj.free();
165   } else {
166     error(getPos(), "Bad 'Length' attribute in stream");
167     obj.free();
168     return NULL;
169   }
170
171   // check for length in damaged file
172   if ((endPos = xref->getStreamEnd(pos)) >= 0) {
173     length = endPos - pos;
174   }
175
176   // make base stream
177   str = lexer->getStream()->getBaseStream()->makeSubStream(pos, length, dict);
178
179   // get filters
180   str = str->addFilters(dict);
181
182   // skip over stream data
183   lexer->setPos(pos + length);
184
185   // refill token buffers and check for 'endstream'
186   shift();  // kill '>>'
187   shift();  // kill 'stream'
188   if (buf1.isCmd("endstream"))
189     shift();
190   else
191     error(getPos(), "Missing 'endstream'");
192
193   return str;
194 }
195
196 void Parser::shift() {
197   if (inlineImg > 0) {
198     ++inlineImg;
199   } else if (buf2.isCmd("ID")) {
200     lexer->skipChar();          // skip char after 'ID' command
201     inlineImg = 1;
202   }
203   buf1.free();
204   buf1 = buf2;
205   if (inlineImg > 0)            // don't buffer inline image data
206     buf2.initNull();
207   else
208     lexer->getObj(&buf2);
209 }