Exemplo n.º 1
0
        internal static CoreTokenScanner Scanner(string s)
        {
            var result = new CoreTokenScanner(new ByteArrayInputBytes(OtherEncodings.StringAsLatin1Bytes(s)));

            return(result);
        }
Exemplo n.º 2
0
 private static StreamInputBytes StringToStream(string str) => new StreamInputBytes(new MemoryStream(OtherEncodings.StringAsLatin1Bytes(str)));
Exemplo n.º 3
0
        private static void WriteInt(int value, Stream outputStream)
        {
            var bytes = OtherEncodings.StringAsLatin1Bytes(value.ToString("G"));

            outputStream.Write(bytes, 0, bytes.Length);
        }
Exemplo n.º 4
0
        public void ArrayAndStreamBehaveTheSame()
        {
            var bytes = OtherEncodings.StringAsLatin1Bytes(TestData);

            var array = new ByteArrayInputBytes(bytes);

            using (var memoryStream = new MemoryStream(bytes))
            {
                var stream = new StreamInputBytes(memoryStream);

                Assert.Equal(bytes.Length, array.Length);
                Assert.Equal(bytes.Length, stream.Length);

                Assert.Equal(0, array.CurrentOffset);
                Assert.Equal(0, stream.CurrentOffset);

                array.Seek(5);
                stream.Seek(5);

                Assert.Equal(array.CurrentOffset, stream.CurrentOffset);

                Assert.Equal((byte)'5', array.CurrentByte);
                Assert.Equal(array.CurrentByte, stream.CurrentByte);

                Assert.Equal(array.Peek(), stream.Peek());

                array.Seek(0);
                stream.Seek(0);

                Assert.Equal(0, array.CurrentByte);
                Assert.Equal(array.CurrentByte, stream.CurrentByte);

                array.Seek(7);
                stream.Seek(7);

                var arrayString  = string.Empty;
                var streamString = string.Empty;

                while (array.MoveNext())
                {
                    arrayString += (char)array.CurrentByte;
                }

                while (stream.MoveNext())
                {
                    streamString += (char)stream.CurrentByte;
                }

                Assert.Equal("89", streamString);

                Assert.Equal(arrayString, streamString);

                Assert.True(stream.IsAtEnd());
                Assert.True(array.IsAtEnd());

                stream.Seek(0);
                array.Seek(0);

                Assert.False(stream.IsAtEnd());
                Assert.False(array.IsAtEnd());
            }
        }
Exemplo n.º 5
0
 private static ByteArrayInputBytes StringToBytes(string str) => new ByteArrayInputBytes(OtherEncodings.StringAsLatin1Bytes(str));
Exemplo n.º 6
0
        public bool TryTokenize(byte currentByte, IInputBytes inputBytes, out IToken token)
        {
            var builder = new StringBuilder();

            token = null;

            if (inputBytes == null)
            {
                return(false);
            }

            if (currentByte != '(')
            {
                return(false);
            }

            var numberOfBrackets = 1;
            var isEscapeActive   = false;
            var isLineBreaking   = false;

            var octalModeActive = false;

            short[] octal      = { 0, 0, 0 };
            var     octalsRead = 0;

            while (inputBytes.MoveNext())
            {
                var b = inputBytes.CurrentByte;
                var c = (char)b;

                if (octalModeActive)
                {
                    var nextCharacterOctal = c >= '0' && c <= '7';

                    if (nextCharacterOctal)
                    {
                        // left shift the octals.
                        LeftShiftOctal(c, octalsRead, octal);
                        octalsRead++;
                    }

                    if (octalsRead == 3 || !nextCharacterOctal)
                    {
                        var characterCode = OctalHelpers.FromOctalDigits(octal);

                        // For now :(
                        // TODO: I have a sneaking suspicion this is wrong, not sure what behaviour is for large octal numbers
                        builder.Append((char)characterCode);

                        octal[0]        = 0;
                        octal[1]        = 0;
                        octal[2]        = 0;
                        octalsRead      = 0;
                        octalModeActive = false;
                    }

                    if (nextCharacterOctal)
                    {
                        continue;
                    }
                }

                switch (c)
                {
                case ')':
                    isLineBreaking = false;
                    if (!isEscapeActive)
                    {
                        numberOfBrackets--;
                    }

                    isEscapeActive = false;
                    if (numberOfBrackets > 0)
                    {
                        builder.Append(c);
                    }

                    // TODO: Check for other ends of string where the string is improperly formatted. See commented method
                    numberOfBrackets = CheckForEndOfString(numberOfBrackets, inputBytes);

                    break;

                case '(':
                    isLineBreaking = false;

                    if (!isEscapeActive)
                    {
                        numberOfBrackets++;
                    }

                    isEscapeActive = false;
                    builder.Append(c);
                    break;

                // Escape
                case '\\':
                    isLineBreaking = false;
                    // Escaped backslash
                    if (isEscapeActive)
                    {
                        builder.Append(c);
                        isEscapeActive = false;
                    }
                    else
                    {
                        isEscapeActive = true;
                    }
                    break;

                default:
                    if (isLineBreaking)
                    {
                        if (ReadHelper.IsEndOfLine(c))
                        {
                            continue;
                        }

                        isLineBreaking = false;
                        builder.Append(c);
                    }
                    else if (isEscapeActive)
                    {
                        ProcessEscapedCharacter(c, builder, octal, ref octalModeActive, ref octalsRead, ref isLineBreaking);
                        isEscapeActive = false;
                    }
                    else
                    {
                        builder.Append(c);
                    }

                    break;
                }

                if (numberOfBrackets <= 0)
                {
                    break;
                }
            }

            StringToken.Encoding encodedWith;
            string tokenStr;

            if (builder.Length >= 2)
            {
                if (builder[0] == 0xFE && builder[1] == 0xFF)
                {
                    var rawBytes = OtherEncodings.StringAsLatin1Bytes(builder.ToString());

                    tokenStr = Encoding.BigEndianUnicode.GetString(rawBytes).Substring(1);

                    encodedWith = StringToken.Encoding.Utf16BE;
                }
                else if (builder[0] == 0xFF && builder[1] == 0xFE)
                {
                    var rawBytes = OtherEncodings.StringAsLatin1Bytes(builder.ToString());

                    tokenStr = Encoding.Unicode.GetString(rawBytes).Substring(1);

                    encodedWith = StringToken.Encoding.Utf16;
                }
                else
                {
                    tokenStr = builder.ToString();

                    encodedWith = StringToken.Encoding.Iso88591;
                }
            }
            else
            {
                tokenStr = builder.ToString();

                encodedWith = StringToken.Encoding.Iso88591;
            }

            token = new StringToken(tokenStr, encodedWith);

            return(true);
        }
