xref.cc

来自「source code: Covert TXT to PDF」· CC 代码 · 共 668 行 · 第 1/2 页

CC
668
字号
  return more; err1:  obj.free(); err2:  ok = gFalse;  return gFalse;}// Attempt to construct an xref table for a damaged file.GBool XRef::constructXRef() {  Parser *parser;  Object obj;  char buf[256];  Guint pos;  int num, gen;  int newSize;  int streamEndsSize;  char *p;  int i;  GBool gotRoot;  error(0, "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;    // got trailer dictionary    if (!strncmp(p, "trailer", 7)) {      obj.initNull();      parser = new Parser(NULL,		 new Lexer(NULL,		   str->makeSubStream(start + pos + 7, gFalse, 0, &obj)));      if (!trailerDict.isNone())	trailerDict.free();      parser->getObj(&trailerDict);      if (trailerDict.isDict()) {	trailerDict.dictLookupNF("Root", &obj);	if (obj.isRef()) {	  rootNum = obj.getRefNum();	  rootGen = obj.getRefGen();	  gotRoot = gTrue;	}	obj.free();      } else {	pos = 0;      }      delete parser;    // look for object    } else if (isdigit(*p)) {      num = atoi(p);      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;		entries = (XRefEntry *)		            grealloc(entries, newSize * sizeof(XRefEntry));		for (i = size; i < newSize; ++i) {		  entries[i].offset = 0xffffffff;		  entries[i].used = gFalse;		}		size = newSize;	      }	      if (!entries[num].used || gen >= entries[num].gen) {		entries[num].offset = pos - start;		entries[num].gen = gen;		entries[num].used = gTrue;	      }	    }	  }	}      }    } else if (!strncmp(p, "endstream", 9)) {      if (streamEndsLen == streamEndsSize) {	streamEndsSize += 64;	streamEnds = (Guint *)grealloc(streamEnds,				       streamEndsSize * sizeof(int));      }      streamEnds[streamEndsLen++] = pos;    }  }  if (gotRoot)    return gTrue;  error(-1, "Couldn't find trailer dictionary");  return gFalse;}#ifndef NO_DECRYPTIONGBool XRef::checkEncrypted(GString *ownerPassword, GString *userPassword) {  Object encrypt, filterObj, versionObj, revisionObj, lengthObj;  Object ownerKey, userKey, permissions, fileID, fileID1;  GBool encrypted1;  GBool ret;  ret = gFalse;  permFlags = defPermFlags;  ownerPasswordOk = gFalse;  trailerDict.dictLookup("Encrypt", &encrypt);  if ((encrypted1 = encrypt.isDict())) {    ret = gTrue;    encrypt.dictLookup("Filter", &filterObj);    if (filterObj.isName("Standard")) {      encrypt.dictLookup("V", &versionObj);      encrypt.dictLookup("R", &revisionObj);      encrypt.dictLookup("Length", &lengthObj);      encrypt.dictLookup("O", &ownerKey);      encrypt.dictLookup("U", &userKey);      encrypt.dictLookup("P", &permissions);      trailerDict.dictLookup("ID", &fileID);      if (versionObj.isInt() &&	  revisionObj.isInt() &&	  ownerKey.isString() && ownerKey.getString()->getLength() == 32 &&	  userKey.isString() && userKey.getString()->getLength() == 32 &&	  permissions.isInt() &&	  fileID.isArray()) {	encVersion = versionObj.getInt();	encRevision = revisionObj.getInt();	if (lengthObj.isInt()) {	  keyLength = lengthObj.getInt() / 8;	} else {	  keyLength = 5;	}	permFlags = permissions.getInt();	if (encVersion >= 1 && encVersion <= 2 &&	    encRevision >= 2 && encRevision <= 3) {	  fileID.arrayGet(0, &fileID1);	  if (fileID1.isString()) {	    if (Decrypt::makeFileKey(encVersion, encRevision, keyLength,				     ownerKey.getString(), userKey.getString(),				     permFlags, fileID1.getString(),				     ownerPassword, userPassword, fileKey,				     &ownerPasswordOk)) {	      if (ownerPassword && !ownerPasswordOk) {		error(-1, "Incorrect owner password");	      }	      ret = gFalse;	    } else {	      error(-1, "Incorrect password");	    }	  } else {	    error(-1, "Weird encryption info");	  }	  fileID1.free();	} else {	  error(-1, "Unsupported version/revision (%d/%d) of Standard security handler",		encVersion, encRevision);	}      } else {	error(-1, "Weird encryption info");      }      fileID.free();      permissions.free();      userKey.free();      ownerKey.free();      lengthObj.free();      revisionObj.free();      versionObj.free();    } else {      error(-1, "Unknown security handler '%s'",	    filterObj.isName() ? filterObj.getName() : "???");    }    filterObj.free();  }  encrypt.free();  // this flag has to be set *after* we read the O/U/P strings  encrypted = encrypted1;  return ret;}#elseGBool XRef::checkEncrypted(GString *ownerPassword, GString *userPassword) {  Object obj;  GBool encrypted;  trailerDict.dictLookup("Encrypt", &obj);  if ((encrypted = !obj.isNull())) {    error(-1, "PDF file is encrypted and this version of the Xpdf tools");    error(-1, "was built without decryption support.");  }  obj.free();  return encrypted;}#endifGBool XRef::okToPrint(GBool ignoreOwnerPW) {#ifndef NO_DECRYPTION  if ((ignoreOwnerPW || !ownerPasswordOk) && !(permFlags & permPrint)) {    return gFalse;  }#endif  return gTrue;}GBool XRef::okToChange(GBool ignoreOwnerPW) {#ifndef NO_DECRYPTION  if ((ignoreOwnerPW || !ownerPasswordOk) && !(permFlags & permChange)) {    return gFalse;  }#endif  return gTrue;}GBool XRef::okToCopy(GBool ignoreOwnerPW) {#ifndef NO_DECRYPTION  if ((ignoreOwnerPW || !ownerPasswordOk) && !(permFlags & permCopy)) {    return gFalse;  }#endif  return gTrue;}GBool XRef::okToAddNotes(GBool ignoreOwnerPW) {#ifndef NO_DECRYPTION  if ((ignoreOwnerPW || !ownerPasswordOk) && !(permFlags & permNotes)) {    return gFalse;  }#endif  return gTrue;}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) {    obj->initNull();    return obj;  }  e = &entries[num];  if (e->gen == gen && e->offset != 0xffffffff) {    obj1.initNull();    parser = new Parser(this,	       new Lexer(this,		 str->makeSubStream(start + e->offset, gFalse, 0, &obj1)));    parser->getObj(&obj1);    parser->getObj(&obj2);    parser->getObj(&obj3);    if (obj1.isInt() && obj1.getInt() == num &&	obj2.isInt() && obj2.getInt() == gen &&	obj3.isCmd("obj")) {#ifndef NO_DECRYPTION      parser->getObj(obj, encrypted ? fileKey : (Guchar *)NULL, keyLength,		     num, gen);#else      parser->getObj(obj);#endif    } else {      obj->initNull();    }    obj1.free();    obj2.free();    obj3.free();    delete parser;  } else {    obj->initNull();  }  return obj;}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 + =
减小字号Ctrl + -
显示快捷键?