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