Exemplo n.º 7
0
        public void BytesEmptyReturnsEmptyString()
        {
            var result = OtherEncodings.BytesAsLatin1String(new byte[0]);

            Assert.Equal(string.Empty, result);
        }
Exemplo n.º 8
0
        public void Run(IOperationContext operationContext, IResourceStore resourceStore)
        {
            var input = new ByteArrayInputBytes(Text != null ? OtherEncodings.StringAsLatin1Bytes(Text) : Bytes);

            operationContext.ShowText(input);
        }
Exemplo n.º 9
0
        public static void WriteCrossReferenceTable(IReadOnlyDictionary <IndirectReference, long> objectOffsets,
                                                    ObjectToken catalogToken,
                                                    Stream outputStream)
        {
            if (objectOffsets.Count == 0)
            {
                throw new InvalidOperationException("Could not write empty cross reference table.");
            }

            WriteLineBreak(outputStream);
            var position = outputStream.Position;

            outputStream.Write(Xref, 0, Xref.Length);
            WriteLineBreak(outputStream);

            var min = objectOffsets.Min(x => x.Key.ObjectNumber);
            var max = objectOffsets.Max(x => x.Key.ObjectNumber);

            if (max - min != objectOffsets.Count - 1)
            {
                throw new NotSupportedException("Object numbers must form a contiguous range");
            }

            WriteLong(min, outputStream);
            WriteWhitespace(outputStream);
            WriteLong(max, outputStream);
            WriteWhitespace(outputStream);
            WriteLineBreak(outputStream);

            foreach (var keyValuePair in objectOffsets.OrderBy(x => x.Key.ObjectNumber))
            {
                /*
                 * nnnnnnnnnn ggggg n eol
                 * where:
                 * nnnnnnnnnn is a 10-digit byte offset
                 * ggggg is a 5-digit generation number
                 * n is a literal keyword identifying this as an in-use entry
                 * eol is a 2-character end-of-line sequence ('\r\n' or ' \n')
                 */
                var paddedOffset = OtherEncodings.StringAsLatin1Bytes(keyValuePair.Value.ToString("D10"));
                outputStream.Write(paddedOffset, 0, paddedOffset.Length);

                WriteWhitespace(outputStream);

                var generation = OtherEncodings.StringAsLatin1Bytes(keyValuePair.Key.Generation.ToString("D5"));
                outputStream.Write(generation, 0, generation.Length);

                WriteWhitespace(outputStream);

                outputStream.WriteByte(InUseEntry);

                WriteWhitespace(outputStream);
                WriteLineBreak(outputStream);
            }

            outputStream.Write(Trailer, 0, Trailer.Length);
            WriteLineBreak(outputStream);

            var trailerDictionary = new DictionaryToken(new Dictionary <IToken, IToken>
            {
                { NameToken.Size, new NumericToken(objectOffsets.Count) },
                { NameToken.Root, new IndirectReferenceToken(catalogToken.Number) }
            });

            WriteDictionary(trailerDictionary, outputStream);
            WriteLineBreak(outputStream);

            outputStream.Write(StartXref, 0, StartXref.Length);
            WriteLineBreak(outputStream);

            WriteLong(position, outputStream);
            WriteLineBreak(outputStream);

            // Complete!
            outputStream.Write(Eof, 0, Eof.Length);
        }
