Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 132 additions & 0 deletions PdfSharpCore/Pdf.Advanced/PdfEmbeddedFile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
namespace PdfSharpCore.Pdf.Advanced
{
/// <summary>
/// Represent a file stream embedded in the PDF document
/// </summary>
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

/// <summary>
/// Predefined keys of this embedded file.
/// </summary>
public class Keys : PdfDictionary.PdfStream.Keys
{
/// <summary>
/// (Optional) The type of PDF object that this dictionary describes; if present,
/// must be EmbeddedFile for an embedded file stream.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Optional, FixedValue = "EmbeddedFile")]
public const string Type = "/Type";

/// <summary>
/// (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.”
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Optional)]
public const string Subtype = "/Subtype";

/// <summary>
/// (Optional) An embedded file parameter dictionary containing additional,
/// file-specific information (see Table 3.43).
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.Optional)]
public const string Params = "/Params";

/// <summary>
/// (Optional) The size of the embedded file, in bytes.
/// </summary>
[KeyInfo(KeyType.Integer | KeyType.Optional)]
public const string Size = "/Size";

/// <summary>
/// (Optional) The date and time when the embedded file was created.
/// </summary>
[KeyInfo(KeyType.Date | KeyType.Optional)]
public const string CreationDate = "/CreationDate";

/// <summary>
/// (Optional) The date and time when the embedded file was last modified.
/// </summary>
[KeyInfo(KeyType.Date | KeyType.Optional)]
public const string ModDate = "/ModDate";

/// <summary>
/// (Optional) A subdictionary containing additional information specific to Mac OS files (see Table 3.44).
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.Optional)]
public const string Mac = "/Mac";

/// <summary>
/// (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.
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.Optional)]
public const string CheckSum = "/CheckSum";

/// <summary>
/// Gets the KeysMeta for these keys.
/// </summary>
internal static DictionaryMeta Meta
{
get
{
if (Keys.meta == null)
Keys.meta = CreateMeta(typeof(Keys));
return Keys.meta;
}
}
static DictionaryMeta meta;
}

/// <summary>
/// Gets the KeysMeta of this dictionary type.
/// </summary>
internal override DictionaryMeta Meta
{
get { return Keys.Meta; }
}
}
}
120 changes: 120 additions & 0 deletions PdfSharpCore/Pdf.Advanced/PdfFileSpecification.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
namespace PdfSharpCore.Pdf.Advanced
{
/// <summary>
/// Represent a file stream embedded in the PDF document
/// </summary>
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);
}
}
}

/// <summary>
/// Predefined keys of this embedded file.
/// </summary>
public class Keys : KeysBase
{
/// <summary>
/// (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).
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Optional, FixedValue = "Filespec")]
public const string Type = "/Type";

/// <summary>
/// (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
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.Optional)]
public const string F = "/F";

/// <summary>
/// (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.
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.Optional)]
public const string EF = "/EF";

/// <summary>
/// Gets the KeysMeta for these keys.
/// </summary>
internal static DictionaryMeta Meta
{
get
{
if (Keys.meta == null)
Keys.meta = CreateMeta(typeof(Keys));
return Keys.meta;
}
}
static DictionaryMeta meta;
}

/// <summary>
/// Gets the KeysMeta of this dictionary type.
/// </summary>
internal override DictionaryMeta Meta
{
get { return Keys.Meta; }
}
}
}
129 changes: 129 additions & 0 deletions PdfSharpCore/Pdf.Annotations/PdfFileAttachmentAnnotation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
using PdfSharpCore.Pdf.Advanced;
using System;

namespace PdfSharpCore.Pdf.Annotations
{
/// <summary>
/// Represent a file that is attached to the PDF
/// </summary>
public class PdfFileAttachmentAnnotation : PdfAnnotation
{
/// <summary>
/// Name of icons used in displaying the annotation.
/// </summary>
public enum IconType
{
Graph,
PushPin,
Paperclip,
Tag
}

/// <summary>
/// Initializes a new instance of the <see cref="PdfFileAttachmentAnnotation"/> class.
/// </summary>
public PdfFileAttachmentAnnotation()
{
Elements.SetName(Keys.Subtype, "/FileAttachment");
}

/// <summary>
/// Initializes a new instance of the <see cref="PdfFileAttachmentAnnotation"/> class.
/// </summary>
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);
}
}
}

/// <summary>
/// Predefined keys of this dictionary.
/// </summary>
internal new class Keys : PdfAnnotation.Keys
{
/// <summary>
/// (Required) The file associated with this annotation.
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.Required)]
public const string FS = "/FS";

/// <summary>
/// (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.”
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Optional)]
public const string Name = "/Name";

/// <summary>
/// Gets the KeysMeta for these keys.
/// </summary>
public static DictionaryMeta Meta
{
get
{
if (Keys.meta == null)
Keys.meta = CreateMeta(typeof(Keys));
return Keys.meta;
}
}
static DictionaryMeta meta;
}

/// <summary>
/// Gets the KeysMeta of this dictionary type.
/// </summary>
internal override DictionaryMeta Meta
{
get { return Keys.Meta; }
}
}
}