diff --git a/PdfSharpCore/Pdf.Advanced/PdfEmbeddedFile.cs b/PdfSharpCore/Pdf.Advanced/PdfEmbeddedFile.cs
new file mode 100644
index 00000000..20dcb243
--- /dev/null
+++ b/PdfSharpCore/Pdf.Advanced/PdfEmbeddedFile.cs
@@ -0,0 +1,132 @@
+namespace PdfSharpCore.Pdf.Advanced
+{
+ ///
+ /// Represent a file stream embedded in the PDF document
+ ///
+ public class PdfEmbeddedFile : PdfDictionary
+ {
+ private readonly PdfDictionary paramsDictionary;
+
+ public PdfEmbeddedFile(PdfDocument document)
+ : base(document)
+ {
+ this.paramsDictionary = new PdfDictionary();
+
+ Elements.SetName(Keys.Type, "/EmbeddedFile");
+ Elements.SetObject(Keys.Params, paramsDictionary);
+ }
+
+ public PdfEmbeddedFile(PdfDocument document, byte[] bytes, string checksum = null)
+ : this(document)
+ {
+ this.CreateStreamAndSetProperties(bytes, checksum);
+ }
+
+ public void CreateStreamAndSetProperties(byte[] bytes, string checksum = null)
+ {
+ this.CreateStream(bytes);
+
+ this.paramsDictionary.Elements.SetInteger(Keys.Size, bytes.Length);
+
+ if (string.IsNullOrEmpty(checksum))
+ this.paramsDictionary.Elements.Remove(Keys.CheckSum);
+ else
+ this.paramsDictionary.Elements.SetString(Keys.CheckSum, checksum);
+ }
+
+ public string MimeType
+ {
+ get { return Elements.GetName(Keys.Subtype); }
+ set { Elements.SetName(Keys.Subtype, value); }
+ }
+
+ // TODO : Add properties for the subdictionnary Params and the subsubdictionnary Mac
+
+ ///
+ /// Predefined keys of this embedded file.
+ ///
+ public class Keys : PdfDictionary.PdfStream.Keys
+ {
+ ///
+ /// (Optional) The type of PDF object that this dictionary describes; if present,
+ /// must be EmbeddedFile for an embedded file stream.
+ ///
+ [KeyInfo(KeyType.Name | KeyType.Optional, FixedValue = "EmbeddedFile")]
+ public const string Type = "/Type";
+
+ ///
+ /// (Optional) The subtype of the embedded file. The value of this entry must be a
+ /// first-class name, as defined in Appendix E. Names without a registered prefix
+ /// must conform to the MIME media type names defined in Internet RFC 2046,
+ /// Multipurpose Internet Mail Extensions (MIME), Part Two: Media Types(see the
+ /// Bibliography), with the provision that characters not allowed in names must
+ /// use the 2-character hexadecimal code format described in Section 3.2.4,
+ /// “Name Objects.”
+ ///
+ [KeyInfo(KeyType.Name | KeyType.Optional)]
+ public const string Subtype = "/Subtype";
+
+ ///
+ /// (Optional) An embedded file parameter dictionary containing additional,
+ /// file-specific information (see Table 3.43).
+ ///
+ [KeyInfo(KeyType.Dictionary | KeyType.Optional)]
+ public const string Params = "/Params";
+
+ ///
+ /// (Optional) The size of the embedded file, in bytes.
+ ///
+ [KeyInfo(KeyType.Integer | KeyType.Optional)]
+ public const string Size = "/Size";
+
+ ///
+ /// (Optional) The date and time when the embedded file was created.
+ ///
+ [KeyInfo(KeyType.Date | KeyType.Optional)]
+ public const string CreationDate = "/CreationDate";
+
+ ///
+ /// (Optional) The date and time when the embedded file was last modified.
+ ///
+ [KeyInfo(KeyType.Date | KeyType.Optional)]
+ public const string ModDate = "/ModDate";
+
+ ///
+ /// (Optional) A subdictionary containing additional information specific to Mac OS files (see Table 3.44).
+ ///
+ [KeyInfo(KeyType.Dictionary | KeyType.Optional)]
+ public const string Mac = "/Mac";
+
+ ///
+ /// (Optional) A 16-byte string that is the checksum of the bytes of the uncompressed
+ /// embedded file. The checksum is calculated by applying the standard MD5 message-digest
+ /// algorithm (described in Internet RFC 1321, The MD5 Message-Digest Algorithm; see the
+ /// Bibliography) to the bytes of the embedded file stream.
+ ///
+ [KeyInfo(KeyType.Dictionary | KeyType.Optional)]
+ public const string CheckSum = "/CheckSum";
+
+ ///
+ /// Gets the KeysMeta for these keys.
+ ///
+ internal static DictionaryMeta Meta
+ {
+ get
+ {
+ if (Keys.meta == null)
+ Keys.meta = CreateMeta(typeof(Keys));
+ return Keys.meta;
+ }
+ }
+ static DictionaryMeta meta;
+ }
+
+ ///
+ /// Gets the KeysMeta of this dictionary type.
+ ///
+ internal override DictionaryMeta Meta
+ {
+ get { return Keys.Meta; }
+ }
+ }
+}
diff --git a/PdfSharpCore/Pdf.Advanced/PdfFileSpecification.cs b/PdfSharpCore/Pdf.Advanced/PdfFileSpecification.cs
new file mode 100644
index 00000000..056aa399
--- /dev/null
+++ b/PdfSharpCore/Pdf.Advanced/PdfFileSpecification.cs
@@ -0,0 +1,120 @@
+namespace PdfSharpCore.Pdf.Advanced
+{
+ ///
+ /// Represent a file stream embedded in the PDF document
+ ///
+ public class PdfFileSpecification : PdfDictionary
+ {
+ private readonly PdfDictionary embeddedFileDictionary;
+
+ public PdfFileSpecification(PdfDocument document)
+ : base(document)
+ {
+ this.embeddedFileDictionary = new PdfDictionary();
+
+ Elements.SetName(Keys.Type, "/Filespec");
+ Elements.SetObject(Keys.EF, embeddedFileDictionary);
+ }
+
+ public PdfFileSpecification(PdfDocument document, string fileName, PdfEmbeddedFile embeddedFile)
+ : this(document)
+ {
+ this.FileName = fileName;
+ this.EmbeddedFile = embeddedFile;
+ }
+
+ public string FileName
+ {
+ get { return Elements.GetString(Keys.F); }
+ set { Elements.SetString(Keys.F, value); }
+ }
+
+ public PdfEmbeddedFile EmbeddedFile
+ {
+ get
+ {
+ var reference = embeddedFileDictionary.Elements.GetReference(Keys.F);
+
+ return reference?.Value as PdfEmbeddedFile;
+ }
+ set
+ {
+ if (value == null)
+ {
+ embeddedFileDictionary.Elements.Remove(Keys.F);
+ }
+ else
+ {
+ if (!value.IsIndirect)
+ Owner._irefTable.Add(value);
+
+ embeddedFileDictionary.Elements.SetReference(Keys.F, value);
+ }
+ }
+ }
+
+ ///
+ /// Predefined keys of this embedded file.
+ ///
+ public class Keys : KeysBase
+ {
+ ///
+ /// (Required if an EF or RF entry is present; recommended always)
+ /// The type of PDF object that this dictionary describes; must be Filespec
+ /// for a file specification dictionary (see implementation note 45 in Appendix H).
+ ///
+ [KeyInfo(KeyType.Name | KeyType.Optional, FixedValue = "Filespec")]
+ public const string Type = "/Type";
+
+ ///
+ /// (Required if the DOS, Mac, and Unix entries are all absent; amended with the UF
+ /// entry for PDF 1.7) A file specification string of the form described in Section
+ /// 3.10.1, “File Specification Strings,” or (if the file system is URL) a uniform
+ /// resource locator, as described in Section 3.10.4, “URL Specifications.”
+ ///
+ /// Note: It is recommended that the UF entry be used in addition to the F entry.
+ /// The UF entry provides cross-platform and cross-language compatibility and the F
+ /// entry provides backwards compatibility
+ ///
+ [KeyInfo(KeyType.Dictionary | KeyType.Optional)]
+ public const string F = "/F";
+
+ ///
+ /// (Required if RF is present; PDF 1.3; amended to include the UF key in PDF 1.7)
+ /// A dictionary containing a subset of the keys F, UF, DOS, Mac, and Unix,
+ /// corresponding to the entries by those names in the file specification dictionary.
+ /// The value of each such key is an embedded file stream (see Section 3.10.3,
+ /// “Embedded File Streams”) containing the corresponding file. If this entry is
+ /// present, the Type entry is required and the file specification dictionary must
+ /// be indirectly referenced. (See implementation note 46in Appendix H.)
+ ///
+ /// Note: It is recommended that the F and UF entries be used in place of the DOS,
+ /// Mac, or Unix entries.
+ ///
+ [KeyInfo(KeyType.Dictionary | KeyType.Optional)]
+ public const string EF = "/EF";
+
+ ///
+ /// Gets the KeysMeta for these keys.
+ ///
+ internal static DictionaryMeta Meta
+ {
+ get
+ {
+ if (Keys.meta == null)
+ Keys.meta = CreateMeta(typeof(Keys));
+ return Keys.meta;
+ }
+ }
+ static DictionaryMeta meta;
+ }
+
+ ///
+ /// Gets the KeysMeta of this dictionary type.
+ ///
+ internal override DictionaryMeta Meta
+ {
+ get { return Keys.Meta; }
+ }
+ }
+}
diff --git a/PdfSharpCore/Pdf.Annotations/PdfFileAttachmentAnnotation.cs b/PdfSharpCore/Pdf.Annotations/PdfFileAttachmentAnnotation.cs
new file mode 100644
index 00000000..34c995e2
--- /dev/null
+++ b/PdfSharpCore/Pdf.Annotations/PdfFileAttachmentAnnotation.cs
@@ -0,0 +1,129 @@
+using PdfSharpCore.Pdf.Advanced;
+using System;
+
+namespace PdfSharpCore.Pdf.Annotations
+{
+ ///
+ /// Represent a file that is attached to the PDF
+ ///
+ public class PdfFileAttachmentAnnotation : PdfAnnotation
+ {
+ ///
+ /// Name of icons used in displaying the annotation.
+ ///
+ public enum IconType
+ {
+ Graph,
+ PushPin,
+ Paperclip,
+ Tag
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public PdfFileAttachmentAnnotation()
+ {
+ Elements.SetName(Keys.Subtype, "/FileAttachment");
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public PdfFileAttachmentAnnotation(PdfDocument document)
+ : base(document)
+ {
+ Elements.SetName(Keys.Subtype, "/FileAttachment");
+ Flags = PdfAnnotationFlags.Locked;
+ }
+
+ public IconType Icon
+ {
+ get
+ {
+ var iconName = Elements.GetName(Keys.Name);
+
+ if (iconName == null)
+ return IconType.PushPin;
+
+ return (IconType)(Enum.Parse(typeof(IconType), iconName));
+ }
+ set { Elements.SetName(Keys.Name, value.ToString()); }
+ }
+
+ public PdfFileSpecification File
+ {
+ get
+ {
+ var reference = Elements.GetReference(Keys.FS);
+
+ return reference?.Value as PdfFileSpecification;
+ }
+ set
+ {
+ if (value == null)
+ {
+ Elements.Remove(Keys.FS);
+ }
+ else
+ {
+ if (!value.IsIndirect)
+ Owner._irefTable.Add(value);
+
+ Elements.SetReference(Keys.FS, value);
+ }
+ }
+ }
+
+ ///
+ /// Predefined keys of this dictionary.
+ ///
+ internal new class Keys : PdfAnnotation.Keys
+ {
+ ///
+ /// (Required) The file associated with this annotation.
+ ///
+ [KeyInfo(KeyType.Dictionary | KeyType.Required)]
+ public const string FS = "/FS";
+
+ ///
+ /// (Optional) The name of an icon to be used in displaying the annotation.
+ /// Viewer applications should provide predefined icon appearances for at least
+ /// the following standard names:
+ ///
+ /// Graph
+ /// PushPin
+ /// Paperclip
+ /// Tag
+ ///
+ /// Additional names may be supported as well. Default value: PushPin.
+ /// Note: The annotation dictionary’s AP entry, if present, takes precedence over
+ /// the Name entry; see Table 8.15 on page 606 and Section 8.4.4, “Appearance Streams.”
+ ///
+ [KeyInfo(KeyType.Name | KeyType.Optional)]
+ public const string Name = "/Name";
+
+ ///
+ /// Gets the KeysMeta for these keys.
+ ///
+ public static DictionaryMeta Meta
+ {
+ get
+ {
+ if (Keys.meta == null)
+ Keys.meta = CreateMeta(typeof(Keys));
+ return Keys.meta;
+ }
+ }
+ static DictionaryMeta meta;
+ }
+
+ ///
+ /// Gets the KeysMeta of this dictionary type.
+ ///
+ internal override DictionaryMeta Meta
+ {
+ get { return Keys.Meta; }
+ }
+ }
+}