Exemplo n.º 10
0
        public EncryptionHandler(EncryptionDictionary encryptionDictionary, TrailerDictionary trailerDictionary, IReadOnlyList <string> passwords)
        {
            this.encryptionDictionary = encryptionDictionary;

            passwords = passwords ?? new[] { string.Empty };

            if (!passwords.Contains(string.Empty))
            {
                passwords = new List <string>(passwords)
                {
                    string.Empty
                };
            }

            byte[] documentIdBytes;

            if (trailerDictionary.Identifier != null && trailerDictionary.Identifier.Count == 2)
            {
                var token = trailerDictionary.Identifier[0];

                switch (token)
                {
                case HexToken hex:
                    documentIdBytes = hex.Bytes.ToArray();
                    break;

                default:
                    documentIdBytes = OtherEncodings.StringAsLatin1Bytes(token.Data);
                    break;
                }
            }
            else
            {
                documentIdBytes = EmptyArray <byte> .Instance;
            }

            if (encryptionDictionary == null)
            {
                return;
            }

            useAes = false;

            if (encryptionDictionary.EncryptionAlgorithmCode == EncryptionAlgorithmCode.SecurityHandlerInDocument ||
                encryptionDictionary.EncryptionAlgorithmCode == EncryptionAlgorithmCode.SecurityHandlerInDocument256)
            {
                if (!encryptionDictionary.TryGetCryptHandler(out var cryptHandlerLocal))
                {
                    throw new PdfDocumentEncryptedException("Document encrypted with security handler in document but no crypt dictionary found.", encryptionDictionary);
                }

                cryptHandler = cryptHandlerLocal;

                useAes = cryptHandlerLocal?.StreamDictionary?.Name == CryptDictionary.Method.AesV2 ||
                         cryptHandlerLocal?.StreamDictionary?.Name == CryptDictionary.Method.AesV3;
            }

            var charset = OtherEncodings.Iso88591;

            if (encryptionDictionary.Revision == 5 || encryptionDictionary.Revision == 6)
            {
                // ReSharper disable once RedundantAssignment
                charset = Encoding.UTF8;
            }

            var length = encryptionDictionary.EncryptionAlgorithmCode == EncryptionAlgorithmCode.Rc4OrAes40BitKey
                ? 5
                : encryptionDictionary.KeyLength.GetValueOrDefault() / 8;

            var foundPassword = false;

            foreach (var password in passwords)
            {
                var passwordBytes = charset.GetBytes(password);

                var    isUserPassword = false;
                byte[] decryptionPasswordBytes;

                if (IsOwnerPassword(passwordBytes, encryptionDictionary, length, documentIdBytes, out var userPassBytes))
                {
                    if (encryptionDictionary.Revision == 5 || encryptionDictionary.Revision == 6)
                    {
                        decryptionPasswordBytes = passwordBytes;
                    }
                    else
                    {
                        decryptionPasswordBytes = userPassBytes;
                    }
                }
                else if (IsUserPassword(passwordBytes, encryptionDictionary, length, documentIdBytes))
                {
                    decryptionPasswordBytes = passwordBytes;
                    isUserPassword          = true;
                }
                else
                {
                    continue;
                }

                encryptionKey = CalculateEncryptionKey(decryptionPasswordBytes, encryptionDictionary,
                                                       length,
                                                       documentIdBytes,
                                                       isUserPassword);

                foundPassword = true;

                break;
            }

            if (!foundPassword)
            {
                throw new PdfDocumentEncryptedException("The document was encrypted and none of the provided passwords were the user or owner password.",
                                                        encryptionDictionary);
            }
        }
