public PdfDocumentReader(Stream stream, bool leaveOpen)
        {
            if (stream is null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            try {
                if (!stream.CanSeek)
                {
                    stream    = _copyStreamToMemory(stream, leaveOpen);
                    leaveOpen = false;
                }

                this._stream           = stream;
                this._leaveOpen        = leaveOpen;
                this._rootReference    = null;
                this._encryptReference = null;
                this._infoReference    = null;

                _fileVersion = _readHeader();

                int pos    = _readStartXref();
                var reader = new PdfStreamReader(this, stream, pos);

                try {
                    var token = reader.ReadToken();
                    switch (token.Type)
                    {
                    case PdfValueType.Xref:
                        _readXrefTable(reader);
                        break;

                    case PdfValueType.Integer:
                        _readXrefObject(pos, reader, token);
                        break;

                    default:
                        throw new PdfExceptionReader("Can't locate table.");
                    }
                }
                catch (Exception err) {
                    throw new PdfExceptionReader("Error reading xref table.", err);
                }
            }
            catch (Exception err) {
                if (!leaveOpen)
                {
                    stream.Close();
                }

                throw new PdfExceptionReader("Can't open PDF stream.", err);
            }
        }
예제 #2
0
        public void ReturnsCorrect(string input, string expected, int expectedPosition)
        {
            var bytes = Encoding.ASCII.GetBytes(input);

            using (var memoryStream = new MemoryStream(bytes))
            {
                var reader = new PdfStreamReader(memoryStream, 512);
                var actual = reader.ReadLine();
                Assert.Equal(expected, actual);
                Assert.Equal(expectedPosition, reader.Position);
            }
        }
예제 #3
0
        public void Valid(string value, int backOff)
        {
            PdfObject actual;

            using (var ms = new MemoryStream(Encoding.ASCII.GetBytes(value)))
            {
                var streamReader = new PdfStreamReader(ms, 512);
                actual = this._reader.ReadObject(streamReader, this._pdf);
                Assert.Equal(value.Length - backOff, streamReader.Position);
            }

            Assert.IsType <PdfNull>(actual);
        }
예제 #4
0
        public void Valid(string value, string expected, int readBack)
        {
            PdfString actual;

            using (var ms = new MemoryStream(Encoding.ASCII.GetBytes(value)))
            {
                var streamReader = new PdfStreamReader(ms, 512);
                actual = this._reader.ReadString(streamReader);
                Assert.Equal(value.Length - readBack, streamReader.Position);
            }

            Assert.Equal(expected, actual.Value);
        }
예제 #5
0
        public void Number()
        {
            var raw = "123";

            using (var ms = new MemoryStream(Encoding.ASCII.GetBytes(raw)))
            {
                var streamReader = new PdfStreamReader(ms, 512);
                var actual       = this._reader.ReadObject(streamReader, this._pdf);

                Assert.IsType <PdfNumber>(actual);
                Assert.Equal(123.00M, ((PdfNumber)actual).Value);
            }
        }
예제 #6
0
        public void Name()
        {
            var raw = "/NAME";

            using (var ms = new MemoryStream(Encoding.ASCII.GetBytes(raw)))
            {
                var streamReader = new PdfStreamReader(ms, 512);
                var actual       = this._reader.ReadObject(streamReader, this._pdf);

                Assert.IsType <PdfName>(actual);
                Assert.Equal("NAME", ((PdfName)actual).Value);
            }
        }
예제 #7
0
        public void Comment()
        {
            var raw = "%TEST YOU";

            using (var ms = new MemoryStream(Encoding.ASCII.GetBytes(raw)))
            {
                var streamReader = new PdfStreamReader(ms, 512);
                var actual       = this._reader.ReadObject(streamReader, this._pdf);

                Assert.IsType <PdfComment>(actual);
                Assert.Equal("TEST YOU", ((PdfComment)actual).Value);
            }
        }
예제 #8
0
        public void Boolean_False()
        {
            var raw = "false";

            using (var ms = new MemoryStream(Encoding.ASCII.GetBytes(raw)))
            {
                var streamReader = new PdfStreamReader(ms, 512);
                var actual       = this._reader.ReadObject(streamReader, this._pdf);

                Assert.IsType <PdfBoolean>(actual);
                Assert.False(((PdfBoolean)actual).Value);
            }
        }
예제 #9
0
        public void Valid(string value, decimal expected)
        {
            PdfNumber actual;

            using (var ms = new MemoryStream(Encoding.ASCII.GetBytes(value)))
            {
                var streamReader = new PdfStreamReader(ms, 512);
                actual = this._reader.ReadNumber(streamReader);
                Assert.Equal(value.Length - 5, streamReader.Position);
            }

            Assert.Equal(expected, actual.Value);
        }
예제 #10
0
        public void Reference()
        {
            var raw = "9 5 R";

            using (var ms = new MemoryStream(Encoding.ASCII.GetBytes(raw)))
            {
                var streamReader = new PdfStreamReader(ms, 512);
                var actual       = this._reader.ReadObject(streamReader, this._pdf);

                Assert.IsType <PdfReference>(actual);
                Assert.Equal(9, ((PdfReference)actual).ObjectNumber);
                Assert.Equal(5, ((PdfReference)actual).Generation);
            }
        }
예제 #11
0
        public void Valid()
        {
            var raw = "<<\r\n" +
                      "/DecodeParms <<\r\n" +
                      "/Columns 5\r\n" +
                      "/Predictor 12\r\n" +
                      ">>\r\n" +
                      "/Filter /FlateDecode\r\n" +
                      "/ID [<9597C618BC90AFA4A078CA72B2DD061C> <48726007F483D547A8BEFF6E9CDA072F>]\r\n" +
                      "/Info 9 0 R\r\n" +
                      "/Length 137\r\n" +
                      "/Root 1 0 R\r\n" +
                      "/Size 126989\r\n" +
                      "/Type /XRef\r\n" +
                      "/W [1 3 1]\r\n" +
                      "/Index [124332 848]\r\n" +
                      "/Encrypt 126988 0 R\r\n" +
                      ">>\r\n";
            PdfObject actual;

            using (var ms = new MemoryStream(Encoding.ASCII.GetBytes(raw)))
            {
                var streamReader = new PdfStreamReader(ms, 512);
                actual = _reader.ReadObject(streamReader, this._pdf);
            }

            Assert.IsType <PdfDictionary>(actual);
            var decodeParamsDictionary = new PdfDictionary();

            decodeParamsDictionary.Entries["Columns"]   = new PdfNumber(5);
            decodeParamsDictionary.Entries["Predictor"] = new PdfNumber(12);

            var expected = new PdfDictionary();

            expected.Entries["DecodeParms"] = decodeParamsDictionary;
            expected.Entries["Filter"]      = new PdfName("FlateDecode");
            expected.Entries["ID"]          = new PdfArray(new PdfBinaryString("9597C618BC90AFA4A078CA72B2DD061C".GetBytesFromHexString()),
                                                           new PdfBinaryString("48726007F483D547A8BEFF6E9CDA072F".GetBytesFromHexString()));
            expected.Entries["Info"]   = null; //hmm?
            expected.Entries["Length"] = new PdfNumber(137);
            expected.Entries["Root"]   = null; //hmm?
            expected.Entries["Size"]   = null; //hmm?
            expected.Entries["Type"]   = new PdfName("XRef");
            expected.Entries["W"]      = new PdfArray(new PdfNumber(1),
                                                      new PdfNumber(3),
                                                      new PdfNumber(1));
            expected.Entries["Index"] = new PdfArray(new PdfNumber(124332),
                                                     new PdfNumber(848));
            expected.Entries["Encrypt"] = null;//hmm?
        }
예제 #12
0
        public void BinaryString()
        {
            var raw = "<901FA3>";

            using (var ms = new MemoryStream(Encoding.ASCII.GetBytes(raw)))
            {
                var streamReader = new PdfStreamReader(ms, 512);
                var actual       = this._reader.ReadObject(streamReader, this._pdf);
                var expected     = new byte[] { 0x90, 0x1F, 0xA3 };

                Assert.IsType <PdfBinaryString>(actual);
                Assert.Equal(expected, ((PdfBinaryString)actual).Value);
            }
        }
예제 #13
0
        public void ReturnsCorrect(int position)
        {
            var buffer = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 };

            using (var memoryStream = new MemoryStream(buffer))
            {
                var reader = new PdfStreamReader(memoryStream, 512);

                reader.Seek(position, SeekOrigin.Begin);
                var actual = reader.Position;

                Assert.Equal(position, actual);
            }
        }
