/// <summary> /// /// </summary> PdfTrailer ReadXRefTableAndTrailer(PdfReferenceTable xrefTable) { Debug.Assert(xrefTable != null); Symbol symbol = ScanNextToken(); // Is it an xref stream? if (symbol == Symbol.Integer) { throw new PdfReaderException(PSSR.CannotHandleXRefStreams); } // TODO: It is very high on the todo list, but still undone Debug.Assert(symbol == Symbol.XRef); while (true) { symbol = ScanNextToken(); if (symbol == Symbol.Integer) { int start = this.lexer.TokenToInteger; int length = ReadInteger(); for (int id = start; id < start + length; id++) { int position = ReadInteger(); int generation = ReadInteger(); ReadSymbol(Symbol.Keyword); string token = lexer.Token; // Skip start entry if (id == 0) { continue; } // Skip unused entries. if (token != "n") { continue; } // Even it is restricted, an object can exists in more than one subsection. // (PDF Reference Implementation Notes 15). PdfObjectID objectID = new PdfObjectID(id, generation); // Ignore the latter one if (xrefTable.Contains(objectID)) { continue; } xrefTable.Add(new PdfReference(objectID, position)); } } else if (symbol == Symbol.Trailer) { ReadSymbol(Symbol.BeginDictionary); PdfTrailer trailer = new PdfTrailer(this.document); this.ReadDictionary(trailer, false); return(trailer); } else { throw new PdfReaderException(PSSR.UnexpectedToken(this.lexer.Token)); } } }
public string Build() { PdfMetadata = ValueOrDefault(PdfMetadata, PdfMetadataDefaultValue); AddMetadata(PdfMetadata); StringBuilder sb = new StringBuilder(); sb.Append($"%PDF-{Version}\n"); sb.Append(BinaryComment()); foreach (PdfObject pdfObject in PdfObjects) { sb.Append(pdfObject.Build()); } var pdfFileUpUntilXref = sb.ToString(); // Temp pdf so that we can calculate position to Reference table var xref = new PdfReferenceTable(pdfFileUpUntilXref, PdfObjects); var xrefPosition = PdfHelpers.Encoding.GetByteCount(pdfFileUpUntilXref); sb.Append($"{xref.ToString()}"); var trailer = new PdfTrailer(this.Catalog, PdfObjects.Count + 1, PdfMetadata); sb.Append(trailer.Build()); // Tells pdf where to find xref table sb.Append("startxref\n"); sb.Append($"{xrefPosition}\n"); sb.Append("%%EOF"); return(sb.ToString()); }
public void Setup() { _reader = new Mock <IPdfReader>(); _editor = new Mock <IPdfEditor>(); _data = new byte[] { 0, 1, 2, 3, 4, 5 }; _rootRef = new Mock <PdfIndirectReference>(); _infoRef = new Mock <PdfIndirectReference>(); _root = new Mock <PdfDictionary>(); _info = new Mock <PdfDictionary>(); _trailer = new PdfTrailer { TrailerDictionary = new Dictionary <PdfName, PdfObject> { { "Root", _rootRef.Object }, { "Info", _infoRef.Object } } }; _reader.Setup(x => x.ReadVersion()).Returns(1.4M); _reader.Setup(x => x.ReadTrailer()).Returns(_trailer); _reader.Setup(x => x.ReadObject(_rootRef.Object)).Returns(_root.Object); _reader.Setup(x => x.ReadObject(_infoRef.Object)).Returns(_info.Object); _inMemoryPdf = new InMemoryPdf(_data, _reader.Object, _editor.Object); }
void Initialize() { //this.info = new PdfInfo(this); fontTable = new PdfFontTable(this); imageTable = new PdfImageTable(this); trailer = new PdfTrailer(this); irefTable = new PdfReferenceTable(this); trailer.CreateNewDocumentIDs(); }
void Initialize() { //_info = new PdfInfo(this); _fontTable = new PdfFontTable(this); _imageTable = new PdfImageTable(this); _trailer = new PdfTrailer(this); _irefTable = new PdfCrossReferenceTable(this); _trailer.CreateNewDocumentIDs(); }
/** Does the actual document manipulation to encrypt it. * @throws DocumentException on error * @throws IOException on error */ protected void go() { body = new PdfBody(HEADER.Length, this, true); os.Write(HEADER, 0, HEADER.Length); PdfObject[] xb = reader.xrefObj; myXref = new int[xb.Length]; int idx = 1; for (int k = 1; k < xb.Length; ++k) { if (xb[k] != null) { myXref[k] = idx++; } } file.reOpen(); for (int k = 1; k < xb.Length; ++k) { if (xb[k] != null) { addToBody(xb[k]); } } file.close(); PdfIndirectReference encryption = null; PdfLiteral fileID = null; if (crypto != null) { PdfIndirectObject encryptionObject = body.Add(crypto.EncryptionDictionary); encryptionObject.writeTo(os); encryption = encryptionObject.IndirectReference; fileID = crypto.FileID; } // write the cross-reference table of the body os.Write(body.CrossReferenceTable, 0, body.CrossReferenceTable.Length); PRIndirectReference iRoot = (PRIndirectReference)reader.trailer.get(PdfName.ROOT); PdfIndirectReference root = new PdfIndirectReference(0, myXref[iRoot.Number]); PRIndirectReference iInfo = (PRIndirectReference)reader.trailer.get(PdfName.INFO); PdfIndirectReference info = null; if (iInfo != null) { info = new PdfIndirectReference(0, myXref[iInfo.Number]); } PdfTrailer trailer = new PdfTrailer(body.Size, body.Offset, root, info, encryption, fileID); byte[] tmp = trailer.toPdf(this); os.Write(tmp, 0, tmp.Length); os.Close(); }
public void Info() { var indirectReference = new Mock <PdfIndirectReference>(); var trailerDictionary = (PdfDictionary) new Dictionary <PdfName, PdfObject> { { "Info", indirectReference.Object } }; var trailer = new PdfTrailer { TrailerDictionary = trailerDictionary }; var result = trailer.Info; Assert.AreEqual(indirectReference.Object, result); }
public void ConvertToString() { var trailerDictionary = new Mock <PdfDictionary>(); var trailer = new PdfTrailer { CrossReferenceTableOffset = 100, TrailerDictionary = trailerDictionary.Object }; trailerDictionary.Setup(x => x.ToString()).Returns("trailerdictionary"); var result = trailer.ToString(); Assert.AreEqual("trailer\ntrailerdictionary\nstartxref\n100", result); }
/// <summary> /// Writes PDF document trailer into file stream /// </summary> /// <param name="trailer">PDF document trailer</param> internal void Write(PdfTrailer trailer) { writeLineRaw("xref"); writeLineRaw("0 {0}", trailer.LastObjectId + 1); writeLineRaw("0000000000 65535 f"); foreach (var offset in trailer.ObjectOffsets) { writeLineRaw("{0} 00000 n", offset); } writeLineRaw("trailer"); writeBeginDictionary(); writeDictionaryEntry("/Size", trailer.LastObjectId + 1); writeDictionaryEntry("/Root", trailer.Root.GetReference()); writeDictionaryEntry("/Info", trailer.Root.Info.GetReference()); writeEndDictionary(); writeLineRaw("startxref"); writeLineRaw("{0}", trailer.XRefOffset); writeRaw(Encoding.ASCII.GetBytes("%%EOF")); }
public void Setup() { _document = new Mock <IEditablePdfDocument>(); _trailer = new PdfTrailer { CrossReferenceTableOffset = 10, TrailerDictionary = new PdfDictionary() }; _crossReferenceTable = new PdfCrossReferenceTable { ObjectOffsets = new Dictionary <int, int>(), Offset = 10 }; _document.SetupGet(x => x.CrossReferenceTable).Returns(_crossReferenceTable); _document.SetupGet(x => x.Encoding).Returns(Encoding.UTF8); _document.SetupGet(x => x.Trailer).Returns(_trailer); _pdfEditor = new PdfEditor(_document.Object); }
/// <summary> /// Write the document to a stream. /// </summary> /// <param name="stream">The stream to write to.</param> /// <returns>The number of bytes written.</returns> public int WriteTo(Stream stream) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } int written = PdfHeader.Value.WriteTo(stream); foreach (IPdfIndirectObject indirectObject in _bodyObjects) { _xrefTable.SetSlot(indirectObject, written); written += indirectObject.WriteTo(stream); } PdfTrailer trailer = new PdfTrailer(_root, _xrefTable); trailer.SetCrossReferenceTableLocation(written); written += _xrefTable.WriteTo(stream); written += trailer.WriteTo(stream); return(written); }
/** * Signals that the <CODE>Document</CODE> was closed and that no other * <CODE>Elements</CODE> will be added. * <P> * The pages-tree is built and written to the outputstream. * A Catalog is constructed, as well as an Info-object, * the referencetable is composed and everything is written * to the outputstream embedded in a Trailer. */ public override void Close() { if (open) { if ((currentPageNumber - 1) != pageReferences.Count) throw new Exception("The page " + pageReferences.Count + " was requested but the document has only " + (currentPageNumber - 1) + " pages."); pdf.Close(); AddSharedObjectsToBody(); foreach (IPdfOCG layer in documentOCG.Keys) { AddToBody(layer.PdfObject, layer.Ref); } // add the root to the body PdfIndirectReference rootRef = root.WritePageTree(); // make the catalog-object and add it to the body PdfDictionary catalog = GetCatalog(rootRef); // [C9] if there is XMP data to add: add it if (xmpMetadata != null) { PdfStream xmp = new PdfStream(xmpMetadata); xmp.Put(PdfName.TYPE, PdfName.METADATA); xmp.Put(PdfName.SUBTYPE, PdfName.XML); if (crypto != null && !crypto.IsMetadataEncrypted()) { PdfArray ar = new PdfArray(); ar.Add(PdfName.CRYPT); xmp.Put(PdfName.FILTER, ar); } catalog.Put(PdfName.METADATA, body.Add(xmp).IndirectReference); } // [C10] make pdfx conformant if (IsPdfX()) { CompleteInfoDictionary(Info); CompleteExtraCatalog(ExtraCatalog); } // [C11] Output Intents if (extraCatalog != null) { catalog.MergeDifferent(extraCatalog); } WriteOutlines(catalog, false); // add the Catalog to the body PdfIndirectObject indirectCatalog = AddToBody(catalog, false); // add the info-object to the body PdfIndirectObject infoObj = AddToBody(Info, false); // [F1] encryption PdfIndirectReference encryption = null; PdfObject fileID = null; body.FlushObjStm(); if (crypto != null) { PdfIndirectObject encryptionObject = AddToBody(crypto.GetEncryptionDictionary(), false); encryption = encryptionObject.IndirectReference; fileID = crypto.FileID; } else fileID = PdfEncryption.CreateInfoId(PdfEncryption.CreateDocumentId()); // write the cross-reference table of the body body.WriteCrossReferenceTable(os, indirectCatalog.IndirectReference, infoObj.IndirectReference, encryption, fileID, prevxref); // make the trailer // [F2] full compression if (fullCompression) { WriteKeyInfo(os); byte[] tmp = GetISOBytes("startxref\n"); os.Write(tmp, 0, tmp.Length); tmp = GetISOBytes(body.Offset.ToString()); os.Write(tmp, 0, tmp.Length); tmp = GetISOBytes("\n%%EOF\n"); os.Write(tmp, 0, tmp.Length); } else { PdfTrailer trailer = new PdfTrailer(body.Size, body.Offset, indirectCatalog.IndirectReference, infoObj.IndirectReference, encryption, fileID, prevxref); trailer.ToPdf(this, os); } base.Close(); } }
protected virtual void Close(PdfIndirectReference info, int skipInfo) { AlterContents(); int rootN = ((PRIndirectReference)reader.trailer.Get(PdfName.ROOT)).Number; if (append) { int[] keys = marked.GetKeys(); for (int k = 0; k < keys.Length; ++k) { int j = keys[k]; PdfObject obj = reader.GetPdfObjectRelease(j); if (obj != null && skipInfo != j && j < initialXrefSize) { AddToBody(obj, obj.IndRef, j != rootN); } } for (int k = initialXrefSize; k < reader.XrefSize; ++k) { PdfObject obj = reader.GetPdfObject(k); if (obj != null) { AddToBody(obj, GetNewObjectNumber(reader, k, 0)); } } } else { for (int k = 1; k < reader.XrefSize; ++k) { PdfObject obj = reader.GetPdfObjectRelease(k); if (obj != null && skipInfo != k) { AddToBody(obj, GetNewObjectNumber(reader, k, 0), k != rootN); } } } PdfIndirectReference encryption = null; PdfObject fileID = null; if (crypto != null) { if (append) { encryption = reader.GetCryptoRef(); } else { PdfIndirectObject encryptionObject = AddToBody(crypto.GetEncryptionDictionary(), false); encryption = encryptionObject.IndirectReference; } fileID = crypto.GetFileID(true); } else { PdfArray IDs = reader.trailer.GetAsArray(PdfName.ID); if(IDs != null && IDs.GetAsString(0) != null) { fileID = PdfEncryption.CreateInfoId(IDs.GetAsString(0).GetBytes(), true); } else { fileID = PdfEncryption.CreateInfoId(PdfEncryption.CreateDocumentId(), true); } } PRIndirectReference iRoot = (PRIndirectReference)reader.trailer.Get(PdfName.ROOT); PdfIndirectReference root = new PdfIndirectReference(0, GetNewObjectNumber(reader, iRoot.Number, 0)); // write the cross-reference table of the body body.WriteCrossReferenceTable(os, root, info, encryption, fileID, prevxref); if (fullCompression) { WriteKeyInfo(os); byte[] tmp = GetISOBytes("startxref\n"); os.Write(tmp, 0, tmp.Length); tmp = GetISOBytes(body.Offset.ToString()); os.Write(tmp, 0, tmp.Length); tmp = GetISOBytes("\n%%EOF\n"); os.Write(tmp, 0, tmp.Length); } else { PdfTrailer trailer = new PdfTrailer(body.Size, body.Offset, root, info, encryption, fileID, prevxref); trailer.ToPdf(this, os); } os.Flush(); if (CloseStream) os.Close(); GetCounter().Written(os.Counter); }
void Initialize() { _trailer = new PdfTrailer(this); _irefTable = new PdfCrossReferenceTable(this); _trailer.CreateNewDocumentIDs(); }
internal void Close(Hashtable moreInfo) { if (closed) return; if (useVp) { reader.SetViewerPreferences(viewerPreferences); MarkUsed(reader.Trailer.Get(PdfName.ROOT)); } if (flat) FlatFields(); if (flatFreeText) FlatFreeTextFields(); AddFieldResources(); PdfDictionary acroForm = (PdfDictionary)PdfReader.GetPdfObject(reader.Catalog.Get(PdfName.ACROFORM), reader.Catalog); if (acroFields != null && acroFields.Xfa.Changed) { MarkUsed(acroForm); if (!flat) acroFields.Xfa.SetXfa(this); } if (sigFlags != 0) { if (acroForm != null) { acroForm.Put(PdfName.SIGFLAGS, new PdfNumber(sigFlags)); MarkUsed(acroForm); } } closed = true; AddSharedObjectsToBody(); SetOutlines(); SetJavaScript(); AddFileAttachments(); PdfDictionary catalog = reader.Catalog; if (openAction != null) { catalog.Put(PdfName.OPENACTION, openAction); } byte[] altMetadata = xmpMetadata; if (altMetadata == null) { PdfObject xmpo = PdfReader.GetPdfObject(catalog.Get(PdfName.METADATA)); if (xmpo != null && xmpo.IsStream()) { altMetadata = PdfReader.GetStreamBytesRaw((PRStream)xmpo); PdfReader.KillIndirect(xmpo); } } // if there is XMP data to add: add it if (altMetadata != null) { PdfStream xmp = new PdfStream(altMetadata); xmp.Put(PdfName.TYPE, PdfName.METADATA); xmp.Put(PdfName.SUBTYPE, PdfName.XML); if (crypto != null && !crypto.IsMetadataEncrypted()) { PdfArray ar = new PdfArray(); ar.Add(PdfName.CRYPT); xmp.Put(PdfName.FILTER, ar); } catalog.Put(PdfName.METADATA, body.Add(xmp).IndirectReference); MarkUsed(catalog); } PRIndirectReference iInfo = null; try { file.ReOpen(); AlterContents(); iInfo = (PRIndirectReference)reader.trailer.Get(PdfName.INFO); int skip = -1; if (iInfo != null) skip = iInfo.Number; int rootN = ((PRIndirectReference)reader.trailer.Get(PdfName.ROOT)).Number; if (append) { int[] keys = marked.GetKeys(); for (int k = 0; k < keys.Length; ++k) { int j = keys[k]; PdfObject obj = reader.GetPdfObjectRelease(j); if (obj != null && skip != j && j < initialXrefSize) { AddToBody(obj, j, j != rootN); } } for (int k = initialXrefSize; k < reader.XrefSize; ++k) { PdfObject obj = reader.GetPdfObject(k); if (obj != null) { AddToBody(obj, GetNewObjectNumber(reader, k, 0)); } } } else { for (int k = 1; k < reader.XrefSize; ++k) { PdfObject obj = reader.GetPdfObjectRelease(k); if (obj != null && skip != k) { AddToBody(obj, GetNewObjectNumber(reader, k, 0), k != rootN); } } } } finally { try { file.Close(); } catch { // empty on purpose } } PdfIndirectReference encryption = null; PdfObject fileID = null; if (crypto != null) { if (append) { encryption = reader.GetCryptoRef(); } else { PdfIndirectObject encryptionObject = AddToBody(crypto.GetEncryptionDictionary(), false); encryption = encryptionObject.IndirectReference; } fileID = crypto.FileID; } PRIndirectReference iRoot = (PRIndirectReference)reader.trailer.Get(PdfName.ROOT); PdfIndirectReference root = new PdfIndirectReference(0, GetNewObjectNumber(reader, iRoot.Number, 0)); PdfIndirectReference info = null; PdfDictionary oldInfo = (PdfDictionary)PdfReader.GetPdfObject(iInfo); PdfDictionary newInfo = new PdfDictionary(); if (oldInfo != null) { foreach (PdfName key in oldInfo.Keys) { PdfObject value = PdfReader.GetPdfObject(oldInfo.Get(key)); newInfo.Put(key, value); } } if (moreInfo != null) { foreach (DictionaryEntry entry in moreInfo) { PdfName keyName = new PdfName((String)entry.Key); String value = (String)entry.Value; if (value == null) newInfo.Remove(keyName); else newInfo.Put(keyName, new PdfString(value, PdfObject.TEXT_UNICODE)); } } if (append) { if (iInfo == null) info = AddToBody(newInfo, false).IndirectReference; else info = AddToBody(newInfo, iInfo.Number, false).IndirectReference; } else { if (newInfo.Size != 0) info = AddToBody(newInfo, false).IndirectReference; } // write the cross-reference table of the body body.WriteCrossReferenceTable(os, root, info, encryption, fileID, prevxref); if (fullCompression) { byte[] tmp = GetISOBytes("startxref\n"); os.Write(tmp, 0, tmp.Length); tmp = GetISOBytes(body.Offset.ToString()); os.Write(tmp, 0, tmp.Length); tmp = GetISOBytes("\n%%EOF\n"); os.Write(tmp, 0, tmp.Length); } else { PdfTrailer trailer = new PdfTrailer(body.Size, body.Offset, root, info, encryption, fileID, prevxref); trailer.ToPdf(this, os); } os.Flush(); if (CloseStream) os.Close(); reader.Close(); }
/// <summary> /// Implements saving a PDF file. /// </summary> void DoSave(PdfWriter writer) { if (_pages == null || _pages.Count == 0) { if (_outStream != null) { // Give feedback if the wrong constructor was used. throw new InvalidOperationException("Cannot save a PDF document with no pages. Do not use \"public PdfDocument(string filename)\" or \"public PdfDocument(Stream outputStream)\" if you want to open an existing PDF document from a file or stream; use PdfReader.Open() for that purpose."); } throw new InvalidOperationException("Cannot save a PDF document with no pages."); } try { // HACK: Remove XRefTrailer if (_trailer is PdfCrossReferenceStream) { // HACK^2: Preserve the SecurityHandler. PdfStandardSecurityHandler securityHandler = _securitySettings.SecurityHandler; _trailer = new PdfTrailer((PdfCrossReferenceStream)_trailer); _trailer._securityHandler = securityHandler; } bool encrypt = _securitySettings.DocumentSecurityLevel != PdfDocumentSecurityLevel.None; if (encrypt) { PdfStandardSecurityHandler securityHandler = _securitySettings.SecurityHandler; if (securityHandler.Reference == null) { _irefTable.Add(securityHandler); } else { Debug.Assert(_irefTable.Contains(securityHandler.ObjectID)); } _trailer.Elements[PdfTrailer.Keys.Encrypt] = _securitySettings.SecurityHandler.Reference; } else { _trailer.Elements.Remove(PdfTrailer.Keys.Encrypt); } PrepareForSave(); if (encrypt) { _securitySettings.SecurityHandler.PrepareEncryption(); } writer.WriteFileHeader(this); PdfReference[] irefs = _irefTable.AllReferences; int count = irefs.Length; for (int idx = 0; idx < count; idx++) { PdfReference iref = irefs[idx]; #if DEBUG_ if (iref.ObjectNumber == 378) { GetType(); } #endif iref.Position = writer.Position; iref.Value.WriteObject(writer); } var startxref = writer.Position; _irefTable.WriteObject(writer); writer.WriteRaw("trailer\n"); _trailer.Elements.SetInteger("/Size", count + 1); _trailer.WriteObject(writer); writer.WriteEof(this, startxref); //if (encrypt) //{ // state &= ~DocumentState.SavingEncrypted; // //_securitySettings.SecurityHandler.EncryptDocument(); //} } finally { if (writer != null) { writer.Stream.Flush(); // DO NOT CLOSE WRITER HERE //writer.Close(); } } }
internal void WriteTrailer(UnderlyingPdf document, SerializationResult sRes) { var trailer = new PdfTrailer(sRes.References[document.Root], sRes.Offsets.Count); this.iSer.SerializeTrailer(this, trailer); }
internal void Close(IDictionary<String, String> moreInfo) { if (closed) return; if (useVp) { reader.SetViewerPreferences(viewerPreferences); MarkUsed(reader.Trailer.Get(PdfName.ROOT)); } if (flat) FlatFields(); if (flatFreeText) FlatFreeTextFields(); AddFieldResources(); PdfDictionary catalog = reader.Catalog; PdfDictionary pages = (PdfDictionary)PdfReader.GetPdfObject(catalog.Get(PdfName.PAGES)); pages.Put(PdfName.ITXT, new PdfString(Document.Release)); MarkUsed(pages); PdfDictionary acroForm = (PdfDictionary)PdfReader.GetPdfObject(catalog.Get(PdfName.ACROFORM), reader.Catalog); if (acroFields != null && acroFields.Xfa.Changed) { MarkUsed(acroForm); if (!flat) acroFields.Xfa.SetXfa(this); } if (sigFlags != 0) { if (acroForm != null) { acroForm.Put(PdfName.SIGFLAGS, new PdfNumber(sigFlags)); MarkUsed(acroForm); MarkUsed(catalog); } } closed = true; AddSharedObjectsToBody(); SetOutlines(); SetJavaScript(); AddFileAttachments(); if (openAction != null) { catalog.Put(PdfName.OPENACTION, openAction); } if (pdf.pageLabels != null) catalog.Put(PdfName.PAGELABELS, pdf.pageLabels.GetDictionary(this)); // OCG if (documentOCG.Count > 0) { FillOCProperties(false); PdfDictionary ocdict = catalog.GetAsDict(PdfName.OCPROPERTIES); if (ocdict == null) { reader.Catalog.Put(PdfName.OCPROPERTIES, OCProperties); } else { ocdict.Put(PdfName.OCGS, OCProperties.Get(PdfName.OCGS)); PdfDictionary ddict = ocdict.GetAsDict(PdfName.D); if (ddict == null) { ddict = new PdfDictionary(); ocdict.Put(PdfName.D, ddict); } ddict.Put(PdfName.ORDER, OCProperties.GetAsDict(PdfName.D).Get(PdfName.ORDER)); ddict.Put(PdfName.RBGROUPS, OCProperties.GetAsDict(PdfName.D).Get(PdfName.RBGROUPS)); ddict.Put(PdfName.OFF, OCProperties.GetAsDict(PdfName.D).Get(PdfName.OFF)); ddict.Put(PdfName.AS, OCProperties.GetAsDict(PdfName.D).Get(PdfName.AS)); } } // metadata int skipInfo = -1; PdfObject oInfo = reader.Trailer.Get(PdfName.INFO); PRIndirectReference iInfo = null; PdfDictionary oldInfo = null; if (oInfo is PRIndirectReference) iInfo = (PRIndirectReference)oInfo; if (iInfo != null) oldInfo = (PdfDictionary)PdfReader.GetPdfObject(iInfo); else if (oInfo is PdfDictionary) oldInfo = (PdfDictionary)oInfo; String producer = null; if (iInfo != null) skipInfo = iInfo.Number; if (oldInfo != null && oldInfo.Get(PdfName.PRODUCER) != null) producer = oldInfo.GetAsString(PdfName.PRODUCER).ToUnicodeString(); if (producer == null) { producer = Document.Version; } else if (producer.IndexOf(Document.Product) == -1) { StringBuilder buf = new StringBuilder(producer); buf.Append("; modified using "); buf.Append(Document.Version); producer = buf.ToString(); } PdfIndirectReference info = null; PdfDictionary newInfo = new PdfDictionary(); if (oldInfo != null) { foreach (PdfName key in oldInfo.Keys) { PdfObject value = PdfReader.GetPdfObject(oldInfo.Get(key)); newInfo.Put(key, value); } } if (moreInfo != null) { foreach (KeyValuePair<string,string> entry in moreInfo) { PdfName keyName = new PdfName(entry.Key); String value = entry.Value; if (value == null) newInfo.Remove(keyName); else newInfo.Put(keyName, new PdfString(value, PdfObject.TEXT_UNICODE)); } } PdfDate date = new PdfDate(); newInfo.Put(PdfName.MODDATE, date); newInfo.Put(PdfName.PRODUCER, new PdfString(producer, PdfObject.TEXT_UNICODE)); if (append) { if (iInfo == null) info = AddToBody(newInfo, false).IndirectReference; else info = AddToBody(newInfo, iInfo.Number, false).IndirectReference; } else { info = AddToBody(newInfo, false).IndirectReference; } // XMP byte[] altMetadata = null; PdfObject xmpo = PdfReader.GetPdfObject(catalog.Get(PdfName.METADATA)); if (xmpo != null && xmpo.IsStream()) { altMetadata = PdfReader.GetStreamBytesRaw((PRStream)xmpo); PdfReader.KillIndirect(catalog.Get(PdfName.METADATA)); } if (xmpMetadata != null) { altMetadata = xmpMetadata; } if (altMetadata != null) { PdfStream xmp; try { XmpReader xmpr; if (moreInfo == null) { xmpr = new XmpReader(altMetadata); if (!(xmpr.ReplaceNode("http://ns.adobe.com/pdf/1.3/", "Producer", producer) || xmpr.ReplaceDescriptionAttribute("http://ns.adobe.com/pdf/1.3/", "Producer", producer))) xmpr.Add("rdf:Description", "http://ns.adobe.com/pdf/1.3/", "Producer", producer); if (!(xmpr.ReplaceNode("http://ns.adobe.com/xap/1.0/", "ModifyDate", date.GetW3CDate()) || xmpr.ReplaceDescriptionAttribute("http://ns.adobe.com/xap/1.0/", "ModifyDate", date.GetW3CDate()))) xmpr.Add("rdf:Description", "http://ns.adobe.com/xap/1.0/", "ModifyDate", date.GetW3CDate()); if (!(xmpr.ReplaceNode("http://ns.adobe.com/xap/1.0/", "MetadataDate", date.GetW3CDate()) || xmpr.ReplaceDescriptionAttribute("http://ns.adobe.com/xap/1.0/", "MetadataDate", date.GetW3CDate()))) { } } else { MemoryStream baos = new MemoryStream(); try { XmpWriter xmpw = new XmpWriter(baos, newInfo, PDFXConformance); xmpw.Close(); } catch (IOException) { } xmpr = new XmpReader(baos.ToArray()); } xmp = new PdfStream(xmpr.SerializeDoc()); } catch { xmp = new PdfStream(altMetadata); } xmp.Put(PdfName.TYPE, PdfName.METADATA); xmp.Put(PdfName.SUBTYPE, PdfName.XML); if (crypto != null && !crypto.IsMetadataEncrypted()) { PdfArray ar = new PdfArray(); ar.Add(PdfName.CRYPT); xmp.Put(PdfName.FILTER, ar); } if (append && xmpo != null) { body.Add(xmp, xmpo.IndRef); } else { catalog.Put(PdfName.METADATA, body.Add(xmp).IndirectReference); MarkUsed(catalog); } } try { file.ReOpen(); AlterContents(); int rootN = ((PRIndirectReference)reader.trailer.Get(PdfName.ROOT)).Number; if (append) { int[] keys = marked.GetKeys(); for (int k = 0; k < keys.Length; ++k) { int j = keys[k]; PdfObject obj = reader.GetPdfObjectRelease(j); if (obj != null && skipInfo != j && j < initialXrefSize) { AddToBody(obj, j, j != rootN); } } for (int k = initialXrefSize; k < reader.XrefSize; ++k) { PdfObject obj = reader.GetPdfObject(k); if (obj != null) { AddToBody(obj, GetNewObjectNumber(reader, k, 0)); } } } else { for (int k = 1; k < reader.XrefSize; ++k) { PdfObject obj = reader.GetPdfObjectRelease(k); if (obj != null && skipInfo != k) { AddToBody(obj, GetNewObjectNumber(reader, k, 0), k != rootN); } } } } finally { try { file.Close(); } catch { // empty on purpose } } PdfIndirectReference encryption = null; PdfObject fileID = null; if (crypto != null) { if (append) { encryption = reader.GetCryptoRef(); } else { PdfIndirectObject encryptionObject = AddToBody(crypto.GetEncryptionDictionary(), false); encryption = encryptionObject.IndirectReference; } fileID = crypto.FileID; } else fileID = PdfEncryption.CreateInfoId(PdfEncryption.CreateDocumentId()); PRIndirectReference iRoot = (PRIndirectReference)reader.trailer.Get(PdfName.ROOT); PdfIndirectReference root = new PdfIndirectReference(0, GetNewObjectNumber(reader, iRoot.Number, 0)); // write the cross-reference table of the body body.WriteCrossReferenceTable(os, root, info, encryption, fileID, prevxref); if (fullCompression) { byte[] tmp = GetISOBytes("startxref\n"); os.Write(tmp, 0, tmp.Length); tmp = GetISOBytes(body.Offset.ToString()); os.Write(tmp, 0, tmp.Length); tmp = GetISOBytes("\n%%EOF\n"); os.Write(tmp, 0, tmp.Length); } else { PdfTrailer trailer = new PdfTrailer(body.Size, body.Offset, root, info, encryption, fileID, prevxref); trailer.ToPdf(this, os); } os.Flush(); if (CloseStream) os.Close(); reader.Close(); }
/// <summary> /// Creates a new instance of the PdfDocument class from the IO stream. /// </summary> /// <param name="stream">The <see cref="Stream"/> on which to open the PdfDocument.</param> /// <returns></returns> public static PdfDocument Open(Stream stream) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } if (!stream.CanRead) { throw new ArgumentException("Cannot read stream", nameof(stream)); } var document = new PdfDocument(stream); using (var reader = new PdfReader(stream)) { // Check header document.pdfVersion = PdfVersion.FromReader(reader); // Check trailer reader.Position = reader.GetXRefPosition(); // Read Cross-Reference Table IPdfTrailer trailer; IXRefSection xrefSection; char fisrtChar; do { fisrtChar = reader.Peek(); if (fisrtChar == XRefSection.StartKeyword[0]) { // Cross-Reference Section xrefSection = XRefSection.FromReader(reader); trailer = PdfTrailer.FromReader(reader); } else if (char.IsDigit(fisrtChar)) { // Cross-Reference Stream var xrefStream = XRefStream.FromReader(reader); trailer = xrefStream; xrefSection = xrefStream; } else { throw new FormatException("Invalid Cross-Reference section."); } if (document.xrefTable == null) { // Initialize document's Cross-Reference Table document.xrefTable = new XRefTable(xrefSection, trailer.Size); } else { // Register section document.xrefTable.AddSection(xrefSection); } // Keep instance of last trailer if (document.trailer == null) { document.trailer = trailer; } // Seek to previous trailer if (trailer.Prev.HasValue) { reader.Position = trailer.Prev.Value; } }while (trailer.Prev != null); } return(document); }
public void SerializeTrailer(PdfWriter writer, PdfTrailer trailer) { writer.WriteLine(PdfTokens.Trailer); SerdesFactory.GetFor(trailer).Serialize(writer, trailer, null); }