X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;ds=inline;f=pdf%2Fxpdf%2FCatalog.cc;h=8762cd4cb4d1a908436382fbadfc4d26b5805620;hb=a2f683fe644fded868c536909907282555b1b777;hp=815cca3ae077b01848aae938bd4dc0ed128d05a5;hpb=7aac8dc8533347e21311b15186e0af82f1b22fd6;p=evince.git diff --git a/pdf/xpdf/Catalog.cc b/pdf/xpdf/Catalog.cc index 815cca3a..8762cd4c 100644 --- a/pdf/xpdf/Catalog.cc +++ b/pdf/xpdf/Catalog.cc @@ -2,17 +2,20 @@ // // Catalog.cc // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2003 Glyph & Cog, LLC // //======================================================================== -#ifdef __GNUC__ +#include + +#ifdef USE_GCC_PRAGMAS #pragma implementation #endif #include #include "gmem.h" #include "Object.h" +#include "XRef.h" #include "Array.h" #include "Dict.h" #include "Page.h" @@ -24,24 +27,27 @@ // Catalog //------------------------------------------------------------------------ -Catalog::Catalog(Object *catDict) { - Object pagesDict; +Catalog::Catalog(XRef *xrefA) { + Object catDict, pagesDict; Object obj, obj2; int numPages0; int i; ok = gTrue; + xref = xrefA; pages = NULL; pageRefs = NULL; numPages = pagesSize = 0; + baseURI = NULL; - if (!catDict->isDict()) { - error(-1, "Catalog object is wrong type (%s)", catDict->getTypeName()); + xref->getCatalog(&catDict); + if (!catDict.isDict()) { + error(-1, "Catalog object is wrong type (%s)", catDict.getTypeName()); goto err1; } // read page tree - catDict->dictLookup("Pages", &pagesDict); + catDict.dictLookup("Pages", &pagesDict); // This should really be isDict("Pages"), but I've seen at least one // PDF file where the /Type entry is missing. if (!pagesDict.isDict()) { @@ -50,13 +56,23 @@ Catalog::Catalog(Object *catDict) { goto err2; } pagesDict.dictLookup("Count", &obj); - if (!obj.isInt()) { + // some PDF files actually use real numbers here ("/Count 9.0") + if (!obj.isNum()) { error(-1, "Page count in top-level pages object is wrong type (%s)", obj.getTypeName()); goto err3; } - pagesSize = numPages0 = obj.getInt(); + pagesSize = numPages0 = (int)obj.getNum(); obj.free(); + // The gcc doesnt optimize this away, so this check is ok, + // even if it looks like a pagesSize != pagesSize check + if (pagesSize*sizeof(Page *)/sizeof(Page *) != pagesSize || + pagesSize*sizeof(Ref)/sizeof(Ref) != pagesSize) { + error(-1, "Invalid 'pagesSize'"); + ok = gFalse; + return; + } + pages = (Page **)gmalloc(pagesSize * sizeof(Page *)); pageRefs = (Ref *)gmalloc(pagesSize * sizeof(Ref)); for (i = 0; i < pagesSize; ++i) { @@ -71,18 +87,17 @@ Catalog::Catalog(Object *catDict) { pagesDict.free(); // read named destination dictionary - catDict->dictLookup("Dests", &dests); + catDict.dictLookup("Dests", &dests); // read root of named destination tree - if (catDict->dictLookup("Names", &obj)->isDict()) + if (catDict.dictLookup("Names", &obj)->isDict()) obj.dictLookup("Dests", &nameTree); else nameTree.initNull(); obj.free(); // read base URI - baseURI = NULL; - if (catDict->dictLookup("URI", &obj)->isDict()) { + if (catDict.dictLookup("URI", &obj)->isDict()) { if (obj.dictLookup("Base", &obj2)->isString()) { baseURI = obj2.getString()->copy(); } @@ -90,6 +105,16 @@ Catalog::Catalog(Object *catDict) { } obj.free(); + // get the metadata stream + catDict.dictLookup("Metadata", &metadata); + + // get the structure tree root + catDict.dictLookup("StructTreeRoot", &structTreeRoot); + + // get the outline dictionary + catDict.dictLookup("Outlines", &outline); + + catDict.free(); return; err3: @@ -97,6 +122,7 @@ Catalog::Catalog(Object *catDict) { err2: pagesDict.free(); err1: + catDict.free(); dests.initNull(); nameTree.initNull(); ok = gFalse; @@ -119,6 +145,33 @@ Catalog::~Catalog() { if (baseURI) { delete baseURI; } + metadata.free(); + structTreeRoot.free(); + outline.free(); +} + +GString *Catalog::readMetadata() { + GString *s; + Dict *dict; + Object obj; + int c; + + if (!metadata.isStream()) { + return NULL; + } + dict = metadata.streamGetDict(); + if (!dict->lookup("Subtype", &obj)->isName("XML")) { + error(-1, "Unknown Metadata type: '%s'", + obj.isName() ? obj.getName() : "???"); + } + obj.free(); + s = new GString(); + metadata.streamReset(); + while ((c = metadata.streamGetChar()) != EOF) { + s->append(c); + } + metadata.streamClose(); + return s; } int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start) { @@ -140,13 +193,18 @@ int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start) { kids.arrayGet(i, &kid); if (kid.isDict("Page")) { attrs2 = new PageAttrs(attrs1, kid.getDict()); - page = new Page(start+1, kid.getDict(), attrs2); + page = new Page(xref, start+1, kid.getDict(), attrs2); if (!page->isOk()) { ++start; goto err3; } if (start >= pagesSize) { pagesSize += 32; + if (pagesSize*sizeof(Page *)/sizeof(Page *) != pagesSize || + pagesSize*sizeof(Ref)/sizeof(Ref) != pagesSize) { + error(-1, "Invalid 'pagesSize' parameter."); + goto err3; + } pages = (Page **)grealloc(pages, pagesSize * sizeof(Page *)); pageRefs = (Ref *)grealloc(pageRefs, pagesSize * sizeof(Ref)); for (j = pagesSize - 32; j < pagesSize; ++j) { @@ -166,7 +224,8 @@ int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start) { // This should really be isDict("Pages"), but I've seen at least one // PDF file where the /Type entry is missing. } else if (kid.isDict()) { - if ((start = readPageTree(kid.getDict(), attrs1, start)) < 0) + if ((start = readPageTree(kid.getDict(), attrs1, start)) + < 0) goto err2; } else { error(-1, "Kid object (page %d) is wrong type (%s)", @@ -225,10 +284,10 @@ LinkDest *Catalog::findDest(GString *name) { // construct LinkDest dest = NULL; if (obj1.isArray()) { - dest = new LinkDest(obj1.getArray(), gTrue); + dest = new LinkDest(obj1.getArray()); } else if (obj1.isDict()) { if (obj1.dictLookup("D", &obj2)->isArray()) - dest = new LinkDest(obj2.getArray(), gTrue); + dest = new LinkDest(obj2.getArray()); else error(-1, "Bad named destination value"); obj2.free(); @@ -236,6 +295,10 @@ LinkDest *Catalog::findDest(GString *name) { error(-1, "Bad named destination value"); } obj1.free(); + if (dest && !dest->isOk()) { + delete dest; + dest = NULL; + } return dest; } @@ -259,8 +322,8 @@ Object *Catalog::findDestInTree(Object *tree, GString *name, Object *obj) { } else if (cmp < 0) { done = gTrue; } - name1.free(); } + name1.free(); } names.free(); if (!found)