Skip to content

Commit

Permalink
Merge branch 'develop' into devsecops
Browse files Browse the repository at this point in the history
  • Loading branch information
aleks-ivanov committed Nov 1, 2024
2 parents 77307b8 + 8a5a1b3 commit 3dd640e
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 10 deletions.
22 changes: 21 additions & 1 deletion itext.tests/itext.io.tests/itext/io/util/UrlUtilTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ You should have received a copy of the GNU Affero General Public License
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using iText.Commons.Utils;
using iText.Test;
using NUnit.Framework;
Expand Down Expand Up @@ -85,7 +87,25 @@ public void OpenStreamTest() {
byte[] bytes = StreamUtil.InputStreamToArray(openStream);
String actual = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
NUnit.Framework.Assert.AreEqual("Hello world from text file!", actual);

}

[NUnit.Framework.Test]
public virtual void openStreamConnectTimeoutTest()
{
bool exceptionThrown = false;
Uri url = new Uri("http://10.255.255.1/");
try {
// We check 2 possible exceptions
UrlUtil.GetInputStreamOfFinalConnection(url, 500, 300000);
} 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.", e.Message.ToLower());
}

NUnit.Framework.Assert.True(exceptionThrown);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
This file is part of the iText (R) project.
Copyright (c) 1998-2024 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.Test;

namespace iText.StyledXmlParser.Resolver.Resource {
[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.", e.Message.ToLower());
}

NUnit.Framework.Assert.True(exceptionThrown);
}
}
}
61 changes: 54 additions & 7 deletions itext/itext.io/itext/io/util/UrlUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,17 @@ You should have received a copy of the GNU Affero General Public License
using System;
using System.IO;
using System.Net;
using System.Threading;
using System.Threading.Tasks;