Exemplo n.º 11
0
        /// <summary>
        /// Writes a valid single section cross-reference (xref) table plus trailer dictionary to the output for the set of object offsets.
        /// </summary>
        /// <param name="objectOffsets">The byte offset from the start of the document for each object in the document.</param>
        /// <param name="catalogToken">The object representing the catalog dictionary which is referenced from the trailer dictionary.</param>
        /// <param name="outputStream">The output stream to write to.</param>
        /// <param name="documentInformationReference">The object reference for the document information dictionary if present.</param>
        internal static void WriteCrossReferenceTable(IReadOnlyDictionary <IndirectReference, long> objectOffsets,
                                                      IndirectReference catalogToken,
                                                      Stream outputStream,
                                                      IndirectReference?documentInformationReference)
        {
            if (objectOffsets.Count == 0)
            {
                throw new InvalidOperationException("Could not write empty cross reference table.");
            }

            WriteLineBreak(outputStream);
            var position = outputStream.Position;

            outputStream.Write(Xref, 0, Xref.Length);
            WriteLineBreak(outputStream);

            var sets = new List <XrefSeries>();

            var orderedList = objectOffsets.OrderBy(x => x.Key.ObjectNumber).ToList();

            long firstObjectNumber = 0;
            long currentObjNum     = 0;
            var  items             = new List <XrefSeries.OffsetAndGeneration>
            {
                // Zero entry
                null
            };

            foreach (var item in orderedList)
            {
                var step = item.Key.ObjectNumber - currentObjNum;
                if (step == 1)
                {
                    currentObjNum = item.Key.ObjectNumber;
                    items.Add(new XrefSeries.OffsetAndGeneration(item.Value, item.Key.Generation));
                }
                else
                {
                    sets.Add(new XrefSeries(firstObjectNumber, items));
                    items = new List <XrefSeries.OffsetAndGeneration>
                    {
                        new XrefSeries.OffsetAndGeneration(item.Value, item.Key.Generation)
                    };

                    currentObjNum     = item.Key.ObjectNumber;
                    firstObjectNumber = item.Key.ObjectNumber;
                }
            }

            if (items.Count > 0)
            {
                sets.Add(new XrefSeries(firstObjectNumber, items));
            }

            foreach (var series in sets)
            {
                WriteLong(series.First, outputStream);
                WriteWhitespace(outputStream);

                WriteLong(series.Offsets.Count, outputStream);

                WriteWhitespace(outputStream);
                WriteLineBreak(outputStream);

                foreach (var offset in series.Offsets)
                {
                    if (offset != null)
                    {
                        /*
                         * nnnnnnnnnn ggggg n eol
                         * where:
                         * nnnnnnnnnn is a 10-digit byte offset
                         * ggggg is a 5-digit generation number
                         * n is a literal keyword identifying this as an in-use entry
                         * eol is a 2-character end-of-line sequence ('\r\n' or ' \n')
                         */
                        var paddedOffset = OtherEncodings.StringAsLatin1Bytes(offset.Offset.ToString("D10", CultureInfo.InvariantCulture));
                        outputStream.Write(paddedOffset, 0, paddedOffset.Length);

                        WriteWhitespace(outputStream);

                        var generation = OtherEncodings.StringAsLatin1Bytes(offset.Generation.ToString("D5", CultureInfo.InvariantCulture));
                        outputStream.Write(generation, 0, generation.Length);

                        WriteWhitespace(outputStream);

                        outputStream.WriteByte(InUseEntry);

                        WriteWhitespace(outputStream);
                        WriteLineBreak(outputStream);
                    }
                    else
                    {
                        WriteFirstXrefEmptyEntry(outputStream);
                    }
                }
            }

            outputStream.Write(Trailer, 0, Trailer.Length);
            WriteLineBreak(outputStream);

            var identifier = new ArrayToken(new IToken[]
            {
                new HexToken(Guid.NewGuid().ToString("N").ToCharArray()),
                new HexToken(Guid.NewGuid().ToString("N").ToCharArray())
            });

            var trailerDictionaryData = new Dictionary <NameToken, IToken>
            {
                // 1 for the free entry.
                { NameToken.Size, new NumericToken(objectOffsets.Count + 1) },
                { NameToken.Root, new IndirectReferenceToken(catalogToken) },
                { NameToken.Id, identifier }
            };

            if (documentInformationReference.HasValue)
            {
                trailerDictionaryData[NameToken.Info] = new IndirectReferenceToken(documentInformationReference.Value);
            }

            var trailerDictionary = new DictionaryToken(trailerDictionaryData);

            WriteDictionary(trailerDictionary, outputStream);
            WriteLineBreak(outputStream);

            outputStream.Write(StartXref, 0, StartXref.Length);
            WriteLineBreak(outputStream);

            WriteLong(position, outputStream);
            WriteLineBreak(outputStream);

            // Complete!
            outputStream.Write(Eof, 0, Eof.Length);
        }
Exemplo n.º 12
0
        public COSArray Parse(IRandomAccessRead reader, CosBaseParser baseParser, CosObjectPool pool)
        {
            ReadHelper.ReadExpectedChar(reader, '[');
            var     po = new COSArray();
            CosBase pbo;

            ReadHelper.SkipSpaces(reader);
            int i;

            while (((i = reader.Peek()) > 0) && ((char)i != ']'))
            {
                pbo = baseParser.Parse(reader, pool);
                if (pbo is CosObject)
                {
                    // We have to check if the expected values are there or not PDFBOX-385
                    if (po.get(po.size() - 1) is CosInt)
                    {
                        var genNumber = (CosInt)po.remove(po.size() - 1);
                        if (po.get(po.size() - 1) is CosInt)
                        {
                            var          number = (CosInt)po.remove(po.size() - 1);
                            CosObjectKey key    = new CosObjectKey(number.AsLong(), genNumber.AsInt());
                            pbo = pool.Get(key);
                        }
                        else
                        {
                            // the object reference is somehow wrong
                            pbo = null;
                        }
                    }
                    else
                    {
                        pbo = null;
                    }
                }
                if (pbo != null)
                {
                    po.add(pbo);
                }
                else
                {
                    //it could be a bad object in the array which is just skipped
                    // LOG.warn("Corrupt object reference at offset " + seqSource.getPosition());

                    // This could also be an "endobj" or "endstream" which means we can assume that
                    // the array has ended.
                    string isThisTheEnd = ReadHelper.ReadString(reader);
                    reader.Unread(OtherEncodings.StringAsLatin1Bytes(isThisTheEnd));
                    if (string.Equals(isThisTheEnd, "endobj") || string.Equals(isThisTheEnd, "endstream"))
                    {
                        return(po);
                    }
                }

                ReadHelper.SkipSpaces(reader);
            }
            // read ']'
            reader.Read();
            ReadHelper.SkipSpaces(reader);
            return(po);
        }
Exemplo n.º 13
0
        public void BytesNullReturnsNullString()
        {
            var result = OtherEncodings.BytesAsLatin1String(null);

            Assert.Null(result);
        }
Exemplo n.º 14
0
        public void StringNullReturnsNullBytes()
        {
            var result = OtherEncodings.StringAsLatin1Bytes(null);

            Assert.Null(result);
        }
Exemplo n.º 15
0
        /// <summary>
        /// Writes a valid single section cross-reference (xref) table plus trailer dictionary to the output for the set of object offsets.
        /// </summary>
        /// <param name="objectOffsets">The byte offset from the start of the document for each object in the document.</param>
        /// <param name="catalogToken">The object representing the catalog dictionary which is referenced from the trailer dictionary.</param>
        /// <param name="outputStream">The output stream to write to.</param>
        /// <param name="documentInformationReference">The object reference for the document information dictionary if present.</param>
        internal static void WriteCrossReferenceTable(IReadOnlyDictionary <IndirectReference, long> objectOffsets,
                                                      ObjectToken catalogToken,
                                                      Stream outputStream,
                                                      IndirectReference?documentInformationReference)
        {
            if (objectOffsets.Count == 0)
            {
                throw new InvalidOperationException("Could not write empty cross reference table.");
            }

            WriteLineBreak(outputStream);
            var position = outputStream.Position;

            outputStream.Write(Xref, 0, Xref.Length);
            WriteLineBreak(outputStream);

            var min = objectOffsets.Min(x => x.Key.ObjectNumber);
            var max = objectOffsets.Max(x => x.Key.ObjectNumber);

            if (max - min != objectOffsets.Count - 1)
            {
                throw new NotSupportedException("Object numbers must form a contiguous range");
            }

            WriteLong(0, outputStream);
            WriteWhitespace(outputStream);
            // 1 extra for the free entry.
            WriteLong(objectOffsets.Count + 1, outputStream);
            WriteWhitespace(outputStream);
            WriteLineBreak(outputStream);

            WriteFirstXrefEmptyEntry(outputStream);

            foreach (var keyValuePair in objectOffsets.OrderBy(x => x.Key.ObjectNumber))
            {
                /*
                 * nnnnnnnnnn ggggg n eol
                 * where:
                 * nnnnnnnnnn is a 10-digit byte offset
                 * ggggg is a 5-digit generation number
                 * n is a literal keyword identifying this as an in-use entry
                 * eol is a 2-character end-of-line sequence ('\r\n' or ' \n')
                 */
                var paddedOffset = OtherEncodings.StringAsLatin1Bytes(keyValuePair.Value.ToString("D10"));
                outputStream.Write(paddedOffset, 0, paddedOffset.Length);

                WriteWhitespace(outputStream);

                var generation = OtherEncodings.StringAsLatin1Bytes(keyValuePair.Key.Generation.ToString("D5"));
                outputStream.Write(generation, 0, generation.Length);

                WriteWhitespace(outputStream);

                outputStream.WriteByte(InUseEntry);

                WriteWhitespace(outputStream);
                WriteLineBreak(outputStream);
            }

            outputStream.Write(Trailer, 0, Trailer.Length);
            WriteLineBreak(outputStream);

            var identifier = new ArrayToken(new IToken[]
            {
                new HexToken(Guid.NewGuid().ToString("N").ToCharArray()),
                new HexToken(Guid.NewGuid().ToString("N").ToCharArray())
            });

            var trailerDictionaryData = new Dictionary <NameToken, IToken>
            {
                // 1 for the free entry.
                { NameToken.Size, new NumericToken(objectOffsets.Count + 1) },
                { NameToken.Root, new IndirectReferenceToken(catalogToken.Number) },
                { NameToken.Id, identifier }
            };

            if (documentInformationReference.HasValue)
            {
                trailerDictionaryData[NameToken.Info] = new IndirectReferenceToken(documentInformationReference.Value);
            }

            var trailerDictionary = new DictionaryToken(trailerDictionaryData);

            WriteDictionary(trailerDictionary, outputStream);
            WriteLineBreak(outputStream);

            outputStream.Write(StartXref, 0, StartXref.Length);
            WriteLineBreak(outputStream);

            WriteLong(position, outputStream);
            WriteLineBreak(outputStream);

            // Complete!
            outputStream.Write(Eof, 0, Eof.Length);
        }