예제 #14
0
        public void StartsAtBeginningReturnsFirstByte()
        {
            var buffer = new byte[] { 0x01, 0x02, 0x03 };

            using (var memoryStream = new MemoryStream(buffer))
            {
                var reader = new PdfStreamReader(memoryStream, 512);
                Assert.Equal(0, reader.Position);

                var expected = 1;
                var actual   = reader.Read();
                Assert.Equal(expected, actual);
                Assert.Equal(1, reader.Position);
            }
        }
예제 #15
0
        internal void                    pdfReadReference(PdfStreamReader reader)
        {
            if (!(base.Count >= 2 &&
                  base[base.Count - 2] is PdfInteger &&
                  base[base.Count - 1] is PdfInteger))
            {
                throw new PdfException("Invalid reference in stream.");
            }

            int id       = ((PdfInteger) base[base.Count - 2]).Value;
            int revision = ((PdfInteger) base[base.Count - 1]).Value;

            base.RemoveRange(base.Count - 2, 2);

            base.Add(reader.Document.pdfGetReference(id, revision));
        }
예제 #16
0
        public void StartsAtEndReturnsNegativeOne()
        {
            var buffer = new byte[] { 0x01, 0x02, 0x03 };

            using (var memoryStream = new MemoryStream(buffer))
            {
                var reader = new PdfStreamReader(memoryStream, 512);
                reader.Seek(3, SeekOrigin.Begin);
                Assert.Equal(3, reader.Position);

                var expected = -1;
                var actual   = reader.Read();
                Assert.Equal(expected, actual);
                Assert.Equal(3, reader.Position);
            }
        }
