📄 xref.cc
字号:
if (obj.getDict()->lookup("XRefStm", &obj2)->isInt()) { pos2 = (Guint)obj2.getInt(); readXRef(&pos2); if (!ok) { obj2.free(); goto err1; } } obj2.free(); obj.free(); return more; err1: obj.free(); ok = gFalse; return gFalse;}GBool XRef::readXRefStream(Stream *xrefStr, Guint *pos) { Dict *dict; int w[3]; GBool more; Object obj, obj2, idx; int newSize, first, n, i; dict = xrefStr->getDict(); if (!dict->lookupNF("Size", &obj)->isInt()) { goto err1; } newSize = obj.getInt(); obj.free(); if (newSize < 0) { goto err1; } if (newSize > size) { entries = (XRefEntry *)greallocn(entries, newSize, sizeof(XRefEntry)); for (i = size; i < newSize; ++i) { entries[i].offset = 0xffffffff; entries[i].type = xrefEntryFree; } size = newSize; } if (!dict->lookupNF("W", &obj)->isArray() || obj.arrayGetLength() < 3) { goto err1; } for (i = 0; i < 3; ++i) { if (!obj.arrayGet(i, &obj2)->isInt()) { obj2.free(); goto err1; } w[i] = obj2.getInt(); obj2.free(); if (w[i] < 0 || w[i] > 4) { goto err1; } } obj.free(); xrefStr->reset(); dict->lookupNF("Index", &idx); if (idx.isArray()) { for (i = 0; i+1 < idx.arrayGetLength(); i += 2) { if (!idx.arrayGet(i, &obj)->isInt()) { idx.free(); goto err1; } first = obj.getInt(); obj.free(); if (!idx.arrayGet(i+1, &obj)->isInt()) { idx.free(); goto err1; } n = obj.getInt(); obj.free(); if (first < 0 || n < 0 || !readXRefStreamSection(xrefStr, w, first, n)) { idx.free(); goto err0; } } } else { if (!readXRefStreamSection(xrefStr, w, 0, newSize)) { idx.free(); goto err0; } } idx.free(); dict->lookupNF("Prev", &obj); if (obj.isInt()) { *pos = (Guint)obj.getInt(); more = gTrue; } else { more = gFalse; } obj.free(); if (trailerDict.isNone()) { trailerDict.initDict(dict); } return more; err1: obj.free(); err0: ok = gFalse; return gFalse;}GBool XRef::readXRefStreamSection(Stream *xrefStr, int *w, int first, int n) { Guint offset; int type, gen, c, newSize, i, j; if (first + n < 0) { return gFalse; } if (first + n > size) { for (newSize = size ? 2 * size : 1024; first + n > newSize && newSize > 0; newSize <<= 1) ; if (newSize < 0) { return gFalse; } entries = (XRefEntry *)greallocn(entries, newSize, sizeof(XRefEntry)); for (i = size; i < newSize; ++i) { entries[i].offset = 0xffffffff; entries[i].type = xrefEntryFree; } size = newSize; } for (i = first; i < first + n; ++i) { if (w[0] == 0) { type = 1; } else { for (type = 0, j = 0; j < w[0]; ++j) { if ((c = xrefStr->getChar()) == EOF) { return gFalse; } type = (type << 8) + c; } } for (offset = 0, j = 0; j < w[1]; ++j) { if ((c = xrefStr->getChar()) == EOF) { return gFalse; } offset = (offset << 8) + c; } for (gen = 0, j = 0; j < w[2]; ++j) { if ((c = xrefStr->getChar()) == EOF) { return gFalse; } gen = (gen << 8) + c; } if (entries[i].offset == 0xffffffff) { switch (type) { case 0: entries[i].offset = offset; entries[i].gen = gen; entries[i].type = xrefEntryFree; break; case 1: entries[i].offset = offset; entries[i].gen = gen; entries[i].type = xrefEntryUncompressed; break; case 2: entries[i].offset = offset; entries[i].gen = gen; entries[i].type = xrefEntryCompressed; break; default: return gFalse; } } } return gTrue;}// Attempt to construct an xref table for a damaged file.GBool XRef::constructXRef() { Parser *parser; Object newTrailerDict, obj; char buf[256]; Guint pos; int num, gen; int newSize; int streamEndsSize; char *p; int i; GBool gotRoot; gfree(entries); size = 0; entries = NULL; error(-1, "PDF file is damaged - attempting to reconstruct xref table..."); gotRoot = gFalse; streamEndsLen = streamEndsSize = 0; str->reset(); while (1) { pos = str->getPos(); if (!str->getLine(buf, 256)) { break; } p = buf; // skip whitespace while (*p && Lexer::isSpace(*p & 0xff)) ++p; // got trailer dictionary if (!strncmp(p, "trailer", 7)) { obj.initNull(); parser = new Parser(NULL, new Lexer(NULL, str->makeSubStream(pos + 7, gFalse, 0, &obj)), gFalse); parser->getObj(&newTrailerDict); if (newTrailerDict.isDict()) { newTrailerDict.dictLookupNF("Root", &obj); if (obj.isRef()) { rootNum = obj.getRefNum(); rootGen = obj.getRefGen(); if (!trailerDict.isNone()) { trailerDict.free(); } newTrailerDict.copy(&trailerDict); gotRoot = gTrue; } obj.free(); } newTrailerDict.free(); delete parser; // look for object } else if (isdigit(*p)) { num = atoi(p); if (num > 0) { do { ++p; } while (*p && isdigit(*p)); if (isspace(*p)) { do { ++p; } while (*p && isspace(*p)); if (isdigit(*p)) { gen = atoi(p); do { ++p; } while (*p && isdigit(*p)); if (isspace(*p)) { do { ++p; } while (*p && isspace(*p)); if (!strncmp(p, "obj", 3)) { if (num >= size) { newSize = (num + 1 + 255) & ~255; if (newSize < 0) { error(-1, "Bad object number"); return gFalse; } entries = (XRefEntry *) greallocn(entries, newSize, sizeof(XRefEntry)); for (i = size; i < newSize; ++i) { entries[i].offset = 0xffffffff; entries[i].type = xrefEntryFree; } size = newSize; } if (entries[num].type == xrefEntryFree || gen >= entries[num].gen) { entries[num].offset = pos - start; entries[num].gen = gen; entries[num].type = xrefEntryUncompressed; } } } } } } } else if (!strncmp(p, "endstream", 9)) { if (streamEndsLen == streamEndsSize) { streamEndsSize += 64; streamEnds = (Guint *)greallocn(streamEnds, streamEndsSize, sizeof(int)); } streamEnds[streamEndsLen++] = pos; } } if (gotRoot) return gTrue; error(-1, "Couldn't find trailer dictionary"); return gFalse;}void XRef::setEncryption(int permFlagsA, GBool ownerPasswordOkA, Guchar *fileKeyA, int keyLengthA, int encVersionA, CryptAlgorithm encAlgorithmA) { int i; encrypted = gTrue; permFlags = permFlagsA; ownerPasswordOk = ownerPasswordOkA; if (keyLengthA <= 16) { keyLength = keyLengthA; } else { keyLength = 16; } for (i = 0; i < keyLength; ++i) { fileKey[i] = fileKeyA[i]; } encVersion = encVersionA; encAlgorithm = encAlgorithmA;}GBool XRef::okToPrint(GBool ignoreOwnerPW) { return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permPrint);}GBool XRef::okToChange(GBool ignoreOwnerPW) { return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permChange);}GBool XRef::okToCopy(GBool ignoreOwnerPW) { return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permCopy);}GBool XRef::okToAddNotes(GBool ignoreOwnerPW) { return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permNotes);}Object *XRef::fetch(int num, int gen, Object *obj) { XRefEntry *e; Parser *parser; Object obj1, obj2, obj3; // check for bogus ref - this can happen in corrupted PDF files if (num < 0 || num >= size) { goto err; } e = &entries[num]; switch (e->type) { case xrefEntryUncompressed: if (e->gen != gen) { goto err; } obj1.initNull(); parser = new Parser(this, new Lexer(this, str->makeSubStream(start + e->offset, gFalse, 0, &obj1)), gTrue); parser->getObj(&obj1); parser->getObj(&obj2); parser->getObj(&obj3); if (!obj1.isInt() || obj1.getInt() != num || !obj2.isInt() || obj2.getInt() != gen || !obj3.isCmd("obj")) { obj1.free(); obj2.free(); obj3.free(); delete parser; goto err; } parser->getObj(obj, encrypted ? fileKey : (Guchar *)NULL, encAlgorithm, keyLength, num, gen); obj1.free(); obj2.free(); obj3.free(); delete parser; break; case xrefEntryCompressed: if (gen != 0) { goto err; } if (!objStr || objStr->getObjStrNum() != (int)e->offset) { if (objStr) { delete objStr; } objStr = new ObjectStream(this, e->offset); } objStr->getObject(e->gen, num, obj); break; default: goto err; } return obj; err: return obj->initNull();}Object *XRef::getDocInfo(Object *obj) { return trailerDict.dictLookup("Info", obj);}// Added for the pdftex project.Object *XRef::getDocInfoNF(Object *obj) { return trailerDict.dictLookupNF("Info", obj);}GBool XRef::getStreamEnd(Guint streamStart, Guint *streamEnd) { int a, b, m; if (streamEndsLen == 0 || streamStart > streamEnds[streamEndsLen - 1]) { return gFalse; } a = -1; b = streamEndsLen - 1; // invariant: streamEnds[a] < streamStart <= streamEnds[b] while (b - a > 1) { m = (a + b) / 2; if (streamStart <= streamEnds[m]) { b = m; } else { a = m; } } *streamEnd = streamEnds[b]; return gTrue;}Guint XRef::strToUnsigned(char *s) { Guint x; char *p; int i; x = 0; for (p = s, i = 0; *p && isdigit(*p) && i < 10; ++p, ++i) { x = 10 * x + (*p - '0'); } return x;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -