summaryrefslogtreecommitdiff
path: root/noncore/unsupported/qpdf/xpdf/XRef.cc
Unidiff
Diffstat (limited to 'noncore/unsupported/qpdf/xpdf/XRef.cc') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/unsupported/qpdf/xpdf/XRef.cc80
1 files changed, 52 insertions, 28 deletions
diff --git a/noncore/unsupported/qpdf/xpdf/XRef.cc b/noncore/unsupported/qpdf/xpdf/XRef.cc
index 5d526e9..0e1bbc9 100644
--- a/noncore/unsupported/qpdf/xpdf/XRef.cc
+++ b/noncore/unsupported/qpdf/xpdf/XRef.cc
@@ -1,11 +1,11 @@
1//======================================================================== 1//========================================================================
2// 2//
3// XRef.cc 3// XRef.cc
4// 4//
5// Copyright 1996 Derek B. Noonburg 5// Copyright 1996-2002 Glyph & Cog, LLC
6// 6//
7//======================================================================== 7//========================================================================
8 8
9#ifdef __GNUC__ 9#ifdef __GNUC__
10#pragma implementation 10#pragma implementation
11#endif 11#endif
@@ -22,12 +22,13 @@
22#include "Parser.h" 22#include "Parser.h"
23#include "Dict.h" 23#include "Dict.h"
24#ifndef NO_DECRYPTION 24#ifndef NO_DECRYPTION
25#include "Decrypt.h" 25#include "Decrypt.h"
26#endif 26#endif
27#include "Error.h" 27#include "Error.h"
28#include "ErrorCodes.h"
28#include "XRef.h" 29#include "XRef.h"
29 30
30//------------------------------------------------------------------------ 31//------------------------------------------------------------------------
31 32
32 #define xrefSearchSize 1024// read this many bytes at end of file 33 #define xrefSearchSize 1024// read this many bytes at end of file
33 // to look for 'startxref' 34 // to look for 'startxref'
@@ -46,16 +47,17 @@
46 47
47//------------------------------------------------------------------------ 48//------------------------------------------------------------------------
48// XRef 49// XRef
49//------------------------------------------------------------------------ 50//------------------------------------------------------------------------
50 51
51XRef::XRef(BaseStream *strA, GString *ownerPassword, GString *userPassword) { 52XRef::XRef(BaseStream *strA, GString *ownerPassword, GString *userPassword) {
52 int pos; 53 Guint pos;
53 int i; 54 int i;
54 55
55 ok = gTrue; 56 ok = gTrue;
57 errCode = errNone;
56 size = 0; 58 size = 0;
57 entries = NULL; 59 entries = NULL;
58 streamEnds = NULL; 60 streamEnds = NULL;
59 streamEndsLen = 0; 61 streamEndsLen = 0;
60 62
61 // read the trailer 63 // read the trailer
@@ -64,31 +66,33 @@ XRef::XRef(BaseStream *strA, GString *ownerPassword, GString *userPassword) {
64 pos = readTrailer(); 66 pos = readTrailer();
65 67
66 // if there was a problem with the trailer, 68 // if there was a problem with the trailer,
67 // try to reconstruct the xref table 69 // try to reconstruct the xref table
68 if (pos == 0) { 70 if (pos == 0) {
69 if (!(ok = constructXRef())) { 71 if (!(ok = constructXRef())) {
72 errCode = errDamaged;
70 return; 73 return;
71 } 74 }
72 75
73 // trailer is ok - read the xref table 76 // trailer is ok - read the xref table
74 } else { 77 } else {
75 entries = (XRefEntry *)gmalloc(size * sizeof(XRefEntry)); 78 entries = (XRefEntry *)gmalloc(size * sizeof(XRefEntry));
76 for (i = 0; i < size; ++i) { 79 for (i = 0; i < size; ++i) {
77 entries[i].offset = -1; 80 entries[i].offset = 0xffffffff;
78 entries[i].used = gFalse; 81 entries[i].used = gFalse;
79 } 82 }
80 while (readXRef(&pos)) ; 83 while (readXRef(&pos)) ;
81 84
82 // if there was a problem with the xref table, 85 // if there was a problem with the xref table,
83 // try to reconstruct it 86 // try to reconstruct it
84 if (!ok) { 87 if (!ok) {
85 gfree(entries); 88 gfree(entries);
86 size = 0; 89 size = 0;
87 entries = NULL; 90 entries = NULL;
88 if (!(ok = constructXRef())) { 91 if (!(ok = constructXRef())) {
92 errCode = errDamaged;
89 return; 93 return;
90 } 94 }
91 } 95 }
92 } 96 }
93 97
94 // now set the trailer dictionary's xref pointer so we can fetch 98 // now set the trailer dictionary's xref pointer so we can fetch
@@ -98,12 +102,13 @@ XRef::XRef(BaseStream *strA, GString *ownerPassword, GString *userPassword) {
98 // check for encryption 102 // check for encryption
99#ifndef NO_DECRYPTION 103#ifndef NO_DECRYPTION
100 encrypted = gFalse; 104 encrypted = gFalse;
101#endif 105#endif
102 if (checkEncrypted(ownerPassword, userPassword)) { 106 if (checkEncrypted(ownerPassword, userPassword)) {
103 ok = gFalse; 107 ok = gFalse;
108 errCode = errEncrypted;
104 return; 109 return;
105 } 110 }
106} 111}
107 112
108XRef::~XRef() { 113XRef::~XRef() {
109 gfree(entries); 114 gfree(entries);
@@ -112,23 +117,24 @@ XRef::~XRef() {
112 gfree(streamEnds); 117 gfree(streamEnds);
113 } 118 }
114} 119}
115 120
116// Read startxref position, xref table size, and root. Returns 121// Read startxref position, xref table size, and root. Returns
117// first xref position. 122// first xref position.
118int XRef::readTrailer() { 123Guint XRef::readTrailer() {
119 Parser *parser; 124 Parser *parser;
120 Object obj; 125 Object obj;
121 char buf[xrefSearchSize+1]; 126 char buf[xrefSearchSize+1];
122 int n, pos, pos1; 127 int n;
128 Guint pos, pos1;
123 char *p; 129 char *p;
124 int c; 130 int c;
125 int i; 131 int i;
126 132
127 // read last xrefSearchSize bytes 133 // read last xrefSearchSize bytes
128 str->setPos(-xrefSearchSize); 134 str->setPos(xrefSearchSize, -1);
129 for (n = 0; n < xrefSearchSize; ++n) { 135 for (n = 0; n < xrefSearchSize; ++n) {
130 if ((c = str->getChar()) == EOF) 136 if ((c = str->getChar()) == EOF)
131 break; 137 break;
132 buf[n] = c; 138 buf[n] = c;
133 } 139 }
134 buf[n] = '\0'; 140 buf[n] = '\0';
@@ -138,13 +144,13 @@ int XRef::readTrailer() {
138 if (!strncmp(&buf[i], "startxref", 9)) 144 if (!strncmp(&buf[i], "startxref", 9))
139 break; 145 break;
140 } 146 }
141 if (i < 0) 147 if (i < 0)
142 return 0; 148 return 0;
143 for (p = &buf[i+9]; isspace(*p); ++p) ; 149 for (p = &buf[i+9]; isspace(*p); ++p) ;
144 pos = lastXRefPos = atoi(p); 150 pos = lastXRefPos = strToUnsigned(p);
145 151
146 // find trailer dict by looking after first xref table 152 // find trailer dict by looking after first xref table
147 // (NB: we can't just use the trailer dict at the end of the file -- 153 // (NB: we can't just use the trailer dict at the end of the file --
148 // this won't work for linearized files.) 154 // this won't work for linearized files.)
149 str->setPos(start + pos); 155 str->setPos(start + pos);
150 for (i = 0; i < 4; ++i) 156 for (i = 0; i < 4; ++i)
@@ -173,14 +179,15 @@ int XRef::readTrailer() {
173 pos1 += (p - buf) + n * 20; 179 pos1 += (p - buf) + n * 20;
174 } 180 }
175 pos1 += 7; 181 pos1 += 7;
176 182
177 // read trailer dict 183 // read trailer dict
178 obj.initNull(); 184 obj.initNull();
179 parser = new Parser(NULL, new Lexer(NULL, str->makeSubStream(start + pos1, 185 parser = new Parser(NULL,
180 -1, &obj))); 186 new Lexer(NULL,
187 str->makeSubStream(start + pos1, gFalse, 0, &obj)));
181 parser->getObj(&trailerDict); 188 parser->getObj(&trailerDict);
182 if (trailerDict.isDict()) { 189 if (trailerDict.isDict()) {
183 trailerDict.dictLookupNF("Size", &obj); 190 trailerDict.dictLookupNF("Size", &obj);
184 if (obj.isInt()) 191 if (obj.isInt())
185 size = obj.getInt(); 192 size = obj.getInt();
186 else 193 else
@@ -201,13 +208,13 @@ int XRef::readTrailer() {
201 208
202 // return first xref position 209 // return first xref position
203 return pos; 210 return pos;
204} 211}
205 212
206// Read an xref table and the prev pointer from the trailer. 213// Read an xref table and the prev pointer from the trailer.
207GBool XRef::readXRef(int *pos) { 214GBool XRef::readXRef(Guint *pos) {
208 Parser *parser; 215 Parser *parser;
209 Object obj, obj2; 216 Object obj, obj2;
210 char s[20]; 217 char s[20];
211 GBool more; 218 GBool more;
212 int first, newSize, n, i, j; 219 int first, newSize, n, i, j;
213 int c; 220 int c;
@@ -258,27 +265,27 @@ GBool XRef::readXRef(int *pos) {
258 // check for buggy PDF files with an incorrect (too small) xref 265 // check for buggy PDF files with an incorrect (too small) xref
259 // table size 266 // table size
260 if (first + n > size) { 267 if (first + n > size) {
261 newSize = size + 256; 268 newSize = size + 256;
262 entries = (XRefEntry *)grealloc(entries, newSize * sizeof(XRefEntry)); 269 entries = (XRefEntry *)grealloc(entries, newSize * sizeof(XRefEntry));
263 for (i = size; i < newSize; ++i) { 270 for (i = size; i < newSize; ++i) {
264 entries[i].offset = -1; 271 entries[i].offset = 0xffffffff;
265 entries[i].used = gFalse; 272 entries[i].used = gFalse;
266 } 273 }
267 size = newSize; 274 size = newSize;
268 } 275 }
269 for (i = first; i < first + n; ++i) { 276 for (i = first; i < first + n; ++i) {
270 for (j = 0; j < 20; ++j) { 277 for (j = 0; j < 20; ++j) {
271 if ((c = str->getChar()) == EOF) { 278 if ((c = str->getChar()) == EOF) {
272 goto err2; 279 goto err2;
273 } 280 }
274 s[j] = (char)c; 281 s[j] = (char)c;
275 } 282 }
276 if (entries[i].offset < 0) { 283 if (entries[i].offset == 0xffffffff) {
277 s[10] = '\0'; 284 s[10] = '\0';
278 entries[i].offset = atoi(s); 285 entries[i].offset = strToUnsigned(s);
279 s[16] = '\0'; 286 s[16] = '\0';
280 entries[i].gen = atoi(&s[11]); 287 entries[i].gen = atoi(&s[11]);
281 if (s[17] == 'n') { 288 if (s[17] == 'n') {
282 entries[i].used = gTrue; 289 entries[i].used = gTrue;
283 } else if (s[17] == 'f') { 290 } else if (s[17] == 'f') {
284 entries[i].used = gFalse; 291 entries[i].used = gFalse;
@@ -290,34 +297,35 @@ GBool XRef::readXRef(int *pos) {
290 // instead of 0. 297 // instead of 0.
291 if (i == 1 && first == 1 && 298 if (i == 1 && first == 1 &&
292 entries[1].offset == 0 && entries[1].gen == 65535 && 299 entries[1].offset == 0 && entries[1].gen == 65535 &&
293 !entries[1].used) { 300 !entries[1].used) {
294 i = first = 0; 301 i = first = 0;
295 entries[0] = entries[1]; 302 entries[0] = entries[1];
296 entries[1].offset = -1; 303 entries[1].offset = 0xffffffff;
297 } 304 }
298 } 305 }
299 } 306 }
300 } 307 }
301 308
302 // read prev pointer from trailer dictionary 309 // read prev pointer from trailer dictionary
303 obj.initNull(); 310 obj.initNull();
304 parser = new Parser(NULL, new Lexer(NULL, str->makeSubStream(str->getPos(), 311 parser = new Parser(NULL,
305 -1, &obj))); 312 new Lexer(NULL,
313 str->makeSubStream(str->getPos(), gFalse, 0, &obj)));
306 parser->getObj(&obj); 314 parser->getObj(&obj);
307 if (!obj.isCmd("trailer")) { 315 if (!obj.isCmd("trailer")) {
308 goto err1; 316 goto err1;
309 } 317 }
310 obj.free(); 318 obj.free();
311 parser->getObj(&obj); 319 parser->getObj(&obj);
312 if (!obj.isDict()) { 320 if (!obj.isDict()) {
313 goto err1; 321 goto err1;
314 } 322 }
315 obj.getDict()->lookupNF("Prev", &obj2); 323 obj.getDict()->lookupNF("Prev", &obj2);
316 if (obj2.isInt()) { 324 if (obj2.isInt()) {
317 *pos = obj2.getInt(); 325 *pos = (Guint)obj2.getInt();
318 more = gTrue; 326 more = gTrue;
319 } else { 327 } else {
320 more = gFalse; 328 more = gFalse;
321 } 329 }
322 obj.free(); 330 obj.free();
323 obj2.free(); 331 obj2.free();
@@ -334,13 +342,13 @@ GBool XRef::readXRef(int *pos) {
334 342
335// Attempt to construct an xref table for a damaged file. 343// Attempt to construct an xref table for a damaged file.
336GBool XRef::constructXRef() { 344GBool XRef::constructXRef() {
337 Parser *parser; 345 Parser *parser;
338 Object obj; 346 Object obj;
339 char buf[256]; 347 char buf[256];
340 int pos; 348 Guint pos;
341 int num, gen; 349 int num, gen;
342 int newSize; 350 int newSize;
343 int streamEndsSize; 351 int streamEndsSize;
344 char *p; 352 char *p;
345 int i; 353 int i;
346 GBool gotRoot; 354 GBool gotRoot;
@@ -357,14 +365,15 @@ GBool XRef::constructXRef() {
357 } 365 }
358 p = buf; 366 p = buf;
359 367
360 // got trailer dictionary 368 // got trailer dictionary
361 if (!strncmp(p, "trailer", 7)) { 369 if (!strncmp(p, "trailer", 7)) {
362 obj.initNull(); 370 obj.initNull();
363 parser = new Parser(NULL, new Lexer(NULL, 371 parser = new Parser(NULL,
364 str->makeSubStream(start + pos + 7, -1, &obj))); 372 new Lexer(NULL,
373 str->makeSubStream(start + pos + 7, gFalse, 0, &obj)));
365 if (!trailerDict.isNone()) 374 if (!trailerDict.isNone())
366 trailerDict.free(); 375 trailerDict.free();
367 parser->getObj(&trailerDict); 376 parser->getObj(&trailerDict);
368 if (trailerDict.isDict()) { 377 if (trailerDict.isDict()) {
369 trailerDict.dictLookupNF("Root", &obj); 378 trailerDict.dictLookupNF("Root", &obj);
370 if (obj.isRef()) { 379 if (obj.isRef()) {
@@ -400,13 +409,13 @@ GBool XRef::constructXRef() {
400 if (!strncmp(p, "obj", 3)) { 409 if (!strncmp(p, "obj", 3)) {
401 if (num >= size) { 410 if (num >= size) {
402 newSize = (num + 1 + 255) & ~255; 411 newSize = (num + 1 + 255) & ~255;
403 entries = (XRefEntry *) 412 entries = (XRefEntry *)
404 grealloc(entries, newSize * sizeof(XRefEntry)); 413 grealloc(entries, newSize * sizeof(XRefEntry));
405 for (i = size; i < newSize; ++i) { 414 for (i = size; i < newSize; ++i) {
406 entries[i].offset = -1; 415 entries[i].offset = 0xffffffff;
407 entries[i].used = gFalse; 416 entries[i].used = gFalse;
408 } 417 }
409 size = newSize; 418 size = newSize;
410 } 419 }
411 if (!entries[num].used || gen >= entries[num].gen) { 420 if (!entries[num].used || gen >= entries[num].gen) {
412 entries[num].offset = pos - start; 421 entries[num].offset = pos - start;
@@ -418,13 +427,14 @@ GBool XRef::constructXRef() {
418 } 427 }
419 } 428 }
420 429
421 } else if (!strncmp(p, "endstream", 9)) { 430 } else if (!strncmp(p, "endstream", 9)) {
422 if (streamEndsLen == streamEndsSize) { 431 if (streamEndsLen == streamEndsSize) {
423 streamEndsSize += 64; 432 streamEndsSize += 64;
424 streamEnds = (int *)grealloc(streamEnds, streamEndsSize * sizeof(int)); 433 streamEnds = (Guint *)grealloc(streamEnds,
434 streamEndsSize * sizeof(int));
425 } 435 }
426 streamEnds[streamEndsLen++] = pos; 436 streamEnds[streamEndsLen++] = pos;
427 } 437 }
428 } 438 }
429 439
430 if (gotRoot) 440 if (gotRoot)
@@ -577,16 +587,17 @@ Object *XRef::fetch(int num, int gen, Object *obj) {
577 if (num < 0 || num >= size) { 587 if (num < 0 || num >= size) {
578 obj->initNull(); 588 obj->initNull();
579 return obj; 589 return obj;
580 } 590 }
581 591
582 e = &entries[num]; 592 e = &entries[num];
583 if (e->gen == gen && e->offset >= 0) { 593 if (e->gen == gen && e->offset != 0xffffffff) {
584 obj1.initNull(); 594 obj1.initNull();
585 parser = new Parser(this, new Lexer(this, 595 parser = new Parser(this,
586 str->makeSubStream(start + e->offset, -1, &obj1))); 596 new Lexer(this,
597 str->makeSubStream(start + e->offset, gFalse, 0, &obj1)));
587 parser->getObj(&obj1); 598 parser->getObj(&obj1);
588 parser->getObj(&obj2); 599 parser->getObj(&obj2);
589 parser->getObj(&obj3); 600 parser->getObj(&obj3);
590 if (obj1.isInt() && obj1.getInt() == num && 601 if (obj1.isInt() && obj1.getInt() == num &&
591 obj2.isInt() && obj2.getInt() == gen && 602 obj2.isInt() && obj2.getInt() == gen &&
592 obj3.isCmd("obj")) { 603 obj3.isCmd("obj")) {
@@ -615,18 +626,18 @@ Object *XRef::getDocInfo(Object *obj) {
615 626
616// Added for the pdftex project. 627// Added for the pdftex project.
617Object *XRef::getDocInfoNF(Object *obj) { 628Object *XRef::getDocInfoNF(Object *obj) {
618 return trailerDict.dictLookupNF("Info", obj); 629 return trailerDict.dictLookupNF("Info", obj);
619} 630}
620 631
621int XRef::getStreamEnd(int streamStart) { 632GBool XRef::getStreamEnd(Guint streamStart, Guint *streamEnd) {
622 int a, b, m; 633 int a, b, m;
623 634
624 if (streamEndsLen == 0 || 635 if (streamEndsLen == 0 ||
625 streamStart > streamEnds[streamEndsLen - 1]) { 636 streamStart > streamEnds[streamEndsLen - 1]) {
626 return -1; 637 return gFalse;
627 } 638 }
628 639
629 a = -1; 640 a = -1;
630 b = streamEndsLen - 1; 641 b = streamEndsLen - 1;
631 // invariant: streamEnds[a] < streamStart <= streamEnds[b] 642 // invariant: streamEnds[a] < streamStart <= streamEnds[b]
632 while (b - a > 1) { 643 while (b - a > 1) {
@@ -634,8 +645,21 @@ int XRef::getStreamEnd(int streamStart) {
634 if (streamStart <= streamEnds[m]) { 645 if (streamStart <= streamEnds[m]) {
635 b = m; 646 b = m;
636 } else { 647 } else {
637 a = m; 648 a = m;
638 } 649 }
639 } 650 }
640 return streamEnds[b]; 651 *streamEnd = streamEnds[b];
652 return gTrue;
653}
654
655Guint XRef::strToUnsigned(char *s) {
656 Guint x;
657 char *p;
658 int i;
659
660 x = 0;
661 for (p = s, i = 0; *p && isdigit(*p) && i < 10; ++p, ++i) {
662 x = 10 * x + (*p - '0');
663 }
664 return x;
641} 665}