PageRenderTime 39ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/PDFsharp/code/PdfSharp/PdfSharp.Pdf.Advanced/PdfTrailer.cs

#
C# | 286 lines | 140 code | 30 blank | 116 comment | 29 complexity | c3ea4a8679fa6302757d54b0c1bdae5d MD5 | raw file
  1. #region PDFsharp - A .NET library for processing PDF
  2. //
  3. // Authors:
  4. // Stefan Lange (mailto:Stefan.Lange@pdfsharp.com)
  5. //
  6. // Copyright (c) 2005-2009 empira Software GmbH, Cologne (Germany)
  7. //
  8. // http://www.pdfsharp.com
  9. // http://sourceforge.net/projects/pdfsharp
  10. //
  11. // Permission is hereby granted, free of charge, to any person obtaining a
  12. // copy of this software and associated documentation files (the "Software"),
  13. // to deal in the Software without restriction, including without limitation
  14. // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  15. // and/or sell copies of the Software, and to permit persons to whom the
  16. // Software is furnished to do so, subject to the following conditions:
  17. //
  18. // The above copyright notice and this permission notice shall be included
  19. // in all copies or substantial portions of the Software.
  20. //
  21. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  22. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  23. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  24. // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  25. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  26. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  27. // DEALINGS IN THE SOFTWARE.
  28. #endregion
  29. using System;
  30. using System.Diagnostics;
  31. using System.Collections;
  32. using PdfSharp.Pdf.IO;
  33. using PdfSharp.Pdf.Security;
  34. using PdfSharp.Pdf.Internal;
  35. namespace PdfSharp.Pdf.Advanced
  36. {
  37. /// <summary>
  38. /// Represents a PDF trailer dictionary. Even trailers are dictionaries their never have a cross
  39. /// reference entry in PdfReferenceTable.
  40. /// </summary>
  41. internal sealed class PdfTrailer : PdfDictionary
  42. {
  43. /// <summary>
  44. /// Initializes a new instance of PdfTrailer.
  45. /// </summary>
  46. public PdfTrailer(PdfDocument document) : base(document)
  47. {
  48. this.document = document;
  49. }
  50. public int Size
  51. {
  52. get {return Elements.GetInteger(Keys.Size);}
  53. set {Elements.SetInteger(Keys.Size, value);}
  54. }
  55. // TODO: needed when linearized...
  56. //public int Prev
  57. //{
  58. // get {return Elements.GetInteger(Keys.Prev);}
  59. //}
  60. public PdfDocumentInformation Info
  61. {
  62. get {return (PdfDocumentInformation)Elements.GetValue(Keys.Info, VCF.CreateIndirect);}
  63. }
  64. /// <summary>
  65. /// (Required; must be an indirect reference)
  66. /// The catalog dictionary for the PDF document contained in the file.
  67. /// </summary>
  68. public PdfCatalog Root
  69. {
  70. get {return (PdfCatalog)Elements.GetValue(PdfTrailer.Keys.Root, VCF.CreateIndirect);}
  71. }
  72. /// <summary>
  73. /// Gets the first or second document identifier.
  74. /// </summary>
  75. public string GetDocumentID(int index)
  76. {
  77. if (index < 0 || index > 1)
  78. throw new ArgumentOutOfRangeException("index", index, "Index must be 0 or 1.");
  79. PdfArray array = Elements[Keys.ID] as PdfArray;
  80. if (array == null || array.Elements.Count < 2)
  81. return "";
  82. PdfItem item = array.Elements[index];
  83. if (item is PdfString)
  84. return ((PdfString)item).Value;
  85. return "";
  86. }
  87. /// <summary>
  88. /// Sets the first or second document identifier.
  89. /// </summary>
  90. public void SetDocumentID(int index, string value)
  91. {
  92. if (index < 0 || index > 1)
  93. throw new ArgumentOutOfRangeException("index", index, "Index must be 0 or 1.");
  94. PdfArray array = Elements[Keys.ID] as PdfArray;
  95. if (array == null || array.Elements.Count < 2)
  96. array = CreateNewDocumentIDs();
  97. array.Elements[index] = new PdfString(value, PdfStringFlags.HexLiteral);
  98. }
  99. /// <summary>
  100. /// Creates and sets two identical new document IDs.
  101. /// </summary>
  102. internal PdfArray CreateNewDocumentIDs()
  103. {
  104. PdfArray array = new PdfArray(this.document);
  105. byte[] docID = Guid.NewGuid().ToByteArray();
  106. string id = PdfEncoders.RawEncoding.GetString(docID, 0, docID.Length);
  107. array.Elements.Add(new PdfString(id, PdfStringFlags.HexLiteral));
  108. array.Elements.Add(new PdfString(id, PdfStringFlags.HexLiteral));
  109. Elements[Keys.ID] = array;
  110. return array;
  111. }
  112. /// <summary>
  113. /// Gets the standard security handler.
  114. /// </summary>
  115. public PdfStandardSecurityHandler SecurityHandler
  116. {
  117. get
  118. {
  119. if (this.securityHandler == null)
  120. this.securityHandler = (PdfStandardSecurityHandler)Elements.GetValue(Keys.Encrypt, VCF.CreateIndirect);
  121. return this.securityHandler;
  122. }
  123. }
  124. internal PdfStandardSecurityHandler securityHandler;
  125. //internal override void WriteDictionaryElement(PdfSharp.Pdf.IO.PdfWriter writer, PdfName key)
  126. //{
  127. // //if (key == Keys.ID)
  128. // //{
  129. // // PdfArray array = Elements[key] as PdfArray;
  130. // // PdfItem item = array.Elements[0];
  131. // // //base.WriteDictionaryElement(writer, key);
  132. // // return;
  133. // //}
  134. // base.WriteDictionaryElement (writer, key);
  135. //}
  136. internal override void WriteObject(PdfWriter writer)
  137. {
  138. // Delete /XRefStm entry, if any
  139. this.elements.Remove(Keys.XRefStm);
  140. // Don't encypt myself
  141. PdfStandardSecurityHandler securityHandler = writer.SecurityHandler;
  142. writer.SecurityHandler = null;
  143. base.WriteObject(writer);
  144. writer.SecurityHandler = securityHandler;
  145. }
  146. /// <summary>
  147. /// Replace temporary irefs by their correct counterparts from the iref table.
  148. /// </summary>
  149. internal void Finish()
  150. {
  151. // \Root
  152. PdfReference iref = document.trailer.Elements[PdfTrailer.Keys.Root] as PdfReference;
  153. if (iref != null && iref.Value == null)
  154. {
  155. iref = document.irefTable[iref.ObjectID];
  156. Debug.Assert(iref.Value != null);
  157. this.document.trailer.Elements[PdfTrailer.Keys.Root] = iref;
  158. }
  159. // \Info
  160. iref = this.document.trailer.Elements[PdfTrailer.Keys.Info] as PdfReference;
  161. if (iref != null && iref.Value == null)
  162. {
  163. iref = document.irefTable[iref.ObjectID];
  164. Debug.Assert(iref.Value != null);
  165. this.document.trailer.Elements[PdfTrailer.Keys.Info] = iref;
  166. }
  167. // \Encrypt
  168. iref = this.document.trailer.Elements[PdfTrailer.Keys.Encrypt] as PdfReference;
  169. if (iref != null)
  170. {
  171. iref = document.irefTable[iref.ObjectID];
  172. Debug.Assert(iref.Value != null);
  173. this.document.trailer.Elements[PdfTrailer.Keys.Encrypt] = iref;
  174. // The encryption dictionary (security handler) was read in before the XRefTable construction
  175. // was completed. The next lines fix that state (it take several hours to find that bugs...).
  176. iref.Value = this.document.trailer.securityHandler;
  177. this.document.trailer.securityHandler.Reference = iref;
  178. iref.Value.Reference = iref;
  179. }
  180. Elements.Remove(Keys.Prev);
  181. this.document.irefTable.IsUnderConstruction = false;
  182. }
  183. /// <summary>
  184. /// Predefined keys of this dictionary.
  185. /// </summary>
  186. internal sealed class Keys : KeysBase
  187. {
  188. /// <summary>
  189. /// (Required; must not be an indirect reference) The total number of entries in the file’s
  190. /// cross-reference table, as defined by the combination of the original section and all
  191. /// update sections. Equivalently, this value is 1 greater than the highest object number
  192. /// used in the file.
  193. /// Note: Any object in a cross-reference section whose number is greater than this value is
  194. /// ignored and considered missing.
  195. /// </summary>
  196. [KeyInfo(KeyType.Integer | KeyType.Required)]
  197. public const string Size = "/Size";
  198. /// <summary>
  199. /// (Present only if the file has more than one cross-reference section; must not be an indirect
  200. /// reference) The byte offset from the beginning of the file to the beginning of the previous
  201. /// cross-reference section.
  202. /// </summary>
  203. [KeyInfo(KeyType.Integer | KeyType.Optional)]
  204. public const string Prev = "/Prev";
  205. /// <summary>
  206. /// (Required; must be an indirect reference) The catalog dictionary for the PDF document
  207. /// contained in the file.
  208. /// </summary>
  209. [KeyInfo(KeyType.Dictionary | KeyType.Required, typeof(PdfCatalog))]
  210. public const string Root = "/Root";
  211. /// <summary>
  212. /// (Required if document is encrypted; PDF 1.1) The document’s encryption dictionary.
  213. /// </summary>
  214. [KeyInfo(KeyType.Dictionary | KeyType.Optional, typeof(PdfStandardSecurityHandler))]
  215. public const string Encrypt = "/Encrypt";
  216. /// <summary>
  217. /// (Optional; must be an indirect reference) The document’s information dictionary.
  218. /// </summary>
  219. [KeyInfo(KeyType.Dictionary | KeyType.Optional, typeof(PdfDocumentInformation))]
  220. public const string Info = "/Info";
  221. /// <summary>
  222. /// (Optional, but strongly recommended; PDF 1.1) An array of two strings constituting
  223. /// a file identifier for the file. Although this entry is optional,
  224. /// its absence might prevent the file from functioning in some workflows
  225. /// that depend on files being uniquely identified.
  226. /// </summary>
  227. [KeyInfo(KeyType.Array | KeyType.Optional)]
  228. public const string ID = "/ID";
  229. /// <summary>
  230. /// (Optional) The byte offset from the beginning of the file of a cross-reference stream.
  231. /// </summary>
  232. [KeyInfo(KeyType.Integer | KeyType.Optional)]
  233. public const string XRefStm = "/XRefStm";
  234. /// <summary>
  235. /// Gets the KeysMeta for these keys.
  236. /// </summary>
  237. public static DictionaryMeta Meta
  238. {
  239. get
  240. {
  241. if (Keys.meta == null)
  242. Keys.meta = CreateMeta(typeof(Keys));
  243. return Keys.meta;
  244. }
  245. }
  246. static DictionaryMeta meta;
  247. }
  248. /// <summary>
  249. /// Gets the KeysMeta of this dictionary type.
  250. /// </summary>
  251. internal override DictionaryMeta Meta
  252. {
  253. get {return Keys.Meta;}
  254. }
  255. }
  256. }