/// <summary> /// Matches and parses the XRefTable in the this instances PDF data stream that is /// specified pased on the position value between the startXRefPos and the end of file marker /// </summary> /// <param name="startxrefPos"></param> /// <param name="eofPos"></param> /// <param name="trailerPrevOffset">The offset marked in the trailer dictionary of any previous XRefTable this file contains.</param> /// <returns></returns> protected PDFXRefTable GetXRefTable(PDFFileRange startxrefPos, PDFFileRange eofPos, long trailerPrevOffset) { long xrefPos = long.Parse(this.Searcher.GetInnerText(startxrefPos, eofPos).Trim()); this.Searcher.Position = xrefPos; string fullXRef = this.Searcher.GetInnerText((int)(eofPos.StartOffset - xrefPos)); int end; PDFXRefTable table = PDFXRefTable.Parse(fullXRef, 0, out end); table.Offset = xrefPos; if (trailerPrevOffset > 0) // we have a previous entry { this.Searcher.Position = trailerPrevOffset; if (startxrefPos.Found) { eofPos = this.Searcher.MatchForwardString(EndOfFileMarker); startxrefPos = AssertFoundRange(this.Searcher.MatchBackwardString(XRefMarker), XRefMarker); PDFFileRange trailerPos = AssertFoundRange(this.Searcher.MatchBackwardString(TrailerMarker), TrailerMarker); PDFDictionary trailer = GetTrailerDictionary(trailerPos, startxrefPos); IFileObject prevEntry; if (trailer.TryGetValue(PrevXRefName, out prevEntry)) { if (prevEntry is PDFNumber) { trailerPrevOffset = ((PDFNumber)prevEntry).Value; } else if (prevEntry is PDFReal) { trailerPrevOffset = (long)((PDFReal)prevEntry).Value; } else { trailerPrevOffset = -1; } } else { trailerPrevOffset = -1; } PDFXRefTable prevTable = GetXRefTable(startxrefPos, eofPos, trailerPrevOffset); table.Previous = prevTable; } } return(table); }
protected static PDFObjectRef AssertGetObjectRef(PDFDictionary dict, PDFName entry, string errorMessage) { IFileObject found; if (!dict.TryGetValue(entry, out found)) { throw new PDFNativeParserException(errorMessage); } if (found.Type != PDFObjectTypes.ObjectRef) { throw new PDFNativeParserException(errorMessage); } return((PDFObjectRef)found); }
/// <summary> /// Initializes the known PDF file data such as trailers, xref tables and catalogs /// </summary> protected override void InitData(PDFTraceLog log) { try { if (log.ShouldLog(TraceLevel.Debug)) { log.Add(TraceLevel.Debug, "PDFReader", "Finding end of file, startxref and trailer positions"); } this.Searcher.Position = this.Searcher.Length; PDFFileRange eofPos = AssertFoundRange(Searcher.MatchBackwardString(EndOfFileMarker), EndOfFileMarker); PDFFileRange startxrefPos = AssertFoundRange(Searcher.MatchBackwardString(StartXRefMarker), StartXRefMarker); PDFFileRange trailerPos = AssertFoundRange(Searcher.MatchBackwardString(TrailerMarker), TrailerMarker); if (log.ShouldLog(TraceLevel.Debug)) { log.Add(TraceLevel.Debug, "PDFReader", "Markers found, loading the trailer dictionary"); } PDFDictionary trailer = GetTrailerDictionary(trailerPos, startxrefPos); this._trailer = trailer; if (log.ShouldLog(TraceLevel.Debug)) { log.Add(TraceLevel.Debug, "PDFReader", "Markers found, loading the XRef table"); } PDFObjectRef catalogRef = AssertGetObjectRef(trailer, CatalogObjName, "The '" + CatalogObjName + "' entry couldnot be found in the documents trailer dictionary"); PDFObjectRef infoRef = AssertGetObjectRef(trailer, InfoObjName, "The '" + InfoObjName + "' entry couldnot be found in the documents trailer dictionary"); IFileObject prevXRefObj; trailer.TryGetValue(PrevXRefName, out prevXRefObj); long prevOffset = -1; if (prevXRefObj is PDFNumber) { prevOffset = ((PDFNumber)prevXRefObj).Value; } else if (prevXRefObj is PDFReal) { prevOffset = (long)((PDFNumber)prevXRefObj).Value; } PDFXRefTable xref = GetXRefTable(startxrefPos, eofPos, prevOffset); if (log.ShouldLog(TraceLevel.Debug)) { log.Add(TraceLevel.Debug, "PDFReader", "References for the catalog and document info found"); } this._xreftable = xref; this._info = (PDFFileIndirectObject)this.GetObject(infoRef); if (log.ShouldLog(TraceLevel.Debug)) { log.Add(TraceLevel.Debug, "PDFReader", "Loaded the document Info indirect object"); } this._catalog = (PDFFileIndirectObject)this.GetObject(catalogRef); if (log.ShouldLog(TraceLevel.Debug)) { log.Add(TraceLevel.Debug, "PDFReader", "Loaded the document Catalog indirect object"); } //TODO: Look for more updates and read those in too } catch (Exception ex) { throw new PDFNativeParserException(CommonErrors.CouldNotInitializeThePDFReader, ex); } }