Exemplo n.º 16
0
        private IToken DecryptInternal(IndirectReference reference, IToken token)
        {
            switch (token)
            {
            case StreamToken stream:
            {
                if (cryptHandler?.StreamDictionary?.IsIdentity == true ||
                    cryptHandler?.StreamDictionary?.Name == CryptDictionary.Method.None)
                {
                    // TODO: No idea if this is right.
                    return(token);
                }

                if (stream.StreamDictionary.TryGet(NameToken.Type, out NameToken typeName))
                {
                    if (NameToken.Xref.Equals(typeName))
                    {
                        return(token);
                    }

                    if (!encryptionDictionary.EncryptMetadata && NameToken.Metadata.Equals(typeName))
                    {
                        return(token);
                    }

                    // TODO: check unencrypted metadata
                }

                var streamDictionary = (DictionaryToken)DecryptInternal(reference, stream.StreamDictionary);

                var decrypted = DecryptData(stream.Data.ToArray(), reference);

                token = new StreamToken(streamDictionary, decrypted);

                break;
            }

            case StringToken stringToken:
            {
                if (cryptHandler?.StringDictionary?.IsIdentity == true ||
                    cryptHandler?.StringDictionary?.Name == CryptDictionary.Method.None)
                {
                    // TODO: No idea if this is right.
                    return(token);
                }

                var data = OtherEncodings.StringAsLatin1Bytes(stringToken.Data);

                var decrypted = DecryptData(data, reference);

                token = new StringToken(OtherEncodings.BytesAsLatin1String(decrypted));

                break;
            }

            case HexToken hexToken:
            {
                var data = hexToken.Bytes.ToArray();

                var decrypted = DecryptData(data, reference);

                token = new HexToken(Hex.GetString(decrypted).ToCharArray());

                break;
            }

            case DictionaryToken dictionary:
            {
                // PDFBOX-2936: avoid orphan /CF dictionaries found in US govt "I-" files
                if (dictionary.TryGet(NameToken.Cf, out _))
                {
                    return(token);
                }

                var isSignatureDictionary = dictionary.TryGet(NameToken.Type, out NameToken typeName) &&
                                            (typeName.Equals(NameToken.Sig) || typeName.Equals(NameToken.DocTimeStamp));

                foreach (var keyValuePair in dictionary.Data)
                {
                    if (isSignatureDictionary && keyValuePair.Key == NameToken.Contents.Data)
                    {
                        continue;
                    }

                    if (keyValuePair.Value is StringToken || keyValuePair.Value is ArrayToken || keyValuePair.Value is DictionaryToken)
                    {
                        var inner = DecryptInternal(reference, keyValuePair.Value);
                        dictionary = dictionary.With(keyValuePair.Key, inner);
                    }
                }

                token = dictionary;

                break;
            }

            case ArrayToken array:
            {
                var result = new IToken[array.Length];

                for (var i = 0; i < array.Length; i++)
                {
                    result[i] = DecryptInternal(reference, array.Data[i]);
                }

                token = new ArrayToken(result);

                break;
            }
            }

            return(token);
        }
Exemplo n.º 17
0
        private static void WriteLong(long value, Stream outputStream)
        {
            var bytes = OtherEncodings.StringAsLatin1Bytes(value.ToString("G", CultureInfo.InvariantCulture));

            outputStream.Write(bytes, 0, bytes.Length);
        }