namespace iText.IO.Util {
/// <summary>
/// This file is a helper class for internal usage only.
/// Be aware that its API and functionality may be changed in future.
/// </summary>
public static class UrlUtil {
private const int DEFAULT_CONNECT_TIMEOUT = 300000;
private const int DEFAULT_READ_TIMEOUT = 300000;
/// <summary>This method makes a valid URL from a given filename.</summary>
/// <param name="filename">a given filename</param>
/// <returns>a valid URL</returns>
Expand All @@ -41,27 +45,56 @@ public static Uri ToURL(String filename) {
}
}

[Obsolete]
/// <summary>
/// Gets the input stream of connection related to last redirected url. You should manually close input stream after
/// calling this method to not hold any open resources.
/// </summary>
/// <param name="url">an initial URL.</param>
///
/// <returns>an input stream of connection related to the last redirected url.</returns>
public static Stream OpenStream(Uri url) {
return OpenStream(url, DEFAULT_CONNECT_TIMEOUT, DEFAULT_READ_TIMEOUT);
}

/// <summary>
/// Gets the input stream of connection related to last redirected url. You should manually close input stream after
/// calling this method to not hold any open resources.
/// </summary>
/// <param name="url">an initial URL.</param>
/// <param name="connectTimeout">a connect timeout in milliseconds</param>
/// <param name="readTimeout">a read timeout in milliseconds</param>
///
/// <returns>an input stream of connection related to the last redirected url.</returns>
static Stream OpenStream(Uri url, int connectTimeout, int readTimeout)
{
Stream isp;
if (url.IsFile) {
if (url.IsFile)
{
// Use url.LocalPath because it's needed for handling UNC pathes (like used in local
// networks, e.g. \\computer\file.ext). It's safe to use #LocalPath because we
// check #IsFile beforehand. On the other hand, the url.AbsolutePath provides escaped string and also breaks
// UNC path.
isp = new FileStream(url.LocalPath, FileMode.Open, FileAccess.Read);
} else {
WebRequest req = WebRequest.Create(url);
isp = new FileStream(url.LocalPath, FileMode.Open, FileAccess.Read);
}
else
{
HttpWebRequest req = (HttpWebRequest) WebRequest.Create(url);
req.Timeout = connectTimeout;
req.ReadWriteTimeout = readTimeout;
req.Credentials = CredentialCache.DefaultCredentials;
using (WebResponse res = req.GetResponse())
using (Stream rs = res.GetResponseStream()) {
using (Stream rs = res.GetResponseStream())
{
// We don't want to leave the response stream in an open state as it
// may lead to running out of server connections what will block processing
// of new requests. Therefore copying the state of the stream to a MemoryStream
// which doesn't deal with connections.
isp = new MemoryStream();
byte[] buffer = new byte[4096];
int read;
while ((read = rs.Read(buffer, 0, buffer.Length)) > 0) {
while ((read = rs.Read(buffer, 0, buffer.Length)) > 0)
{
isp.Write(buffer, 0, read);
}
isp.Position = 0;
Expand Down Expand Up @@ -124,7 +157,21 @@ public static String GetNormalizedFileUriString(String filename)
///
/// <returns>an input stream of connection related to the last redirected url.</returns>
public static Stream GetInputStreamOfFinalConnection(Uri url) {
return UrlUtil.OpenStream(url);
return OpenStream(url, 3000000, 3000000);
}

/// <summary>
/// Gets the input stream of connection related to last redirected url. You should manually close input stream after
/// calling this method to not hold any open resources.
/// </summary>
/// <param name="url">an initial URL.</param>
/// <param name="connectTimeout">a connect timeout in milliseconds</param>
/// <param name="readTimeout">a read timeout in milliseconds</param>
///
/// <returns>an input stream of connection related to the last redirected url.</returns>
public static Stream GetInputStreamOfFinalConnection(Uri url, int connectTimeout, int readTimeout)
{
return OpenStream(url, connectTimeout, readTimeout);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ public class DefaultResourceRetriever : IResourceRetriever {

private long resourceSizeByteLimit;

private int connectTimeout;

private int readTimeout;

private const int DEFAULT_CONNECT_TIMEOUT = 300000;

private const int DEFAULT_READ_TIMEOUT = 300000;

/// <summary>
/// Creates a new
/// <see cref="DefaultResourceRetriever"/>
Expand All @@ -56,6 +64,8 @@ public class DefaultResourceRetriever : IResourceRetriever {
/// </remarks>
public DefaultResourceRetriever() {
resourceSizeByteLimit = long.MaxValue;
connectTimeout = DEFAULT_CONNECT_TIMEOUT;
readTimeout = DEFAULT_READ_TIMEOUT;
}

/// <summary>Gets the resource size byte limit.</summary>
Expand Down Expand Up @@ -84,6 +94,58 @@ public virtual IResourceRetriever SetResourceSizeByteLimit(long resourceSizeByte
return this;
}

/// <summary>Gets the connect timeout.</summary>
/// <remarks>
/// Gets the connect timeout.
/// The connect timeout is used to create input stream with a limited time to establish connection to resource.
/// </remarks>
/// <returns>the connect timeout in milliseconds</returns>
public virtual int GetConnectTimeout() {
return connectTimeout;
}

/// <summary>Sets the connect timeout.</summary>
/// <remarks>
/// Sets the connect timeout.
/// The connect timeout is used to create input stream with a limited time to establish connection to resource.
/// </remarks>
/// <param name="connectTimeout">the connect timeout in milliseconds</param>
/// <returns>
/// the
/// <see cref="IResourceRetriever"/>
/// instance
/// </returns>
public virtual IResourceRetriever SetConnectTimeout(int connectTimeout) {
this.connectTimeout = connectTimeout;
return this;
}

/// <summary>Gets the read timeout.</summary>
/// <remarks>
/// Gets the read timeout.
/// The read timeout is used to create input stream with a limited time to receive data from resource.
/// </remarks>
/// <returns>the read timeout in milliseconds</returns>
public virtual int GetReadTimeout() {
return readTimeout;
}

/// <summary>Sets the read timeout.</summary>
/// <remarks>
/// Sets the read timeout.
/// The read timeout is used to create input stream with a limited time to receive data from resource.
/// </remarks>
/// <param name="readTimeout">the read timeout in milliseconds</param>
/// <returns>
/// the
/// <see cref="IResourceRetriever"/>
/// instance
/// </returns>
public virtual IResourceRetriever SetReadTimeout(int readTimeout) {
this.readTimeout = readTimeout;
return this;
}

/// <summary>
/// Gets the input stream with current limit on the number of bytes read,
/// that connect with source URL for retrieving data from that connection.
Expand All @@ -96,7 +158,8 @@ public virtual Stream GetInputStreamByUrl(Uri url) {
, url));
return null;
}
return new LimitedInputStream(UrlUtil.GetInputStreamOfFinalConnection(url), resourceSizeByteLimit);
return new LimitedInputStream(UrlUtil.GetInputStreamOfFinalConnection(url, connectTimeout, readTimeout), resourceSizeByteLimit
);
}

/// <summary>Gets the byte array that are retrieved from the source URL.</summary>
Expand Down
2 changes: 1 addition & 1 deletion port-hash
Original file line number Diff line number Diff line change
@@ -1 +1 @@
66825a95b70cfc06c877ac9b3b52a931245427ed
99202aca794f5c7df2d4ecfa5c23ecaad35da666

0 comments on commit 3dd640e

Please sign in to comment.