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