~ubuntu-branches/ubuntu/precise/ipe/precise

« back to all changes in this revision

Viewing changes to src/xpdflib/parser.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Steve M. Robbins
  • Date: 2005-02-24 22:09:16 UTC
  • mfrom: (2.1.1 hoary)
  • Revision ID: james.westby@ubuntu.com-20050224220916-9vxiiqjz066r5489
Tags: 6.0pre23-2
debian/control: Ipe should depend on exact version of libipe.
Closes: #296771.

Show diffs side-by-side

added added

removed removed

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