
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