예제 #17
0
        public void StartsAtMiddleReturnsMiddle()
        {
            var buffer = new byte[] { 0x01, 0x02, 0x03 };

            using (var memoryStream = new MemoryStream(buffer))
            {
                var reader = new PdfStreamReader(memoryStream, 512);
                reader.Seek(1, SeekOrigin.Begin);
                Assert.Equal(1, reader.Position);

                var expected = 2;
                var actual   = reader.Read();
                Assert.Equal(expected, actual);
                Assert.Equal(2, reader.Position);
            }
        }
예제 #18
0
        public void ReadsLastByte()
        {
            var buffer = new byte[] { 0x01, 0x02, 0x03 };

            using (var memoryStream = new MemoryStream(buffer))
            {
                var reader = new PdfStreamReader(memoryStream, 512);
                reader.Seek(2, SeekOrigin.Begin);
                Assert.Equal(2, reader.Position);

                var expected = 3;
                var actual   = reader.Read();
                Assert.Equal(expected, actual);
                Assert.Equal(3, reader.Position);
            }
        }
예제 #19
0
        public void StartsAtBeginningReturnsFullBuffer()
        {
            var buffer = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 };

            using (var memoryStream = new MemoryStream(buffer))
            {
                var reader     = new PdfStreamReader(memoryStream, 512);
                var readBuffer = new byte[2];

                Assert.Equal(0, reader.Position);

                var bytesRead = reader.Read(readBuffer, 0, readBuffer.Length);
                Assert.Equal(2, reader.Position);
                Assert.Equal(2, bytesRead);
                Assert.Equal(new byte[] { 0x01, 0x02 }, readBuffer);
            }
        }