Exemplo n.º 18
0
        public EncryptionHandler(EncryptionDictionary encryptionDictionary, TrailerDictionary trailerDictionary, string password)
        {
            this.encryptionDictionary = encryptionDictionary;

            var documentIdBytes = trailerDictionary.Identifier != null && trailerDictionary.Identifier.Count == 2 ?
                                  OtherEncodings.StringAsLatin1Bytes(trailerDictionary.Identifier[0])
                : EmptyArray <byte> .Instance;

            password = password ?? string.Empty;

            if (encryptionDictionary == null)
            {
                return;
            }

            useAes = false;

            if (encryptionDictionary.EncryptionAlgorithmCode == EncryptionAlgorithmCode.SecurityHandlerInDocument ||
                encryptionDictionary.EncryptionAlgorithmCode == EncryptionAlgorithmCode.SecurityHandlerInDocument256)
            {
                if (!encryptionDictionary.TryGetCryptHandler(out var cryptHandlerLocal))
                {
                    throw new PdfDocumentEncryptedException("Document encrypted with security handler in document but no crypt dictionary found.", encryptionDictionary);
                }

                cryptHandler = cryptHandlerLocal;

                useAes = cryptHandlerLocal?.StreamDictionary?.Name == CryptDictionary.Method.AesV2 ||
                         cryptHandlerLocal?.StreamDictionary?.Name == CryptDictionary.Method.AesV3;
            }

            var charset = OtherEncodings.Iso88591;

            if (encryptionDictionary.Revision == 5 || encryptionDictionary.Revision == 6)
            {
                // ReSharper disable once RedundantAssignment
                charset = Encoding.UTF8;
            }

            var passwordBytes = charset.GetBytes(password);

            byte[] decryptionPasswordBytes;

            var length = encryptionDictionary.EncryptionAlgorithmCode == EncryptionAlgorithmCode.Rc4OrAes40BitKey
                ? 5
                : encryptionDictionary.KeyLength.GetValueOrDefault() / 8;

            var isUserPassword = false;

            if (IsOwnerPassword(passwordBytes, encryptionDictionary, length, documentIdBytes, out var userPassBytes))
            {
                if (encryptionDictionary.Revision == 5 || encryptionDictionary.Revision == 6)
                {
                    decryptionPasswordBytes = passwordBytes;
                }
                else
                {
                    decryptionPasswordBytes = userPassBytes;
                }
            }
            else if (IsUserPassword(passwordBytes, encryptionDictionary, length, documentIdBytes))
            {
                decryptionPasswordBytes = passwordBytes;
                isUserPassword          = true;
            }
            else
            {
                throw new PdfDocumentEncryptedException("The document was encrypted and the provided password was neither the user or owner password.", encryptionDictionary);
            }

            encryptionKey = CalculateEncryptionKey(decryptionPasswordBytes, encryptionDictionary,
                                                   length,
                                                   documentIdBytes,
                                                   isUserPassword);
        }
Exemplo n.º 19
0
        public IReadOnlyDictionary <CosObjectKey, long> GetObjectLocations()
        {
            if (objectLocations != null)
            {
                return(objectLocations);
            }

            var lastEndOfFile = GetLastEndOfFileMarker();

            var results = new Dictionary <CosObjectKey, long>();

            var originPosition = reader.GetPosition();

            long currentOffset    = MinimumSearchOffset;
            long lastObjectId     = long.MinValue;
            int  lastGenerationId = int.MinValue;
            long lastObjOffset    = long.MinValue;

            byte[] objString    = OtherEncodings.StringAsLatin1Bytes(" obj");
            byte[] endobjString = OtherEncodings.StringAsLatin1Bytes("endobj");

            bool endobjFound = false;

            do
            {
                reader.Seek(currentOffset);
                if (ReadHelper.IsString(reader, objString))
                {
                    long tempOffset = currentOffset - 1;
                    reader.Seek(tempOffset);
                    int generationId = reader.Peek();

                    // is the next char a digit?
                    if (ReadHelper.IsDigit(generationId))
                    {
                        generationId -= 48;
                        tempOffset--;
                        reader.Seek(tempOffset);
                        if (ReadHelper.IsSpace(reader))
                        {
                            while (tempOffset > MinimumSearchOffset && ReadHelper.IsSpace(reader))
                            {
                                reader.Seek(--tempOffset);
                            }

                            bool objectIdFound = false;
                            while (tempOffset > MinimumSearchOffset && ReadHelper.IsDigit(reader))
                            {
                                reader.Seek(--tempOffset);
                                objectIdFound = true;
                            }

                            if (objectIdFound)
                            {
                                reader.Read();
                                long objectId = ObjectHelper.ReadObjectNumber(reader);
                                if (lastObjOffset > 0)
                                {
                                    // add the former object ID only if there was a subsequent object ID
                                    results[new CosObjectKey(lastObjectId, lastGenerationId)] = lastObjOffset;
                                }
                                lastObjectId     = objectId;
                                lastGenerationId = generationId;
                                lastObjOffset    = tempOffset + 1;
                                currentOffset   += objString.Length - 1;
                                endobjFound      = false;
                            }
                        }
                    }
                }
                else if (ReadHelper.IsString(reader, "endobj"))
                {
                    endobjFound    = true;
                    currentOffset += endobjString.Length - 1;
                }
                currentOffset++;
            } while (currentOffset < lastEndOfFile && !reader.IsEof());
            if ((lastEndOfFile < long.MaxValue || endobjFound) && lastObjOffset > 0)
            {
                // if the pdf wasn't cut off in the middle or if the last object ends with a "endobj" marker
                // the last object id has to be added here so that it can't get lost as there isn't any subsequent object id
                results[new CosObjectKey(lastObjectId, lastGenerationId)] = lastObjOffset;
            }

            // reestablish origin position
            reader.Seek(originPosition);

            objectLocations = results;

            return(objectLocations);
        }
