/** * 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(); } }
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(); }
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); }
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(); }