예제 #20
0
        public void StartsAtEndReturnsNegativeOne()
        {
            var buffer = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 };

            using (var memoryStream = new MemoryStream(buffer))
            {
                var reader     = new PdfStreamReader(memoryStream, 512);
                var readBuffer = new byte[2];

                reader.Seek(5, SeekOrigin.Begin);
                Assert.Equal(5, reader.Position);

                var bytesRead = reader.Read(readBuffer, 0, readBuffer.Length);
                Assert.Equal(5, reader.Position);
                Assert.Equal(-1, bytesRead);
                Assert.Equal(new byte[] { 0x00, 0x00 }, readBuffer);
            }
        }
예제 #21
0
        public void ReadsPartialAtEnd()
        {
            var buffer = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 };

            using (var memoryStream = new MemoryStream(buffer))
            {
                var reader     = new PdfStreamReader(memoryStream, 512);
                var readBuffer = new byte[2];

                reader.Seek(4, SeekOrigin.Begin);
                Assert.Equal(4, reader.Position);

                var bytesRead = reader.Read(readBuffer, 0, readBuffer.Length);
                Assert.Equal(5, reader.Position);
                Assert.Equal(1, bytesRead);
                Assert.Equal(new byte[] { 0x05, 0x00 }, readBuffer);
            }
        }
예제 #22
0
        public void WithNumberThenIndirectReference()
        {
            var raw = "[0 18 0 R]";

            PdfObject actual;

            using (var ms = new MemoryStream(Encoding.ASCII.GetBytes(raw)))
            {
                var streamReader = new PdfStreamReader(ms, 512);
                actual = _reader.ReadObject(streamReader, this._pdf);
            }

            Assert.IsType <PdfArray>(actual);
            var actualArray = (PdfArray)actual;

            Assert.IsType <PdfNumber>(actualArray.Objects[0]);
            Assert.IsType <PdfReference>(actualArray.Objects[1]);
        }
예제 #23
0
        public void ReadsLastByte()
        {
            var buffer = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 };

            using (var memoryStream = new MemoryStream(buffer))
            {
                var reader     = new PdfStreamReader(memoryStream, 512);
                var readBuffer = new byte[2];

                reader.Seek(3, SeekOrigin.Begin);
                Assert.Equal(3, reader.Position);

                var bytesRead = reader.Peek(readBuffer, 0, readBuffer.Length);
                Assert.Equal(3, reader.Position);
                Assert.Equal(2, bytesRead);
                Assert.Equal(new byte[] { 0x04, 0x05 }, readBuffer);
            }
        }
