
committed by
iText Software

3 changed files with 442 additions and 0 deletions
-
57itext.tests/itext.io.tests/itext/io/resolver/resource/DefaultResourceRetrieverTest.cs
-
235itext.tests/itext.io.tests/itext/io/resolver/resource/LimitedInputStreamTest.cs
-
150itext/itext.io/itext/io/resolver/resource/LimitedInputStream.cs
@ -0,0 +1,57 @@ |
|||||
|
/* |
||||
|
This file is part of the iText (R) project. |
||||
|
Copyright (c) 1998-2025 Apryse Group NV |
||||
|
Authors: Apryse Software. |
||||
|
|
||||
|
This program is offered under a commercial and under the AGPL license. |
||||
|
For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
|
||||
|
|
||||
|
AGPL licensing: |
||||
|
This program is free software: you can redistribute it and/or modify |
||||
|
it under the terms of the GNU Affero General Public License as published by |
||||
|
the Free Software Foundation, either version 3 of the License, or |
||||
|
(at your option) any later version. |
||||
|
|
||||
|
This program is distributed in the hope that it will be useful, |
||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
GNU Affero General Public License for more details. |
||||
|
|
||||
|
You should have received a copy of the GNU Affero General Public License |
||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
|
||||
|
using System; |
||||
|
using System.Net; |
||||
|
using iText.Commons.Utils; |
||||
|
using iText.Test; |
||||
|
|
||||
|
namespace iText.IO.Resolver.Resource { |
||||
|
//\cond DO_NOT_DOCUMENT
|
||||
|
[NUnit.Framework.Category("IntegrationTest")] |
||||
|
internal class DefaultResourceRetrieverTest : ExtendedITextTest { |
||||
|
[NUnit.Framework.Test] |
||||
|
public virtual void RetrieveResourceConnectTimeoutTest() { |
||||
|
bool exceptionThrown = false; |
||||
|
Uri url = new Uri("http://10.255.255.1/"); |
||||
|
DefaultResourceRetriever resourceRetriever = new DefaultResourceRetriever(); |
||||
|
resourceRetriever.SetConnectTimeout(500); |
||||
|
|
||||
|
try { |
||||
|
// We check 2 possible exceptions
|
||||
|
resourceRetriever.GetInputStreamByUrl(url); |
||||
|
} |
||||
|
catch (WebException e) { |
||||
|
exceptionThrown = true; |
||||
|
// Do not check exception message because it is localized
|
||||
|
} |
||||
|
catch (OperationCanceledException e) { |
||||
|
exceptionThrown = true; |
||||
|
NUnit.Framework.Assert.AreEqual("the operation was canceled.", StringNormalizer.ToLowerCase(e.Message)); |
||||
|
} |
||||
|
|
||||
|
NUnit.Framework.Assert.True(exceptionThrown); |
||||
|
} |
||||
|
} |
||||
|
//\endcond
|
||||
|
} |
@ -0,0 +1,235 @@ |
|||||
|
/* |
||||
|
This file is part of the iText (R) project. |
||||
|
Copyright (c) 1998-2025 Apryse Group NV |
||||
|
Authors: Apryse Software. |
||||
|
|
||||
|
This program is offered under a commercial and under the AGPL license. |
||||
|
For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
|
||||
|
|
||||
|
AGPL licensing: |
||||
|
This program is free software: you can redistribute it and/or modify |
||||
|
it under the terms of the GNU Affero General Public License as published by |
||||
|
the Free Software Foundation, either version 3 of the License, or |
||||
|
(at your option) any later version. |
||||
|
|
||||
|
This program is distributed in the hope that it will be useful, |
||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
GNU Affero General Public License for more details. |
||||
|
|
||||
|
You should have received a copy of the GNU Affero General Public License |
||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
using System; |
||||
|
using System.IO; |
||||
|
using iText.IO.Exceptions; |
||||
|
using iText.Test; |
||||
|
|
||||
|
namespace iText.IO.Resolver.Resource { |
||||
|
[NUnit.Framework.Category("UnitTest")] |
||||
|
public class LimitedInputStreamTest : ExtendedITextTest { |
||||
|
[NUnit.Framework.Test] |
||||
|
public virtual void ReadingByteAfterFileReadingTest() { |
||||
|
using (Stream stream = new LimitedInputStream(new LimitedInputStreamTest.TestStreamGenerator().OpenStream( |
||||
|
), 100)) { |
||||
|
// The user can call the reading methods as many times as he want, and if the
|
||||
|
// stream has been read, then should not throw an ReadingByteLimitException exception
|
||||
|
for (int i = 0; i < 101; i++) { |
||||
|
NUnit.Framework.Assert.DoesNotThrow(() => stream.Read()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[NUnit.Framework.Test] |
||||
|
public virtual void ReadingByteArrayAfterFileReadingTest() { |
||||
|
using (Stream stream = new LimitedInputStream(new LimitedInputStreamTest.TestStreamGenerator().OpenStream( |
||||
|
), 100)) { |
||||
|
// The user can call the reading methods as many times as he want, and if the
|
||||
|
// stream has been read, then should not throw an ReadingByteLimitException exception
|
||||
|
NUnit.Framework.Assert.DoesNotThrow(() => stream.Read(new byte[100])); |
||||
|
NUnit.Framework.Assert.DoesNotThrow(() => stream.Read(new byte[1])); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[NUnit.Framework.Test] |
||||
|
public virtual void ReadingByteArrayWithOffsetAfterFileReadingTest() { |
||||
|
using (Stream stream = new LimitedInputStream(new LimitedInputStreamTest.TestStreamGenerator().OpenStream( |
||||
|
), 100)) { |
||||
|
// The user can call the reading methods as many times as he want, and if the
|
||||
|
// stream has been read, then should not throw an ReadingByteLimitException exception
|
||||
|
NUnit.Framework.Assert.DoesNotThrow(() => { |
||||
|
stream.JRead(new byte[100], 0, 100); |
||||
|
} |
||||
|
); |
||||
|
NUnit.Framework.Assert.DoesNotThrow(() => { |
||||
|
stream.JRead(new byte[1], 0, 1); |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[NUnit.Framework.Test] |
||||
|
public virtual void ReadingByteWithLimitOfOneLessThenFileSizeTest() { |
||||
|
using (Stream stream = new LimitedInputStream(new LimitedInputStreamTest.TestStreamGenerator().OpenStream( |
||||
|
), 88)) { |
||||
|
for (int i = 0; i < 88; i++) { |
||||
|
NUnit.Framework.Assert.AreNotEqual(-1, stream.Read()); |
||||
|
} |
||||
|
NUnit.Framework.Assert.Catch(typeof(ReadingByteLimitException), () => stream.Read()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[NUnit.Framework.Test] |
||||
|
public virtual void ReadingByteArrayWithLimitOfOneLessThenFileSizeTest() { |
||||
|
using (Stream stream = new LimitedInputStream(new LimitedInputStreamTest.TestStreamGenerator().OpenStream( |
||||
|
), 88)) { |
||||
|
byte[] bytes = new byte[100]; |
||||
|
int numOfReadBytes = stream.Read(bytes); |
||||
|
NUnit.Framework.Assert.AreEqual(88, numOfReadBytes); |
||||
|
NUnit.Framework.Assert.AreEqual(10, bytes[87]); |
||||
|
NUnit.Framework.Assert.AreEqual(0, bytes[88]); |
||||
|
NUnit.Framework.Assert.Catch(typeof(ReadingByteLimitException), () => stream.Read(new byte[1])); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[NUnit.Framework.Test] |
||||
|
public virtual void ReadingByteArrayWithOffsetAndLimitOfOneLessThenFileSizeTest() { |
||||
|
using (Stream stream = new LimitedInputStream(new LimitedInputStreamTest.TestStreamGenerator().OpenStream( |
||||
|
), 88)) { |
||||
|
byte[] bytes = new byte[100]; |
||||
|
int numOfReadBytes = stream.JRead(bytes, 0, 88); |
||||
|
NUnit.Framework.Assert.AreEqual(88, numOfReadBytes); |
||||
|
NUnit.Framework.Assert.AreEqual(10, bytes[87]); |
||||
|
NUnit.Framework.Assert.AreEqual(0, bytes[88]); |
||||
|
NUnit.Framework.Assert.Catch(typeof(ReadingByteLimitException), () => stream.JRead(bytes, 88, 1)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[NUnit.Framework.Test] |
||||
|
public virtual void ReadingByteArrayWithSmallBufferTest() { |
||||
|
using (Stream stream = new LimitedInputStream(new LimitedInputStreamTest.TestStreamGenerator().OpenStream( |
||||
|
), 89)) { |
||||
|
byte[] bytes = new byte[20]; |
||||
|
MemoryStream output = new MemoryStream(); |
||||
|
while (true) { |
||||
|
int read = stream.Read(bytes); |
||||
|
if (read < 1) { |
||||
|
break; |
||||
|
} |
||||
|
output.Write(bytes, 0, read); |
||||
|
} |
||||
|
NUnit.Framework.Assert.AreEqual(89, output.Length); |
||||
|
output.Dispose(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[NUnit.Framework.Test] |
||||
|
public virtual void ReadingByteArrayWithBigBufferTest() { |
||||
|
// retrieveStyleSheetTest.css.dat size is 89 bytes
|
||||
|
using (Stream stream = new LimitedInputStream(new LimitedInputStreamTest.TestStreamGenerator().OpenStream( |
||||
|
), 89)) { |
||||
|
byte[] bytes = new byte[100]; |
||||
|
NUnit.Framework.Assert.AreEqual(89, stream.Read(bytes)); |
||||
|
byte[] tempBytes = (byte[])bytes.Clone(); |
||||
|
NUnit.Framework.Assert.AreEqual(-1, stream.Read(bytes)); |
||||
|
// Check that the array has not changed when we have read the entire LimitedInputStream
|
||||
|
NUnit.Framework.Assert.AreEqual(tempBytes, bytes); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[NUnit.Framework.Test] |
||||
|
public virtual void ReadingByteArrayWithOffsetAndBigBufferTest() { |
||||
|
using (Stream stream = new LimitedInputStream(new LimitedInputStreamTest.TestStreamGenerator().OpenStream( |
||||
|
), 89)) { |
||||
|
byte[] bytes = new byte[100]; |
||||
|
NUnit.Framework.Assert.AreEqual(89, stream.JRead(bytes, 0, 100)); |
||||
|
byte[] tempBytes = (byte[])bytes.Clone(); |
||||
|
NUnit.Framework.Assert.AreEqual(-1, stream.JRead(bytes, 0, 100)); |
||||
|
// Check that the array has not changed when we have read the entire LimitedInputStream
|
||||
|
NUnit.Framework.Assert.AreEqual(tempBytes, bytes); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[NUnit.Framework.Test] |
||||
|
public virtual void ByteArrayOverwritingTest() { |
||||
|
using (Stream stream = new LimitedInputStream(new LimitedInputStreamTest.TestStreamGenerator().OpenStream( |
||||
|
), 90)) { |
||||
|
byte[] bytes = new byte[100]; |
||||
|
bytes[89] = 13; |
||||
|
NUnit.Framework.Assert.AreEqual(89, stream.Read(bytes)); |
||||
|
// Check that when calling the read(byte[]) method, as many bytes were copied into
|
||||
|
// the original array as were read, and not all bytes from the auxiliary array.
|
||||
|
NUnit.Framework.Assert.AreEqual(13, bytes[89]); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[NUnit.Framework.Test] |
||||
|
public virtual void ReadingByteWithZeroLimitTest() { |
||||
|
using (LimitedInputStream stream = new LimitedInputStream(new MemoryStream(new byte[1]), 0)) { |
||||
|
NUnit.Framework.Assert.Catch(typeof(ReadingByteLimitException), () => stream.Read()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[NUnit.Framework.Test] |
||||
|
public virtual void ReadingByteArrayWithZeroLimitTest() { |
||||
|
using (LimitedInputStream stream = new LimitedInputStream(new MemoryStream(new byte[1]), 0)) { |
||||
|
byte[] bytes = new byte[100]; |
||||
|
NUnit.Framework.Assert.Catch(typeof(ReadingByteLimitException), () => stream.Read(bytes)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[NUnit.Framework.Test] |
||||
|
public virtual void ReadingByteArrayWithOffsetAndZeroLimitTest() { |
||||
|
using (LimitedInputStream stream = new LimitedInputStream(new MemoryStream(new byte[1]), 0)) { |
||||
|
byte[] bytes = new byte[100]; |
||||
|
NUnit.Framework.Assert.Catch(typeof(ReadingByteLimitException), () => stream.JRead(bytes, 0, 100)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[NUnit.Framework.Test] |
||||
|
public virtual void ReadingEmptyByteWithZeroLimitTest() { |
||||
|
using (LimitedInputStream stream = new LimitedInputStream(new MemoryStream(new byte[0]), 0)) { |
||||
|
NUnit.Framework.Assert.AreEqual(-1, stream.Read()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[NUnit.Framework.Test] |
||||
|
public virtual void ReadingEmptyByteArrayWithZeroLimitTest() { |
||||
|
using (LimitedInputStream stream = new LimitedInputStream(new MemoryStream(new byte[0]), 0)) { |
||||
|
byte[] bytes = new byte[100]; |
||||
|
NUnit.Framework.Assert.AreEqual(-1, stream.Read(bytes)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[NUnit.Framework.Test] |
||||
|
public virtual void ReadingEmptyByteArrayWithOffsetAndZeroLimitTest() { |
||||
|
using (LimitedInputStream stream = new LimitedInputStream(new MemoryStream(new byte[0]), 0)) { |
||||
|
byte[] bytes = new byte[100]; |
||||
|
NUnit.Framework.Assert.AreEqual(-1, stream.JRead(bytes, 0, 100)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[NUnit.Framework.Test] |
||||
|
public virtual void IllegalReadingByteLimitValueTest() { |
||||
|
Exception e = NUnit.Framework.Assert.Catch(typeof(ArgumentException), () => new LimitedInputStream(new MemoryStream |
||||
|
(new byte[0]), -1)); |
||||
|
NUnit.Framework.Assert.AreEqual(IoExceptionMessageConstant.READING_BYTE_LIMIT_MUST_NOT_BE_LESS_ZERO, e.Message |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
//\cond DO_NOT_DOCUMENT
|
||||
|
internal class TestStreamGenerator { |
||||
|
//\cond DO_NOT_DOCUMENT
|
||||
|
internal String data = "body {\n" + " background-color: lightblue;\n" + "}\n" + "\n" + "h1 {\n" + " color: navy;\n" |
||||
|
+ " margin-left: 20px;\n" + "}"; |
||||
|
//\endcond
|
||||
|
|
||||
|
//\cond DO_NOT_DOCUMENT
|
||||
|
internal virtual Stream OpenStream() { |
||||
|
return new MemoryStream(data.GetBytes(System.Text.Encoding.UTF8)); |
||||
|
} |
||||
|
//\endcond
|
||||
|
} |
||||
|
//\endcond
|
||||
|
} |
||||
|
} |
@ -0,0 +1,150 @@ |
|||||
|
/* |
||||
|
This file is part of the iText (R) project. |
||||
|
Copyright (c) 1998-2025 Apryse Group NV |
||||
|
Authors: Apryse Software. |
||||
|
|
||||
|
This program is offered under a commercial and under the AGPL license. |
||||
|
For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
|
||||
|
|
||||
|
AGPL licensing: |
||||
|
This program is free software: you can redistribute it and/or modify |
||||
|
it under the terms of the GNU Affero General Public License as published by |
||||
|
the Free Software Foundation, either version 3 of the License, or |
||||
|
(at your option) any later version. |
||||
|
|
||||
|
This program is distributed in the hope that it will be useful, |
||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
GNU Affero General Public License for more details. |
||||
|
|
||||
|
You should have received a copy of the GNU Affero General Public License |
||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
using System; |
||||
|
using System.IO; |
||||
|
using iText.IO.Exceptions; |
||||
|
|
||||
|
namespace iText.IO.Resolver.Resource { |
||||
|
//\cond DO_NOT_DOCUMENT
|
||||
|
/// <summary>
|
||||
|
/// Implementation of the
|
||||
|
/// <see cref="System.IO.Stream"/>
|
||||
|
/// abstract class, which is used to restrict
|
||||
|
/// reading bytes from input stream i.e. if more bytes are read than the readingByteLimit,
|
||||
|
/// an
|
||||
|
/// <see cref="ReadingByteLimitException"/>
|
||||
|
/// exception will be thrown.
|
||||
|
///
|
||||
|
/// Note that the readingByteLimit is not taken into account in the <see cref="Seek"/>,
|
||||
|
/// <see cref="set_Position"/> methods.
|
||||
|
/// </summary>
|
||||
|
internal class LimitedInputStream : Stream { |
||||
|
private bool isLimitViolated; |
||||
|
|
||||
|
private long readingByteLimit; |
||||
|
|
||||
|
private Stream inputStream; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a new
|
||||
|
/// <see cref="LimitedInputStream"/>
|
||||
|
/// instance.
|
||||
|
/// </summary>
|
||||
|
/// <param name="inputStream">the input stream, the reading of bytes from which will be limited</param>
|
||||
|
/// <param name="readingByteLimit">the reading byte limit, must not be less than zero</param>
|
||||
|
public LimitedInputStream(Stream inputStream, long readingByteLimit) { |
||||
|
if (readingByteLimit < 0) { |
||||
|
throw new ArgumentException(IoExceptionMessageConstant.READING_BYTE_LIMIT_MUST_NOT_BE_LESS_ZERO); |
||||
|
} |
||||
|
this.isLimitViolated = false; |
||||
|
this.inputStream = inputStream; |
||||
|
this.readingByteLimit = readingByteLimit; |
||||
|
} |
||||
|
|
||||
|
public override int Read(byte[] buffer, int offset, int count) { |
||||
|
if (isLimitViolated) { |
||||
|
throw new ReadingByteLimitException(); |
||||
|
} |
||||
|
|
||||
|
if (count > readingByteLimit) { |
||||
|
if (readingByteLimit == 0) { |
||||
|
// Still need to test if end of stream is reached, so setting 1 byte to read
|
||||
|
count = 1; |
||||
|
} else { |
||||
|
// Safe to cast to int, because count is int and greater
|
||||
|
count = (int) readingByteLimit; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int bytesRead = inputStream.Read(buffer, offset, count); |
||||
|
readingByteLimit -= bytesRead; |
||||
|
|
||||
|
// If end of stream is met at the moment when readingByteLimit == 0
|
||||
|
// we will not throw an exception, because readingByteLimit would not change
|
||||
|
if (readingByteLimit < 0) { |
||||
|
isLimitViolated = true; |
||||
|
throw new ReadingByteLimitException(); |
||||
|
} |
||||
|
|
||||
|
return bytesRead; |
||||
|
} |
||||
|
|
||||
|
protected override void Dispose(bool disposing) { |
||||
|
if (disposing) { |
||||
|
inputStream.Dispose(); |
||||
|
} |
||||
|
|
||||
|
base.Dispose(disposing); |
||||
|
} |
||||
|
|
||||
|
public override void Flush() { |
||||
|
inputStream.Flush(); |
||||
|
} |
||||
|
|
||||
|
public override long Seek(long offset, SeekOrigin origin) { |
||||
|
return inputStream.Seek(offset, origin); |
||||
|
} |
||||
|
|
||||
|
public override void SetLength(long value) { |
||||
|
inputStream.SetLength(value); |
||||
|
} |
||||
|
|
||||
|
public override void Write(byte[] buffer, int offset, int count) { |
||||
|
inputStream.Write(buffer, offset, count); |
||||
|
} |
||||
|
|
||||
|
public override bool CanRead { |
||||
|
get { |
||||
|
return inputStream.CanRead; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override bool CanSeek { |
||||
|
get { |
||||
|
return inputStream.CanSeek; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override bool CanWrite { |
||||
|
get { |
||||
|
return inputStream.CanWrite; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override long Length { |
||||
|
get { |
||||
|
return inputStream.Length; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override long Position { |
||||
|
get { |
||||
|
return inputStream.Position; |
||||
|
} |
||||
|
set { |
||||
|
inputStream.Position = value; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
//\endcond
|
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue