protected internal virtual void Close(IDictionary<String, String> moreInfo) { if (closed) return; if (useVp) { SetViewerPreferences(); } if (flat) FlatFields(); if (flatFreeText) FlatFreeTextFields(); AddFieldResources(); PdfDictionary catalog = reader.Catalog; 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(); Version version = Version.GetInstance(); if (producer == null) { producer = version.GetVersion; } else if (producer.IndexOf(version.Product) == -1) { StringBuilder buf = new StringBuilder(producer); buf.Append("; modified using "); buf.Append(version.GetVersion); 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 || xmpMetadata != 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); } } Close(info, skipInfo); }
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(); }