diff --git a/src/UglyToad.PdfPig.sln.DotSettings b/src/UglyToad.PdfPig.sln.DotSettings new file mode 100644 index 00000000..39e42e16 --- /dev/null +++ b/src/UglyToad.PdfPig.sln.DotSettings @@ -0,0 +1,2 @@ + + XY \ No newline at end of file diff --git a/src/UglyToad.PdfPig/DocumentLayoutAnalysis/XYNode.cs b/src/UglyToad.PdfPig/DocumentLayoutAnalysis/XYNode.cs index 70620807..db423c55 100644 --- a/src/UglyToad.PdfPig/DocumentLayoutAnalysis/XYNode.cs +++ b/src/UglyToad.PdfPig/DocumentLayoutAnalysis/XYNode.cs @@ -25,29 +25,6 @@ namespace UglyToad.PdfPig.DocumentLayoutAnalysis /// public XYNode[] Children { get; set; } - /// - /// Recursively counts the words included in this node. - /// - public virtual int CountWords() - { - if (Children == null) return 0; - int count = 0; - RecursiveCount(Children, ref count); - return count; - } - - /// - /// Recursively gets the leafs (last nodes) of this node. - /// - public virtual List GetLeafs() - { - List leafs = new List(); - if (Children == null || Children.Count() == 0) return leafs; - int level = 0; - RecursiveGetLeafs(Children, ref leafs, level); - return leafs; - } - /// /// Create a new . /// @@ -79,6 +56,37 @@ namespace UglyToad.PdfPig.DocumentLayoutAnalysis } } + /// + /// Recursively counts the words included in this node. + /// + public virtual int CountWords() + { + if (Children == null) + { + return 0; + } + + int count = 0; + RecursiveCount(Children, ref count); + return count; + } + + /// + /// Recursively gets the leafs (last nodes) of this node. + /// + public virtual List GetLeafs() + { + List leafs = new List(); + if (Children == null || Children.Length == 0) + { + return leafs; + } + + int level = 0; + RecursiveGetLeafs(Children, ref leafs, level); + return leafs; + } + private void RecursiveCount(IEnumerable children, ref int count) { if (children.Count() == 0) return; @@ -122,9 +130,10 @@ namespace UglyToad.PdfPig.DocumentLayoutAnalysis } } + /// public override string ToString() { - return (IsLeaf ? "Leaf" : "Node"); + return IsLeaf ? "Leaf" : "Node"; } } } diff --git a/src/UglyToad.PdfPig/Encryption/EncryptionDictionaryFactory.cs b/src/UglyToad.PdfPig/Encryption/EncryptionDictionaryFactory.cs index 735e1d4f..616545d9 100644 --- a/src/UglyToad.PdfPig/Encryption/EncryptionDictionaryFactory.cs +++ b/src/UglyToad.PdfPig/Encryption/EncryptionDictionaryFactory.cs @@ -73,11 +73,8 @@ byte[] userEncryptionBytes = null, ownerEncryptionBytes = null; if (revision >= 5) { - var oe = encryptionDictionary.Get(NameToken.Oe, tokenScanner); - var ue = encryptionDictionary.Get(NameToken.Ue, tokenScanner); - - ownerEncryptionBytes = OtherEncodings.StringAsLatin1Bytes(oe.Data); - userEncryptionBytes = OtherEncodings.StringAsLatin1Bytes(ue.Data); + ownerEncryptionBytes = GetEncryptionBytesOrDefault(encryptionDictionary, tokenScanner, false); + userEncryptionBytes = GetEncryptionBytesOrDefault(encryptionDictionary, tokenScanner, true); } encryptionDictionary.TryGetOptionalTokenDirect(NameToken.EncryptMetaData, tokenScanner, out BooleanToken encryptMetadata); @@ -89,5 +86,21 @@ encryptionDictionary, encryptMetadata?.Data ?? true); } + + private static byte[] GetEncryptionBytesOrDefault(DictionaryToken encryptionDictionary, IPdfTokenScanner tokenScanner, bool isUser) + { + var name = isUser ? NameToken.Ue : NameToken.Oe; + if (encryptionDictionary.TryGet(name, tokenScanner, out StringToken stringToken)) + { + return OtherEncodings.StringAsLatin1Bytes(stringToken.Data); + } + + if (encryptionDictionary.TryGet(name, tokenScanner, out HexToken hexToken)) + { + return hexToken.Bytes.ToArray(); + } + + return null; + } } } \ No newline at end of file diff --git a/src/UglyToad.PdfPig/Tokens/DictionaryToken.cs b/src/UglyToad.PdfPig/Tokens/DictionaryToken.cs index b8552707..6417e943 100644 --- a/src/UglyToad.PdfPig/Tokens/DictionaryToken.cs +++ b/src/UglyToad.PdfPig/Tokens/DictionaryToken.cs @@ -77,6 +77,26 @@ return Data.TryGetValue(name.Data, out token); } + /// + /// Try and get the entry with a given name and type or look-up the object if it's an indirect reference. + /// + internal bool TryGet(NameToken name, IPdfTokenScanner tokenScanner, out T token) where T : IToken + { + token = default(T); + if (!TryGet(name, out var t) || !(t is T typedToken)) + { + if (t is IndirectReferenceToken reference) + { + return DirectObjectFinder.TryGet(reference, tokenScanner, out token); + } + + return false; + } + + token = typedToken; + return true; + } + /// /// Try and get the entry with a given name and a specific data type. ///