Exemple #1
0
        public TrailerPart ParseTrailer(PdfStreamReader streamReader, IPdf pdf)
        {
            var header = streamReader.ReadLine();

            if (header != "trailer")
            {
                throw new ArgumentOutOfRangeException(nameof(streamReader), "First line in Trailer Content is not \"trailer\"");
            }

            var trailerDictionary = this._pdfReader.ReadObject(streamReader, pdf);

            if (!(trailerDictionary is PdfDictionary))
            {
                throw new InvalidDataException("Trailer dictionary content was not a dictionary.");
            }

            var line = streamReader.ReadLine();
            var foundCrossReference = false;

            if (line == "startxref")
            {
                foundCrossReference = true;
            }

            if (!foundCrossReference)
            {
                throw new InvalidDataException("Missing startxref line");
            }

            var crossReferenceLine = streamReader.ReadLine();

            if (!long.TryParse(crossReferenceLine, out var crossReferenceOffset))
            {
                throw new InvalidDataException("Cross Reference Offset value is not a parseable number");
            }

            line = streamReader.ReadLine();

            if (line == null ||
                line == "%%EOF")
            {
                var result = new TrailerPart((PdfDictionary)trailerDictionary, crossReferenceOffset);

                return(result);
            }

            throw new InvalidDataException("Trailer content is invalid, the last 2 lines should be startxref and a number and optionally a 3rd line containing %%EOF");
        }
        public VersionPart ReadPart(PdfStreamReader streamReader, IPdf pdf)
        {
            var line = streamReader.ReadLine();

            if (line == null)
            {
                throw new ArgumentOutOfRangeException(nameof(streamReader), "Unexpected end of stream");
            }
            else if (line.StartsWith(PdfVersionPrefix))
            {
                var result = this.GetVersionPart(line);
                return(result);
            }
            else
            {
                throw new ArgumentOutOfRangeException(nameof(streamReader), line, "Expected content at current position was not a version");
            }
        }
        public CrossReferencePart ReadPart(PdfStreamReader streamReader, IPdf pdf)
        {
            if (pdf == null)
            {
                throw new ArgumentNullException(nameof(pdf));
            }

            if (pdf.Trailer == null ||
                pdf.Trailer.StartCrossReference == 0)
            {
                return(null);
            }

            var originalPosition = streamReader.Position;

            try
            {
                streamReader.Seek(pdf.Trailer.StartCrossReference, SeekOrigin.Begin);
                var line = streamReader.ReadLine();

                if (line != "xref")
                {
                    throw new ArgumentOutOfRangeException(nameof(streamReader), line, "Invalid Cross Reference Header");
                }

                var subsections = new List <CrossReferencePartSubSection>();
                while (line == "xref")
                {
                    subsections.Add(_subSectionReader.ReadPart(streamReader, pdf));
                    line = streamReader.ReadLine();
                }

                var result = new CrossReferencePart
                {
                    Sections = subsections.ToArray()
                };

                return(result);
            }
            finally
            {
                streamReader.Seek(originalPosition, SeekOrigin.Begin);
            }
        }
        public CrossReferencePartSubSectionEntry ReadPart(PdfStreamReader streamReader, IPdf pdf)
        {
            var line = streamReader.ReadLine();

            if (line.Length != 18)
            {
                throw new ArgumentOutOfRangeException(nameof(streamReader), line, "Line is not 18 characters long.");
            }

            var fields = line.Split(' ');

            if (fields.Length != 3)
            {
                throw new ArgumentOutOfRangeException(nameof(streamReader), line, "Line does not have 3 fields.");
            }

            if (!long.TryParse(fields[0], out var offset))
            {
                throw new ArgumentOutOfRangeException(nameof(streamReader), line, "Invalid offset field. Not a valid number.");
            }

            if (!int.TryParse(fields[1], out var generation))
            {
                throw new ArgumentOutOfRangeException(nameof(streamReader), line, "Invalid generation field. Not a valid number.");
            }

            if (fields[2] != "f" &&
                fields[2] != "n")
            {
                throw new ArgumentOutOfRangeException(nameof(streamReader), line, "Invalid in use flag. Not 'n' or 'f'.");
            }

            var inUseFlag = (CrossReferenceEntryFlag)fields[2][0];
            var result    = new CrossReferencePartSubSectionEntry
            {
                Generation = generation,
                InUse      = inUseFlag,
                Offset     = offset
            };

            return(result);
        }
Exemple #5
0
        public CrossReferencePartSubSection ReadPart(PdfStreamReader streamReader, IPdf pdf)
        {
            var line = streamReader.ReadLine();

            var fields = line.Split(' ');

            if (fields.Length != 2)
            {
                throw new ArgumentOutOfRangeException(nameof(streamReader), line, "Invalid field count for subsection counts.");
            }

            if (!int.TryParse(fields[0], out var startingObject))
            {
                throw new ArgumentOutOfRangeException(nameof(streamReader), line, "Invalid starting object field. Not a valid number.");
            }

            if (!int.TryParse(fields[1], out var objectCount))
            {
                throw new ArgumentOutOfRangeException(nameof(streamReader), line, "Invalid object count. Not a valid number.");
            }

            var entries = new CrossReferencePartSubSectionEntry[objectCount];

            for (var i = 0; i < entries.Length; i++)
            {
                var entry = this._partReader.ReadPart(streamReader, pdf);
                entry.ObjectNumber = startingObject + i;
                entries[i]         = entry;
            }

            var result = new CrossReferencePartSubSection
            {
                Entries        = entries,
                StartingObject = startingObject
            };

            return(result);
        }
Exemple #6
0
        public IPdf Create(Stream stream, PdfOptions pdfOptions)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            if (!stream.CanSeek)
            {
                throw new InvalidDataException("The stream must be seekable");
            }

            if (stream.Length == 0)
            {
                throw new InvalidDataException("Stream is 0 bytes.");
            }

            stream.Seek(0, SeekOrigin.Begin);
            var streamReader = new PdfStreamReader(stream, pdfOptions.ReadBlockSize);

            var pdf = new DefaultPdf(this._pdfReader, streamReader)
            {
                Options = pdfOptions
            };

            pdf.Version = this._versionPartReader.ReadPart(streamReader, pdf);
            pdf.Trailer = this._trailerPartReader.ReadPart(streamReader, pdf);

            if (pdf.Version >= new Version(1, 4))
            {
                //TODO: spec section 7.5.2 states that if the version in the first line is >= 1.4, use the version in the trailer if it exists
            }

            pdf.CrossReferenceTable = this._crossReferencePartReader.ReadPart(streamReader, pdf);
            if (pdf.Trailer.Encrypt != null)
            {
                PdfDictionary encryptDictionary;
                if (pdf.Trailer.Encrypt is PdfReference o)
                {
                    var readObject = pdf.ReadIndirectObject(o);
                    if (readObject == null)
                    {
                        throw new InvalidDataException("Missing encrypt object");
                    }
                    if (!(readObject.InnerObject is PdfDictionary))
                    {
                        throw new InvalidDataException("Encrypt object is not a pdf dictionary");
                    }

                    encryptDictionary = (PdfDictionary)readObject.InnerObject;
                }
                else if (pdf.Trailer.Encrypt is PdfDictionary)
                {
                    encryptDictionary = (PdfDictionary)pdf.Trailer.Encrypt;
                }
                else
                {
                    throw new InvalidDataException("Invalid encrypt dictionary entry");
                }

                pdf.EncryptionDictionary = new EncryptionDictionary(encryptDictionary);
            }

            return(pdf);
        }
Exemple #7
0
        public TrailerPart ReadPart(PdfStreamReader streamReader, IPdf pdf)
        {
            var currentPosition = streamReader.Position;

            try
            {
                var trailerBlockSize = 512;
                var block            = new byte[trailerBlockSize];
                int trailerStart;

                //we'll read x number of bytes at a time with a 7 byte overlap to account for the word trailer.
                //length = 1500

                streamReader.Seek(-trailerBlockSize, SeekOrigin.End);
                string content;
                var    foundTrailer = false;
                do
                {
                    var loopPosition = streamReader.Position;

                    streamReader.Read(block, 0, trailerBlockSize);

                    content = Encoding.ASCII.GetString(block);

                    if ((trailerStart = content.IndexOf("trailer")) >= 0)
                    {
                        streamReader.Seek(loopPosition + trailerStart, SeekOrigin.Begin);

                        foundTrailer = true;
                        break;
                    }

                    content = null;

                    if (loopPosition == 0)
                    {
                        //we were at the beginning of the stream meaning we can't go back any more
                        break;
                    }

                    if (streamReader.Position > trailerBlockSize)
                    {
                        streamReader.Seek((trailerBlockSize * -2) + 7, SeekOrigin.Current); //7 byte overlap
                    }
                    else
                    {
                        streamReader.Seek(0, SeekOrigin.Begin);
                    }
                } while (streamReader.Position - trailerBlockSize > 0); //make sure we don't go before the beginning of the stream for files that have no trailer

                if (foundTrailer)
                {
                    var result = ParseTrailer(streamReader, pdf);
                    return(result);
                }

                return(null);
            }
            finally
            {
                // go back to where we were.
                streamReader.Seek(currentPosition, SeekOrigin.Begin);
            }
        }