Exemplo n.º 20
0
        public CosBase Parse(IRandomAccessRead reader, CosObjectPool pool)
        {
            CosBase retval = null;

            ReadHelper.SkipSpaces(reader);
            int nextByte = reader.Peek();

            if (nextByte == -1)
            {
                return(null);
            }

            char c = (char)nextByte;

            switch (c)
            {
            case '<':
            {
                // pull off first left bracket
                int leftBracket = reader.Read();
                // check for second left bracket
                c = (char)reader.Peek();
                reader.Unread(leftBracket);
                if (c == '<')
                {
                    retval = dictionaryParser.Parse(reader, this, pool);
                    ReadHelper.SkipSpaces(reader);
                }
                else
                {
                    retval = stringParser.Parse(reader);
                }
                break;
            }

            case '[':
            {
                // array
                retval = arrayParser.Parse(reader, this, pool);
                break;
            }

            case '(':
                retval = stringParser.Parse(reader);
                break;

            case '/':
                // name
                retval = nameParser.Parse(reader);
                break;

            case 'n':
            {
                // null
                ReadHelper.ReadExpectedString(reader, "null");
                retval = CosNull.Null;
                break;
            }

            case 't':
            {
                string truestring = OtherEncodings.BytesAsLatin1String(reader.ReadFully(4));
                if (truestring.Equals("true"))
                {
                    retval = PdfBoolean.True;
                }
                else
                {
                    throw new IOException("expected true actual='" + truestring + "' " + reader +
                                          "' at offset " + reader.GetPosition());
                }
                break;
            }

            case 'f':
            {
                string falsestring = OtherEncodings.BytesAsLatin1String(reader.ReadFully(5));
                if (falsestring.Equals("false"))
                {
                    retval = PdfBoolean.False;
                }
                else
                {
                    throw new IOException("expected false actual='" + falsestring + "' " + reader +
                                          "' at offset " + reader.GetPosition());
                }
                break;
            }

            case 'R':
                reader.Read();
                retval = new CosObject(null);
                break;

            default:

                if (char.IsDigit(c) || c == '-' || c == '+' || c == '.')
                {
                    StringBuilder buf = new StringBuilder();
                    int           ic  = reader.Read();
                    c = (char)ic;
                    while (char.IsDigit(c) ||
                           c == '-' ||
                           c == '+' ||
                           c == '.' ||
                           c == 'E' ||
                           c == 'e')
                    {
                        buf.Append(c);
                        ic = reader.Read();
                        c  = (char)ic;
                    }
                    if (ic != -1)
                    {
                        reader.Unread(ic);
                    }
                    retval = CosNumberFactory.get(buf.ToString()) as CosBase;
                }
                else
                {
                    //This is not suppose to happen, but we will allow for it
                    //so we are more compatible with POS writers that don't
                    //follow the spec
                    string badstring = ReadHelper.ReadString(reader);
                    if (badstring == string.Empty)
                    {
                        int peek = reader.Peek();
                        // we can end up in an infinite loop otherwise
                        throw new IOException("Unknown dir object c='" + c +
                                              "' cInt=" + (int)c + " peek='" + (char)peek
                                              + "' peekInt=" + peek + " at offset " + reader.GetPosition());
                    }

                    // if it's an endstream/endobj, we want to put it back so the caller will see it
                    if (string.Equals("endobj", badstring) || string.Equals("endstream", badstring))
                    {
                        reader.Unread(OtherEncodings.StringAsLatin1Bytes(badstring));
                    }
                }
                break;
            }
            return(retval);
        }