예제 #24
0
        public void Valid(string value, int?byte1, int?byte2, int?byte3, int readBack)
        {
            PdfBinaryString actual;

            using (var ms = new MemoryStream(Encoding.ASCII.GetBytes(value)))
            {
                var streamReader = new PdfStreamReader(ms, 512);
                actual = this._reader.ReadBinaryString(streamReader, new PdfOptions {
                    ReadBlockSize = 512
                });
                Assert.Equal(value.Length - readBack, streamReader.Position);
            }

            var expected = (new[] { byte1, byte2, byte3 })
                           .Where(x => x.HasValue)
                           .Where(x => x != -1)
                           .Select(x => (byte)x);

            Assert.Equal(expected, actual.Value);
        }
        private PdfValue                    _readObj(PdfStreamReader reader, bool compressed)
        {
            var value = reader.ReadValue();
            var token = (!compressed && reader.Position < reader.Stream.Length) ? reader.ReadToken() : null;

            if (token != null && value is PdfDictionary && token.Type == PdfValueType.StreamBegin)
            {
                var streamBegin  = reader.Position;
                var streamLength = ((PdfDictionary)value).ValueByName <PdfInteger>("Length").Value;
                reader.Skip(streamLength);
                reader.ReadToken(PdfValueType.StreamEnd);
                value = new PdfObjectReader((PdfDictionary)value, new PdfDataStreamReader(_stream, streamBegin, streamLength));
                token = (!compressed && reader.Position < reader.Stream.Length) ? reader.ReadToken() : null;
            }

            if (token != null && token.Type != PdfValueType.ObjectEnd)
            {
                throw new PdfExceptionReader("Missing endobj");
            }

            return(value);
        }
        internal PdfValue                    pdfReadObj(PdfReferenceReader reference)
        {
            try {
                if (reference.CompressedObj == null)
                {
                    var reader = new PdfStreamReader(this, _stream, reference.Position);

                    int id       = reader.ReadInt();
                    int revision = reader.ReadInt();
                    reader.ReadToken(PdfValueType.ObjectBegin);

                    if (id != reference.Id || revision != reference.Revision)
                    {
                        throw new PdfException("Object id d'not match with xreftable.");
                    }

                    var obj = _readObj(reader, false);

                    if (obj is PdfObjectReader && ((PdfObjectReader)obj).NamedType == "ObjStm")
                    {
                        obj = new PdfObjStmReader(this, (PdfObjectReader)obj);
                    }

                    return(obj);
                }
                else
                {
                    if (!(_xrefTable[reference.CompressedObj.Id].Value is PdfObjStmReader objStm))
                    {
                        throw new PdfException("Obj not ObjStm.");
                    }

                    return(_readObj(new PdfStreamReader(this, objStm.GetStream(reference.Position, reference.Id), 0), true));
                }
            }
            catch (Exception err) {
                throw new PdfExceptionReader("Can't read object " + reference.Id.ToString(CultureInfo.InvariantCulture) + "/" + reference.Revision.ToString(CultureInfo.InvariantCulture) + ".", err);
            }
        }
예제 #27
0
        public void DictionaryWithNull()
        {
            var raw = "<<\r\n" +
                      "/OpenAction [4 0 R /XYZ null null null]\r\n" +
                      ">>\r\n";
            PdfObject actual;

            using (var ms = new MemoryStream(Encoding.ASCII.GetBytes(raw)))
            {
                var streamReader = new PdfStreamReader(ms, 512);
                actual = _reader.ReadObject(streamReader, this._pdf);
            }

            Assert.IsType <PdfDictionary>(actual);
            var decodeParamsDictionary = new PdfDictionary();

            decodeParamsDictionary.Entries["Columns"]   = new PdfNumber(5);
            decodeParamsDictionary.Entries["Predictor"] = new PdfNumber(12);

            var expected = new PdfDictionary();

            expected.Entries["DecodeParms"] = decodeParamsDictionary;
            expected.Entries["Filter"]      = new PdfName("FlateDecode");
            expected.Entries["ID"]          = new PdfArray(new PdfBinaryString("9597C618BC90AFA4A078CA72B2DD061C".GetBytesFromHexString()),
                                                           new PdfBinaryString("48726007F483D547A8BEFF6E9CDA072F".GetBytesFromHexString()));
            expected.Entries["Info"]   = null; //hmm?
            expected.Entries["Length"] = new PdfNumber(137);
            expected.Entries["Root"]   = null; //hmm?
            expected.Entries["Size"]   = null; //hmm?
            expected.Entries["Type"]   = new PdfName("XRef");
            expected.Entries["W"]      = new PdfArray(new PdfNumber(1),
                                                      new PdfNumber(3),
                                                      new PdfNumber(1));
            expected.Entries["Index"] = new PdfArray(new PdfNumber(124332),
                                                     new PdfNumber(848));
            expected.Entries["Encrypt"] = null;//hmm?
        }
예제 #28
0
        internal PdfValueType            pdfReadChildren(PdfStreamReader reader, PdfValueType endValueType)
        {
            PdfValue token;

            while ((token = reader.ReadToken()).Type != endValueType)
            {
                switch (token.Type)
                {
                case PdfValueType.Reference:            pdfReadReference(reader);           break;

                case PdfValueType.ArrayBegin:           pdfReadArray(reader);               break;

                case PdfValueType.DictionaryBegin:      pdfReadDictionary(reader);          break;

                case PdfValueType.ObjectBegin:  // This is a syntax error in the stream but eDocPrint somtimes fails to write endobj.....
                case PdfValueType.StreamBegin:
                    if (endValueType == PdfValueType.ObjectEnd)
                    {
                        return(token.Type);
                    }
                    goto error;

                case PdfValueType.ObjectEnd:
                case PdfValueType.DictionaryEnd:
                case PdfValueType.ArrayEnd:
                case PdfValueType.StreamEnd:
                    error :              throw new PdfException("Unexpected token " + token.Type.ToString() + " in stream.");

                default:
                    base.Add(token);
                    break;
                }
            }

            return(token.Type);
        }
 internal PdfDictionary(PdfStreamReader reader)
 {
     _children = new PdfValueList();
     _children.pdfReadChildren(reader, PdfValueType.DictionaryEnd);
 }
        private void                        _readXrefObject(int pos, PdfStreamReader reader, PdfValue firstToken)
        {
            int id       = ((PdfInteger)firstToken).Value;
            int revision = reader.ReadInt();

            reader.ReadToken(PdfValueType.ObjectBegin);
            _allocateXrefTable(id + 1);
            var rr = new PdfReferenceReader(this, id, revision, pos);

            if (!(_readObj(reader, false) is PdfObjectReader obj))
            {
                throw new PdfExceptionReader("Invalid Xref obj.");
            }
            rr.setValue(obj);
            _xrefTable[id] = rr;

            var                dictionary = obj.Dictionary.Children;
            PdfValueList       w          = null;
            PdfValueList       index      = null;
            int                size       = 0;
            PdfReferenceReader prev       = null;

            for (int i = 0; i < dictionary.Count; ++i)
            {
                var entry = dictionary[i];
                if (entry is PdfName)
                {
                    switch (((PdfName)entry).Value)
                    {
                    case "W":       w = ((PdfArray)dictionary[++i]).Children;               break;

                    case "Index":   index = ((PdfArray)dictionary[++i]).Children;               break;

                    case "Size":    size = ((PdfInteger)dictionary[++i]).Value;                break;

                    case "Prev":    prev = (PdfReferenceReader)dictionary[++i];                break;

                    case "Root":    _rootReference = (PdfReferenceReader)dictionary[++i];                break;

                    case "Encrypt": _encryptReference = (PdfReferenceReader)dictionary[++i];                break;

                    case "Info":    _infoReference = (PdfReferenceReader)dictionary[++i];                break;

                    case "ID":      _id = ((PdfArray)dictionary[++i]).Children.ToArray();     break;
                    }
                }
            }

            if (obj.NamedType != "XRef" || w == null || index == null)
            {
                throw new PdfExceptionReader("Invalid xref object.");
            }

            int s1 = ((PdfInteger)w[0]).Value;
            int s2 = ((PdfInteger)w[1]).Value;
            int s3 = ((PdfInteger)w[2]).Value;

            id = ((PdfInteger)index[0]).Value;

            _allocateXrefTable(((PdfInteger)index[1]).Value);

            using (var r = new PdfXrefStreamReader(obj.GetUncompressStream())) {
                while (!r.EOF)
                {
                    int t  = r.ReadValue(s1);
                    int v2 = r.ReadValue(s2);
                    int v3 = r.ReadValue(s3);

                    switch (t)
                    {
                    case 0:                                                                             break;

                    case 1:     pdfGetReference(id, v3).setPosition(v2);                                break;

                    case 2:     pdfGetReference(id, 0).setCompressed(v3, pdfGetReference(v2, 0));       break;

                    default:    throw new PdfExceptionReader("cross-reference stream type #" + t + " unknown.");
                    }

                    ++id;
                }
            }
        }