From f63c7177319e69ade84eeb2c9f76b030e3021b26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gast=C3=B3n=20Milano?= Date: Tue, 9 Aug 2022 09:57:58 -0300 Subject: [PATCH 01/10] Avoid return new MemoryStream, instead return null and manage nulls in the caller methods. --- .gitignore | 2 + .../GxClasses/Domain/GXXmlReadWrite.cs | 9 ++- .../GxClasses/Core/GXUtilsCommon.cs | 15 ++++- .../GxClasses/Core/Web/GxHttpServer.cs | 17 +++++- .../GxClasses/Data/GXDataMemory.cs | 13 +--- .../GxClasses/Domain/GXFileIO.cs | 18 +++--- .../GxClasses/Domain/GXXmlReadWrite.cs | 5 +- .../GxClasses/Domain/GxHttpClient.cs | 61 ++++++++++++++----- .../dotnetframework/GxExcel/GxExcelEPPlus.cs | 30 +++++++-- .../dotnetframework/GxExcel/GxExcelLite.cs | 16 +++-- .../DotNetCoreUnitTest.csproj | 2 +- .../HttpClient/StreamHandling.cs | 35 +++++++++++ 12 files changed, 170 insertions(+), 53 deletions(-) create mode 100644 dotnet/test/DotNetCoreUnitTest/HttpClient/StreamHandling.cs diff --git a/.gitignore b/.gitignore index dfc726d36..c18bda759 100644 --- a/.gitignore +++ b/.gitignore @@ -361,3 +361,5 @@ build /dotnet/src/dotnetcore/GxDataInitialization/net6.0/GXDataInitialization.deps.json /dotnet/src/dotnetcore/GxNetCoreStartup/net6.0/GxNetCoreStartup.deps.json /dotnet/src/dotnetcore/Reor/net6.0/Reor.deps.json +/dotnet/outsonar.txt +/dotnet/output.txt diff --git a/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs b/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs index 8f1084f65..614ac6337 100644 --- a/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs +++ b/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs @@ -235,7 +235,14 @@ public short OpenResponse(IGxHttpClient httpClient) Close(); EntitiesContainer.Reset(); CreateXMLSettings(); - XMLInput = httpClient.ReceiveStream; + if (httpClient.ReceiveStream != null) + { + XMLInput = httpClient.ReceiveStream; + } + else + { + XMLInput = string.Empty; + } return 0; } diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs index 1cc07c9fe..16edf2acd 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs @@ -5465,14 +5465,18 @@ private static Bitmap BitmapCreateFromStream(string filePathOrUrl) { using (Stream s = ImageFile(filePathOrUrl).GetStream()) { - return new Bitmap(s); + if (s != null) + return new Bitmap(s); + return null; } } private static Image ImageCreateFromStream(string filePathOrUrl) { using (Stream s = ImageFile(filePathOrUrl).GetStream()) { - return Image.FromStream(s); + if (s != null) + return Image.FromStream(s); + return null; } } @@ -5487,6 +5491,8 @@ public static string Resize(string imageFile, int width, int height, bool keepAs { using (Image image = ImageCreateFromStream(imageFile)) { + if (image == null) + return string.Empty; int newheight = height; // Prevent using images internal thumbnail image.RotateFlip(RotateFlipType.Rotate180FlipNone); @@ -5646,7 +5652,10 @@ public static int GetImageWidth(string imageFile) { using (Bitmap bmp = BitmapCreateFromStream(imageFile)) { - return bmp.Width; + if (bmp != null) + { + return bmp.Width; + } } } catch (Exception ex) diff --git a/dotnet/src/dotnetframework/GxClasses/Core/Web/GxHttpServer.cs b/dotnet/src/dotnetframework/GxClasses/Core/Web/GxHttpServer.cs index 14d4b2e10..34f03131b 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/Web/GxHttpServer.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/Web/GxHttpServer.cs @@ -11,6 +11,7 @@ namespace GeneXus.Http.Server using Microsoft.AspNetCore.Http.Extensions; using System.Linq; using Microsoft.AspNetCore.Http.Features; + using System.Text; #endif public class GxHttpCookie @@ -388,14 +389,26 @@ public string GetValue( string name) return string.Empty; } } + // create function to convert stream to string + + + private string GetStringFromStream(Stream stream) + { + if (stream == null) + return string.Empty; + using (StreamReader reader = new StreamReader(stream, System.Text.Encoding.UTF8, true, -1, true)) + { + return reader.ReadToEnd(); + } + } public override string ToString() { if (_httpReq == null) return ""; #if NETCORE - return (new StreamReader(_httpReq.Body)).ReadToEnd(); + return GetStringFromStream(_httpReq.Body); #else - return (new StreamReader(_httpReq.InputStream)).ReadToEnd(); + return GetStringFromStream(_httpReq.InputStream); #endif } public void ToFile(string FileName) diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataMemory.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataMemory.cs index 5ef53027f..5ac71ea95 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataMemory.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataMemory.cs @@ -871,18 +871,7 @@ public static object GetCopyFrom(object value) { MemoryStream memStream = new MemoryStream(); Stream oStream = (Stream)value; - byte[] buffer = new byte[4096]; - - oStream.Seek(0, SeekOrigin.Begin); - - int len; - do - { - len = oStream.Read(buffer, 0, buffer.Length); - memStream.Write(buffer, 0, len); - } - while (len > 0); - + oStream.CopyTo(memStream); return memStream; } else diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GXFileIO.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GXFileIO.cs index 8abbd48d3..32ea642ae 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GXFileIO.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GXFileIO.cs @@ -224,10 +224,10 @@ public void MoveTo(string desDirName) public class GxFileInfo : IGxFileInfo { private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GxFileInfo)); - FileInfo _file; - string _baseDirectory; + private FileInfo _file; + private string _baseDirectory; - public GxFileInfo(FileInfo file) + public GxFileInfo(FileInfo file) { _file = file; } @@ -657,7 +657,7 @@ public class GxFile private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GxFile)); internal IGxFileInfo _file; - string _baseDirectory; + string _baseDirectory; int _lastError; string _lastErrorDescription; string _source; @@ -1040,11 +1040,11 @@ public Stream GetStream() _lastError = 0; _lastErrorDescription = ""; if (!validSource()) - return new MemoryStream(); + return null; if (!Exists()) { _lastError = 2; - return new MemoryStream(); + return null; } try { @@ -1054,7 +1054,7 @@ public Stream GetStream() { setError(e); } - return new MemoryStream(); + return null; } public bool PathIsRooted() { @@ -1437,7 +1437,7 @@ public void Open(String encoding) private FileStream _fileStreamReader; private StreamReader _fileReader; - public void OpenWrite(String encoding) + public void OpenWrite(String encoding) { _lastError = 0; _lastErrorDescription = ""; @@ -1568,6 +1568,8 @@ public void Close() } } } + + } public class GxDirectory diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs index 1d43a4fd0..26f65bd1a 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs @@ -229,7 +229,10 @@ public short OpenResponse(IGxHttpClient httpClient) { if (treader != null) Close(); EntitiesContainer.Reset(); - treader = new XmlTextReader(httpClient.ReceiveStream); + if (httpClient.ReceiveStream != null) + treader = new XmlTextReader(httpClient.ReceiveStream); + else + treader = new XmlTextReader(string.Empty); if (treader != null) { SetDtdProcessing(treader, Resolver, validationType); diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs index 9f72aa3d5..140a478bd 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs @@ -56,7 +56,7 @@ internal MultiPartTemplate() HeaderTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" + "Content-Type: {2}\r\n\r\n"; } } - public class GxHttpClient : IGxHttpClient + public class GxHttpClient : IGxHttpClient, IDisposable { private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Http.Client.GxHttpClient)); public const int _Basic = 0; @@ -64,7 +64,7 @@ public class GxHttpClient : IGxHttpClient public const int _NTLM = 2; public const int _Kerberos = 3; Stream _sendStream; - Stream _receiveStream; + MemoryStream _receiveStream; int _timeout = 30000; short _statusCode = 0; string _proxyHost; @@ -120,13 +120,11 @@ public Stream SendStream _sendStream = value; } } + public Stream ReceiveStream { get { - if (_receiveStream == null) - _receiveStream = new MemoryStream(); - return _receiveStream; } } @@ -671,6 +669,7 @@ HttpResponseMessage ExecuteRequest(string method, string requestUrl, CookieConta } void ReadReponseContent(HttpResponseMessage response) { + _receiveStream?.Dispose(); _receiveStream = new MemoryStream(); int BytesRead; Byte[] Buffer = new Byte[1024]; @@ -820,6 +819,8 @@ public void HttpClientExecute(string method, string name) GXLogging.Debug(log, "_responseString " + ToString()); } NameValueCollection _respHeaders; + private bool disposedValue; + void LoadResponseHeaders(HttpResponseMessage resp) { _respHeaders = new NameValueCollection(); @@ -1165,6 +1166,8 @@ private void WebExecute(string method, string name) GXLogging.Debug(log, "Reading response..."); loadResponseHeaders(resp); + + _receiveStream?.Dispose(); _receiveStream = new MemoryStream(); using (Stream rStream = resp.GetResponseStream()) { @@ -1302,9 +1305,10 @@ public override string ToString() { if (_encoding == null) _encoding = Encoding.UTF8; - MemoryStream ms = (MemoryStream)ReceiveStream; - ms.Seek(0, SeekOrigin.Begin); - Byte[] Buffer = ms.ToArray(); + if (_receiveStream == null) + return string.Empty; + _receiveStream.Seek(0, SeekOrigin.Begin); + byte[] Buffer = _receiveStream.ToArray(); return _encoding.GetString(Buffer, 0, Buffer.Length); } public void ToFile(string fileName) @@ -1321,15 +1325,18 @@ public void ToFile(string fileName) using (fs = new FileStream(pathName, FileMode.Create, FileAccess.Write)) #pragma warning restore SCS0018 // Path traversal: injection possible in {1} argument passed to '{0}' { - ReceiveStream.Seek(0, SeekOrigin.Begin); - Byte[] Buffer = new Byte[1024]; - int BytesRead = ReceiveStream.Read(Buffer, 0, 1024); - while (BytesRead > 0) + if (_receiveStream != null) { - fs.Write(Buffer, 0, BytesRead); - BytesRead = ReceiveStream.Read(Buffer, 0, 1024); + _receiveStream.Seek(0, SeekOrigin.Begin); + Byte[] Buffer = new Byte[1024]; + int BytesRead = _receiveStream.Read(Buffer, 0, 1024); + while (BytesRead > 0) + { + fs.Write(Buffer, 0, BytesRead); + BytesRead = _receiveStream.Read(Buffer, 0, 1024); + } + _receiveStream.Seek(0, SeekOrigin.Begin); } - ReceiveStream.Seek(0, SeekOrigin.Begin); } } @@ -1396,6 +1403,30 @@ public void AddCertificate(string file, string pass) } _certificateCollection.Add(c); } + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + _receiveStream?.Dispose(); + _sendStream?.Dispose(); + } + disposedValue = true; + } + } + ~GxHttpClient() + { + + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } } class GxAuthScheme diff --git a/dotnet/src/dotnetframework/GxExcel/GxExcelEPPlus.cs b/dotnet/src/dotnetframework/GxExcel/GxExcelEPPlus.cs index 64a53a3dc..e923b8ecd 100644 --- a/dotnet/src/dotnetframework/GxExcel/GxExcelEPPlus.cs +++ b/dotnet/src/dotnetframework/GxExcel/GxExcelEPPlus.cs @@ -26,9 +26,19 @@ public short Open(String fileName) GxFile temp = new GxFile(Path.GetDirectoryName(template), template); if (temp.Exists()) { - GXLogging.Debug(log, "Opening Template " + template); - p = new ExcelPackage(temp.GetStream()); - OpenFromTemplate = true; + Stream stream = temp.GetStream(); + if (stream != null) + { + GXLogging.Debug(log, "Opening Template " + template); + p = new ExcelPackage(stream); + OpenFromTemplate = true; + } + else + { + errCod = 4; + errDescription = "Invalid template."; + return errCod; + } } else @@ -47,7 +57,19 @@ public short Open(String fileName) fileName += Constants.EXCEL2007Extension; } if (file.IsExternalFile) - p = new ExcelPackage(file.GetStream()); + { + Stream stream = file.GetStream(); + if (stream != null) + { + p = new ExcelPackage(file.GetStream()); + } + else + { + errCod = 4; + errDescription = "Invalid file."; + return errCod; + } + } else p = new ExcelPackage(new FileInfo(fileName)); } diff --git a/dotnet/src/dotnetframework/GxExcel/GxExcelLite.cs b/dotnet/src/dotnetframework/GxExcel/GxExcelLite.cs index a652df75c..b7c7b1d04 100644 --- a/dotnet/src/dotnetframework/GxExcel/GxExcelLite.cs +++ b/dotnet/src/dotnetframework/GxExcel/GxExcelLite.cs @@ -476,9 +476,11 @@ public short Open(String fileName) { GXLogging.Debug(log,"Opening Template " + template); var stream = templateFile.GetStream(); - stream.Position = 0; - - GxExcelUtils.Invoke(ef, "LoadXls", new object[] { stream }); + if (stream != null) + { + stream.Position = 0; + GxExcelUtils.Invoke(ef, "LoadXls", new object[] { stream }); + } } else { @@ -490,9 +492,11 @@ public short Open(String fileName) else if (file.Exists()) { var stream = file.GetStream(); - stream.Position = 0; - - GxExcelUtils.Invoke(ef, "LoadXls", new object[]{stream}); + if (stream != null) + { + stream.Position = 0; + GxExcelUtils.Invoke(ef, "LoadXls", new object[] { stream }); + } } else { diff --git a/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj b/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj index 62bee4934..f4299cd46 100644 --- a/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj +++ b/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj @@ -1,4 +1,4 @@ - + net6.0 CS8032;1701;1702;NU1701 diff --git a/dotnet/test/DotNetCoreUnitTest/HttpClient/StreamHandling.cs b/dotnet/test/DotNetCoreUnitTest/HttpClient/StreamHandling.cs new file mode 100644 index 000000000..c947adfb3 --- /dev/null +++ b/dotnet/test/DotNetCoreUnitTest/HttpClient/StreamHandling.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using GeneXus.Http.Client; +using GeneXus.XML; +using Xunit; + +namespace DotNetCoreUnitTest.HttpClient +{ + public class StreamHandling + { + [Fact] + public void CreateHttpClient() + { + GxHttpClient client = new GxHttpClient(); + + client.Execute("GET", "https://raw.githubusercontent.com/OFFLINE-GmbH/Online-FTP-S3/master/phpunit.xml"); + Assert.Equal(client.StatusCode, (short) System.Net.HttpStatusCode.OK); + Assert.True( client.ToString().Length > 0); + + // No try to consume the string again in order to verify it works several times. + Assert.True(client.ToString().Length > 0); + + GXXMLReader reader = new GXXMLReader(); + reader.OpenResponse(client); + Assert.True(reader.Read() > 0); + + Assert.True(client.ToString().Length > 0); + + + } + } +} From 1c8d3a47516c53e91c9f45aebe4b354ed654bac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gast=C3=B3n=20Milano?= Date: Tue, 9 Aug 2022 12:13:51 -0300 Subject: [PATCH 02/10] Fix broken build --- .../GxClasses/Core/Web/GxHttpServer.cs | 2 +- .../GxClasses/Domain/GxHttpClient.cs | 1 - .../HttpClient/StreamHandling.cs | 25 +++++++++++-------- .../StringUtil/StringUtilTests.cs | 2 -- .../DotNetUnitTest/Domain/GxHttpClientTest.cs | 20 ++++++++------- 5 files changed, 26 insertions(+), 24 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Core/Web/GxHttpServer.cs b/dotnet/src/dotnetframework/GxClasses/Core/Web/GxHttpServer.cs index fde612cff..5e365fab0 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/Web/GxHttpServer.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/Web/GxHttpServer.cs @@ -412,7 +412,7 @@ public override string ToString() if (_httpReq == null) return String.Empty; #if NETCORE - return GetStringFromStream(_httpReq.Body); + return _httpReq.GetRawBodyString(); #else return GetStringFromStream(_httpReq.InputStream); #endif diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs index 310d7e0a6..ecec655b1 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs @@ -1422,7 +1422,6 @@ protected virtual void Dispose(bool disposing) } ~GxHttpClient() { - Dispose(false); } diff --git a/dotnet/test/DotNetCoreUnitTest/HttpClient/StreamHandling.cs b/dotnet/test/DotNetCoreUnitTest/HttpClient/StreamHandling.cs index c947adfb3..547e3f043 100644 --- a/dotnet/test/DotNetCoreUnitTest/HttpClient/StreamHandling.cs +++ b/dotnet/test/DotNetCoreUnitTest/HttpClient/StreamHandling.cs @@ -14,20 +14,23 @@ public class StreamHandling [Fact] public void CreateHttpClient() { - GxHttpClient client = new GxHttpClient(); + using (GxHttpClient client = new GxHttpClient()) + { + client.Execute("GET", "https://raw.githubusercontent.com/OFFLINE-GmbH/Online-FTP-S3/master/phpunit.xml"); + Assert.Equal(client.StatusCode, (short)System.Net.HttpStatusCode.OK); + Assert.True(client.ToString().Length > 0); - client.Execute("GET", "https://raw.githubusercontent.com/OFFLINE-GmbH/Online-FTP-S3/master/phpunit.xml"); - Assert.Equal(client.StatusCode, (short) System.Net.HttpStatusCode.OK); - Assert.True( client.ToString().Length > 0); + // No try to consume the string again in order to verify it works several times. + Assert.True(client.ToString().Length > 0); - // No try to consume the string again in order to verify it works several times. - Assert.True(client.ToString().Length > 0); + using (GXXMLReader reader = new GXXMLReader()) + { + reader.OpenResponse(client); + Assert.True(reader.Read() > 0); + } - GXXMLReader reader = new GXXMLReader(); - reader.OpenResponse(client); - Assert.True(reader.Read() > 0); - - Assert.True(client.ToString().Length > 0); + Assert.True(client.ToString().Length > 0); + } } diff --git a/dotnet/test/DotNetCoreUnitTest/StringUtil/StringUtilTests.cs b/dotnet/test/DotNetCoreUnitTest/StringUtil/StringUtilTests.cs index a9e7cb262..2735191e9 100644 --- a/dotnet/test/DotNetCoreUnitTest/StringUtil/StringUtilTests.cs +++ b/dotnet/test/DotNetCoreUnitTest/StringUtil/StringUtilTests.cs @@ -32,9 +32,7 @@ public void TestJSONEncodeDoNotEncodeGreaterCharacter() json +=""; string expectedJsonEncoded = "\\t\\t\\t\\t\\t\\t\\t-88.076680,43.945580 -88.077480,43.945930 -88.078530,43.946390 -88.078960\\t\\t\\t\\t#MyLine\\t"; - string jsonEncoded = StringUtil.JSONEncode(json); - File.WriteAllText(@"C:\temp\json.txt", jsonEncoded); Assert.Equal(jsonEncoded, expectedJsonEncoded); } diff --git a/dotnet/test/DotNetUnitTest/Domain/GxHttpClientTest.cs b/dotnet/test/DotNetUnitTest/Domain/GxHttpClientTest.cs index a03f17559..650f44036 100644 --- a/dotnet/test/DotNetUnitTest/Domain/GxHttpClientTest.cs +++ b/dotnet/test/DotNetUnitTest/Domain/GxHttpClientTest.cs @@ -10,15 +10,17 @@ public class GxHttpClientTest [Fact] public void AddHeaderWithSpecialCharactersDoesNotThrowException() { - GxHttpClient httpclient = new GxHttpClient(); - string headerValue = "d3890093-289b-4f87-adad-f2ebea826e8f!8db3bc7ac3d38933c3b0c91a3bcdab60b9bbb3f607a1c9b312b24374e750243f3a31d7e90a4c55@SSORT!d3890093-289b-4f87-adad-f2ebea826e8f!8c7564ac08514ff988ba6c8c6ba3fc0c"; - string headerName = "Authorization"; - httpclient.AddHeader(headerName, headerValue); - httpclient.Host="accountstest.genexus.com"; - httpclient.Secure=1; - httpclient.BaseURL =@"oauth/gam/v2.0/dummy/requesttokenanduserinfo"; - httpclient.Execute("GET", string.Empty); - Assert.NotEqual(((int)HttpStatusCode.InternalServerError), httpclient.StatusCode); + using (GxHttpClient httpclient = new GxHttpClient()) + { + string headerValue = "d3890093-289b-4f87-adad-f2ebea826e8f!8db3bc7ac3d38933c3b0c91a3bcdab60b9bbb3f607a1c9b312b24374e750243f3a31d7e90a4c55@SSORT!d3890093-289b-4f87-adad-f2ebea826e8f!8c7564ac08514ff988ba6c8c6ba3fc0c"; + string headerName = "Authorization"; + httpclient.AddHeader(headerName, headerValue); + httpclient.Host = "accountstest.genexus.com"; + httpclient.Secure = 1; + httpclient.BaseURL = @"oauth/gam/v2.0/dummy/requesttokenanduserinfo"; + httpclient.Execute("GET", string.Empty); + Assert.NotEqual(((int)HttpStatusCode.InternalServerError), httpclient.StatusCode); + } } } From b3a1644d6c34d7e6ed5c980db1711f109ebf3141 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gast=C3=B3n=20Milano?= Date: Tue, 9 Aug 2022 14:18:46 -0300 Subject: [PATCH 03/10] Change namespace --- dotnet/test/DotNetCoreUnitTest/HttpClient/StreamHandling.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/test/DotNetCoreUnitTest/HttpClient/StreamHandling.cs b/dotnet/test/DotNetCoreUnitTest/HttpClient/StreamHandling.cs index 547e3f043..cf1db2e0f 100644 --- a/dotnet/test/DotNetCoreUnitTest/HttpClient/StreamHandling.cs +++ b/dotnet/test/DotNetCoreUnitTest/HttpClient/StreamHandling.cs @@ -7,7 +7,7 @@ using GeneXus.XML; using Xunit; -namespace DotNetCoreUnitTest.HttpClient +namespace DotNetCoreUnitTest.HttpClientTest { public class StreamHandling { From a2b3e0ff09893f8596a302c8b0b67d3aac8e3502 Mon Sep 17 00:00:00 2001 From: Claudia Murialdo Date: Tue, 9 Aug 2022 18:09:13 -0300 Subject: [PATCH 04/10] Remove duplicated package reference. --- dotnet/src/dotnetcore/GxMail/GxMail.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/dotnet/src/dotnetcore/GxMail/GxMail.csproj b/dotnet/src/dotnetcore/GxMail/GxMail.csproj index 42e76af3a..fbeb0ea93 100644 --- a/dotnet/src/dotnetcore/GxMail/GxMail.csproj +++ b/dotnet/src/dotnetcore/GxMail/GxMail.csproj @@ -72,7 +72,6 @@ - From 354725c4d07870bbe5414d638d267d8d862c25f2 Mon Sep 17 00:00:00 2001 From: Claudia Murialdo Date: Tue, 9 Aug 2022 18:54:57 -0300 Subject: [PATCH 05/10] Remove unused AesCryptoServiceProvider. --- .../src/dotnetcore/GxClasses/GxClasses.csproj | 1 - .../Cryptography/AesCryptoServiceProvider.cs | 46 ------------------- 2 files changed, 47 deletions(-) delete mode 100644 dotnet/src/dotnetcore/GxClasses/Helpers/Cryptography/AesCryptoServiceProvider.cs diff --git a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj index 58285ee69..f745f0137 100644 --- a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj +++ b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj @@ -119,7 +119,6 @@ - diff --git a/dotnet/src/dotnetcore/GxClasses/Helpers/Cryptography/AesCryptoServiceProvider.cs b/dotnet/src/dotnetcore/GxClasses/Helpers/Cryptography/AesCryptoServiceProvider.cs deleted file mode 100644 index fd1bba4d8..000000000 --- a/dotnet/src/dotnetcore/GxClasses/Helpers/Cryptography/AesCryptoServiceProvider.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Security.Cryptography; - -namespace GeneXus.Encryption -{ - internal class AesCryptoServiceProvider - { - Aes _aes; - public AesCryptoServiceProvider() - { - _aes = Aes.Create(); - } - - public ICryptoTransform CreateEncryptor() { - return _aes.CreateEncryptor(); - } - - public ICryptoTransform CreateDecryptor() - { - return _aes.CreateDecryptor(); - } - - public CipherMode Mode - { - get { return _aes.Mode; } - set { _aes.Mode = value; } - } - - public PaddingMode Padding - { - get { return _aes.Padding; } - set { _aes.Padding = value; } - } - - public byte[] Key - { - get { return _aes.Key; } - set { _aes.Key = value; } - } - - public void Clear() - { - _aes.Dispose(); - } - - } -} \ No newline at end of file From c3a7a7890d7f79927b566818eb3d1fa65aabdba0 Mon Sep 17 00:00:00 2001 From: Claudia Murialdo Date: Thu, 11 Aug 2022 15:53:05 -0300 Subject: [PATCH 06/10] Given that httpclient reads all the response bytes at execute method, the stream ReceiveStream is changed by a byte[] array to avoid potential Improper Resource Shutdown errors when used outside StandardClasses. --- .../GxClasses/Domain/GXXmlReadWrite.cs | 5 +- .../GxClasses/Domain/GXXmlReadWrite.cs | 15 ++- .../GxClasses/Domain/GxHttpClient.cs | 124 ++++++++---------- 3 files changed, 71 insertions(+), 73 deletions(-) diff --git a/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs b/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs index 614ac6337..e2779a881 100644 --- a/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs +++ b/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs @@ -235,9 +235,10 @@ public short OpenResponse(IGxHttpClient httpClient) Close(); EntitiesContainer.Reset(); CreateXMLSettings(); - if (httpClient.ReceiveStream != null) + GxHttpClient gxHttpClient = httpClient as GxHttpClient; + if (gxHttpClient!=null && gxHttpClient.ReceiveData != null) { - XMLInput = httpClient.ReceiveStream; + XMLInput = new MemoryStream(gxHttpClient.ReceiveData); } else { diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs index 26f65bd1a..3ad6a928b 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs @@ -48,6 +48,7 @@ public class GXXMLReader : IDisposable public const int ValidationXDR = 4; private XmlTextReader treader; + private MemoryStream mreader; private XmlValidatingReader vreader; @@ -229,8 +230,12 @@ public short OpenResponse(IGxHttpClient httpClient) { if (treader != null) Close(); EntitiesContainer.Reset(); - if (httpClient.ReceiveStream != null) - treader = new XmlTextReader(httpClient.ReceiveStream); + GxHttpClient gxHttpClient = httpClient as GxHttpClient; + if (gxHttpClient != null && gxHttpClient.ReceiveData != null) + { + mreader = new MemoryStream(gxHttpClient.ReceiveData); + treader = new XmlTextReader(mreader); + } else treader = new XmlTextReader(string.Empty); if (treader != null) @@ -293,6 +298,7 @@ public void OpenFromString(string s) Uri baseUri = new Uri( sBaseDirectory ); Resolver.Myself = baseUri; treader = null; + mreader = null; try { if (File.Exists(s)) @@ -632,6 +638,11 @@ public short Close() treader.Close(); treader = null; } + if (mreader != null) + { + mreader.Close(); + mreader = null; + } if ( vreader != null ) { vreader.Close(); diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs index ecec655b1..e14f0cdbf 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs @@ -63,8 +63,9 @@ public class GxHttpClient : IGxHttpClient, IDisposable public const int _Digest = 1; public const int _NTLM = 2; public const int _Kerberos = 3; + const int StreamWriterDefaultBufferSize = 1024; Stream _sendStream; - MemoryStream _receiveStream; + byte[] _receiveData; int _timeout = 30000; short _statusCode = 0; string _proxyHost; @@ -125,10 +126,16 @@ public Stream ReceiveStream { get { - return _receiveStream; + return null; + } + } + internal byte[] ReceiveData + { + get + { + return _receiveData; } } - #if NETCORE [SecuritySafeCritical] @@ -416,9 +423,12 @@ void sendVariables(Stream reqStream) if (vars.Count > 0) { string buffer = string.Join(variableSeparator(), vars.ToArray()); - StreamWriter sw = new StreamWriter(reqStream); - sw.Write(buffer); - sw.Flush(); + + using (StreamWriter sw = new StreamWriter(reqStream, Encoding.UTF8, StreamWriterDefaultBufferSize, true)) + { + sw.Write(buffer); + sw.Flush(); + } } } bool IsMultipart { get; set; } @@ -443,13 +453,12 @@ string buildVariableToSend(string key, string value) } public void AddString(string s) { - StreamWriter sw; - if (_contentEncoding != null) - sw = new StreamWriter(SendStream, _contentEncoding); - else - sw = new StreamWriter(SendStream); - sw.Write(s); - sw.Flush(); + Encoding encoding = _contentEncoding!=null ? _contentEncoding: Encoding.UTF8; + using (StreamWriter sw = new StreamWriter(SendStream, encoding, StreamWriterDefaultBufferSize, true)) + { + sw.Write(s); + sw.Flush(); + } } public void ClearFiles() { @@ -673,10 +682,7 @@ HttpResponseMessage ExecuteRequest(string method, string requestUrl, CookieConta } void ReadReponseContent(HttpResponseMessage response) { - _receiveStream?.Dispose(); - _receiveStream = new MemoryStream(); - int BytesRead; - Byte[] Buffer = new Byte[1024]; + _receiveData = Array.Empty(); try { Stream stream = response.Content.ReadAsStreamAsync().GetAwaiter().GetResult(); @@ -685,9 +691,6 @@ void ReadReponseContent(HttpResponseMessage response) charset = null; else charset = response.Content.Headers.ContentType.CharSet; - Buffer = new Byte[1024]; - BytesRead = stream.Read(Buffer, 0, 1024); - GXLogging.Debug(log, "BytesRead " + BytesRead); bool encodingFound = false; if (!string.IsNullOrEmpty(charset)) { @@ -705,16 +708,18 @@ void ReadReponseContent(HttpResponseMessage response) charset = String.Empty; } } - while (BytesRead > 0) + + using (MemoryStream ms = new MemoryStream()) { - if (!encodingFound) - { - _encoding = DetectEncoding(charset, out encodingFound, Buffer, BytesRead); - } - _receiveStream.Write(Buffer, 0, BytesRead); - BytesRead = stream.Read(Buffer, 0, 1024); - GXLogging.Debug(log, "BytesRead " + BytesRead); + stream.CopyTo(ms); + _receiveData = ms.ToArray(); } + int bytesRead = _receiveData.Length; + GXLogging.Debug(log, "BytesRead " + _receiveData.Length); + if (bytesRead > 0 && !encodingFound) + { + _encoding = DetectEncoding(charset, out encodingFound, _receiveData, bytesRead); + } } catch (IOException ioEx) { @@ -723,8 +728,9 @@ void ReadReponseContent(HttpResponseMessage response) else throw ioEx; } - _receiveStream.Seek(0, SeekOrigin.Begin); } + + public void Execute(string method, string name) { if (Config.GetValueOf("useoldhttpclient", out string useOld) && useOld.StartsWith("y", StringComparison.OrdinalIgnoreCase)) @@ -1119,8 +1125,6 @@ private void WebExecute(string method, string name) { HttpWebRequest req; HttpWebResponse resp = null; - int BytesRead; - Byte[] Buffer = new Byte[1024]; _errCode = 0; _errDescription = string.Empty; @@ -1171,17 +1175,13 @@ private void WebExecute(string method, string name) GXLogging.Debug(log, "Reading response..."); loadResponseHeaders(resp); - _receiveStream?.Dispose(); - _receiveStream = new MemoryStream(); + _receiveData = Array.Empty(); + String charset = resp.ContentType; using (Stream rStream = resp.GetResponseStream()) { try { - Buffer = new Byte[1024]; - BytesRead = rStream.Read(Buffer, 0, 1024); - GXLogging.Debug(log, "BytesRead " + BytesRead); bool encodingFound = false; - String charset = resp.ContentType; if (!string.IsNullOrEmpty(charset)) { int idx = charset.IndexOf("charset="); @@ -1198,15 +1198,17 @@ private void WebExecute(string method, string name) charset = String.Empty; } } - while (BytesRead > 0) + using (MemoryStream ms = new MemoryStream()) { - if (!encodingFound) - { - _encoding = DetectEncoding(charset, out encodingFound, Buffer, BytesRead); - } - _receiveStream.Write(Buffer, 0, BytesRead); - BytesRead = rStream.Read(Buffer, 0, 1024); - GXLogging.Debug(log, "BytesRead " + BytesRead); + rStream.CopyTo(ms); + _receiveData = ms.ToArray(); + } + int bytesRead = _receiveData.Length; + GXLogging.Debug(log, "BytesRead " + bytesRead); + + if (bytesRead > 0 && !encodingFound) + { + _encoding = DetectEncoding(charset, out encodingFound, _receiveData, bytesRead); } } catch (IOException ioEx) @@ -1217,7 +1219,6 @@ private void WebExecute(string method, string name) throw ioEx; } } - _receiveStream.Seek(0, SeekOrigin.Begin); _statusCode = (short)resp.StatusCode; _statusDescription = resp.StatusDescription; resp.Close(); @@ -1309,38 +1310,23 @@ public override string ToString() { if (_encoding == null) _encoding = Encoding.UTF8; - if (_receiveStream == null) + if (_receiveData == null) return string.Empty; - _receiveStream.Seek(0, SeekOrigin.Begin); - byte[] Buffer = _receiveStream.ToArray(); - return _encoding.GetString(Buffer, 0, Buffer.Length); + return _encoding.GetString(_receiveData); } public void ToFile(string fileName) { - FileStream fs; string pathName = fileName; #if !NETCORE if (HttpContext.Current != null) #endif - if (fileName.IndexOfAny(new char[] { '\\', ':' }) == -1) - pathName = Path.Combine(GxContext.StaticPhysicalPath(), fileName); -#pragma warning disable SCS0018 // Path traversal: injection possible in {1} argument passed to '{0}' - using (fs = new FileStream(pathName, FileMode.Create, FileAccess.Write)) -#pragma warning restore SCS0018 // Path traversal: injection possible in {1} argument passed to '{0}' + if (fileName.IndexOfAny(new char[] { '\\', ':' }) == -1) + pathName = Path.Combine(GxContext.StaticPhysicalPath(), fileName); + + if (_receiveData != null) { - if (_receiveStream != null) - { - _receiveStream.Seek(0, SeekOrigin.Begin); - Byte[] Buffer = new Byte[1024]; - int BytesRead = _receiveStream.Read(Buffer, 0, 1024); - while (BytesRead > 0) - { - fs.Write(Buffer, 0, BytesRead); - BytesRead = _receiveStream.Read(Buffer, 0, 1024); - } - _receiveStream.Seek(0, SeekOrigin.Begin); - } + File.WriteAllBytes(pathName, _receiveData); } } @@ -1414,7 +1400,7 @@ protected virtual void Dispose(bool disposing) { if (disposing) { - _receiveStream?.Dispose(); + _receiveData = null; _sendStream?.Dispose(); } disposedValue = true; From 40ef8b104fe2546da4ed7a25382fb9a4bcb0bf09 Mon Sep 17 00:00:00 2001 From: Claudia Murialdo Date: Fri, 12 Aug 2022 11:20:09 -0300 Subject: [PATCH 07/10] Fix an Improper Resource Shutdown at GXDataPostgreSQL. --- .../GxClasses/Data/GXDataPostgreSQL.cs | 48 ++++++++++--------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataPostgreSQL.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataPostgreSQL.cs index f13f25d44..b9fd60ab1 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataPostgreSQL.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataPostgreSQL.cs @@ -361,33 +361,35 @@ private byte[] ByteaTextToByteArray(byte[] BackendData) } else { - MemoryStream ms = new MemoryStream(); - while (byteAPosition < byteALength) + using (MemoryStream ms = new MemoryStream()) { - byte octalValue; - byte b = BackendData[byteAPosition]; - if (b >= 0x20 && b < 0x7F && b != 0x27 && b != 0x5C) + while (byteAPosition < byteALength) { - octalValue = BackendData[byteAPosition]; - byteAPosition++; - ms.WriteByte((Byte)octalValue); - } - else if (BackendData[byteAPosition] == ASCIIByteBackSlash && - byteAPosition + 3 < byteALength && - BackendData[byteAPosition + 1] >= ASCIIByteb0 && BackendData[byteAPosition + 1] <= ASCIIByteb7 && - BackendData[byteAPosition + 2] >= ASCIIByteb0 && BackendData[byteAPosition + 2] <= ASCIIByteb7 && - BackendData[byteAPosition + 3] >= ASCIIByteb0 && BackendData[byteAPosition + 3] <= ASCIIByteb7) - { - octalValue = FastConverter.ToByteEscapeFormat(BackendData, byteAPosition + 1); - byteAPosition += 4; - ms.WriteByte((Byte)octalValue); - } - else - { - return BackendData; + byte octalValue; + byte b = BackendData[byteAPosition]; + if (b >= 0x20 && b < 0x7F && b != 0x27 && b != 0x5C) + { + octalValue = BackendData[byteAPosition]; + byteAPosition++; + ms.WriteByte((Byte)octalValue); + } + else if (BackendData[byteAPosition] == ASCIIByteBackSlash && + byteAPosition + 3 < byteALength && + BackendData[byteAPosition + 1] >= ASCIIByteb0 && BackendData[byteAPosition + 1] <= ASCIIByteb7 && + BackendData[byteAPosition + 2] >= ASCIIByteb0 && BackendData[byteAPosition + 2] <= ASCIIByteb7 && + BackendData[byteAPosition + 3] >= ASCIIByteb0 && BackendData[byteAPosition + 3] <= ASCIIByteb7) + { + octalValue = FastConverter.ToByteEscapeFormat(BackendData, byteAPosition + 1); + byteAPosition += 4; + ms.WriteByte((Byte)octalValue); + } + else + { + return BackendData; + } } + return ms.ToArray(); } - return ms.ToArray(); } }catch(Exception ex) { From b72f06f7a2257d2df6575e6e051dc537a3fee6ee Mon Sep 17 00:00:00 2001 From: cmurialdo Date: Fri, 12 Aug 2022 16:25:33 -0300 Subject: [PATCH 08/10] Temporary Revert for BadRequest errors when using httpclient. --- .../GxClasses/Domain/GXXmlReadWrite.cs | 5 +- .../GxClasses/Domain/GXXmlReadWrite.cs | 15 +-- .../GxClasses/Domain/GxHttpClient.cs | 124 ++++++++++-------- 3 files changed, 73 insertions(+), 71 deletions(-) diff --git a/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs b/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs index e2779a881..614ac6337 100644 --- a/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs +++ b/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs @@ -235,10 +235,9 @@ public short OpenResponse(IGxHttpClient httpClient) Close(); EntitiesContainer.Reset(); CreateXMLSettings(); - GxHttpClient gxHttpClient = httpClient as GxHttpClient; - if (gxHttpClient!=null && gxHttpClient.ReceiveData != null) + if (httpClient.ReceiveStream != null) { - XMLInput = new MemoryStream(gxHttpClient.ReceiveData); + XMLInput = httpClient.ReceiveStream; } else { diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs index 3ad6a928b..26f65bd1a 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs @@ -48,7 +48,6 @@ public class GXXMLReader : IDisposable public const int ValidationXDR = 4; private XmlTextReader treader; - private MemoryStream mreader; private XmlValidatingReader vreader; @@ -230,12 +229,8 @@ public short OpenResponse(IGxHttpClient httpClient) { if (treader != null) Close(); EntitiesContainer.Reset(); - GxHttpClient gxHttpClient = httpClient as GxHttpClient; - if (gxHttpClient != null && gxHttpClient.ReceiveData != null) - { - mreader = new MemoryStream(gxHttpClient.ReceiveData); - treader = new XmlTextReader(mreader); - } + if (httpClient.ReceiveStream != null) + treader = new XmlTextReader(httpClient.ReceiveStream); else treader = new XmlTextReader(string.Empty); if (treader != null) @@ -298,7 +293,6 @@ public void OpenFromString(string s) Uri baseUri = new Uri( sBaseDirectory ); Resolver.Myself = baseUri; treader = null; - mreader = null; try { if (File.Exists(s)) @@ -638,11 +632,6 @@ public short Close() treader.Close(); treader = null; } - if (mreader != null) - { - mreader.Close(); - mreader = null; - } if ( vreader != null ) { vreader.Close(); diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs index e14f0cdbf..ecec655b1 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs @@ -63,9 +63,8 @@ public class GxHttpClient : IGxHttpClient, IDisposable public const int _Digest = 1; public const int _NTLM = 2; public const int _Kerberos = 3; - const int StreamWriterDefaultBufferSize = 1024; Stream _sendStream; - byte[] _receiveData; + MemoryStream _receiveStream; int _timeout = 30000; short _statusCode = 0; string _proxyHost; @@ -126,17 +125,11 @@ public Stream ReceiveStream { get { - return null; - } - } - internal byte[] ReceiveData - { - get - { - return _receiveData; + return _receiveStream; } } + #if NETCORE [SecuritySafeCritical] private HttpClientHandler GetHandler() @@ -423,12 +416,9 @@ void sendVariables(Stream reqStream) if (vars.Count > 0) { string buffer = string.Join(variableSeparator(), vars.ToArray()); - - using (StreamWriter sw = new StreamWriter(reqStream, Encoding.UTF8, StreamWriterDefaultBufferSize, true)) - { - sw.Write(buffer); - sw.Flush(); - } + StreamWriter sw = new StreamWriter(reqStream); + sw.Write(buffer); + sw.Flush(); } } bool IsMultipart { get; set; } @@ -453,12 +443,13 @@ string buildVariableToSend(string key, string value) } public void AddString(string s) { - Encoding encoding = _contentEncoding!=null ? _contentEncoding: Encoding.UTF8; - using (StreamWriter sw = new StreamWriter(SendStream, encoding, StreamWriterDefaultBufferSize, true)) - { - sw.Write(s); - sw.Flush(); - } + StreamWriter sw; + if (_contentEncoding != null) + sw = new StreamWriter(SendStream, _contentEncoding); + else + sw = new StreamWriter(SendStream); + sw.Write(s); + sw.Flush(); } public void ClearFiles() { @@ -682,7 +673,10 @@ HttpResponseMessage ExecuteRequest(string method, string requestUrl, CookieConta } void ReadReponseContent(HttpResponseMessage response) { - _receiveData = Array.Empty(); + _receiveStream?.Dispose(); + _receiveStream = new MemoryStream(); + int BytesRead; + Byte[] Buffer = new Byte[1024]; try { Stream stream = response.Content.ReadAsStreamAsync().GetAwaiter().GetResult(); @@ -691,6 +685,9 @@ void ReadReponseContent(HttpResponseMessage response) charset = null; else charset = response.Content.Headers.ContentType.CharSet; + Buffer = new Byte[1024]; + BytesRead = stream.Read(Buffer, 0, 1024); + GXLogging.Debug(log, "BytesRead " + BytesRead); bool encodingFound = false; if (!string.IsNullOrEmpty(charset)) { @@ -708,18 +705,16 @@ void ReadReponseContent(HttpResponseMessage response) charset = String.Empty; } } - - using (MemoryStream ms = new MemoryStream()) + while (BytesRead > 0) { - stream.CopyTo(ms); - _receiveData = ms.ToArray(); + if (!encodingFound) + { + _encoding = DetectEncoding(charset, out encodingFound, Buffer, BytesRead); + } + _receiveStream.Write(Buffer, 0, BytesRead); + BytesRead = stream.Read(Buffer, 0, 1024); + GXLogging.Debug(log, "BytesRead " + BytesRead); } - int bytesRead = _receiveData.Length; - GXLogging.Debug(log, "BytesRead " + _receiveData.Length); - if (bytesRead > 0 && !encodingFound) - { - _encoding = DetectEncoding(charset, out encodingFound, _receiveData, bytesRead); - } } catch (IOException ioEx) { @@ -728,9 +723,8 @@ void ReadReponseContent(HttpResponseMessage response) else throw ioEx; } + _receiveStream.Seek(0, SeekOrigin.Begin); } - - public void Execute(string method, string name) { if (Config.GetValueOf("useoldhttpclient", out string useOld) && useOld.StartsWith("y", StringComparison.OrdinalIgnoreCase)) @@ -1125,6 +1119,8 @@ private void WebExecute(string method, string name) { HttpWebRequest req; HttpWebResponse resp = null; + int BytesRead; + Byte[] Buffer = new Byte[1024]; _errCode = 0; _errDescription = string.Empty; @@ -1175,13 +1171,17 @@ private void WebExecute(string method, string name) GXLogging.Debug(log, "Reading response..."); loadResponseHeaders(resp); - _receiveData = Array.Empty(); - String charset = resp.ContentType; + _receiveStream?.Dispose(); + _receiveStream = new MemoryStream(); using (Stream rStream = resp.GetResponseStream()) { try { + Buffer = new Byte[1024]; + BytesRead = rStream.Read(Buffer, 0, 1024); + GXLogging.Debug(log, "BytesRead " + BytesRead); bool encodingFound = false; + String charset = resp.ContentType; if (!string.IsNullOrEmpty(charset)) { int idx = charset.IndexOf("charset="); @@ -1198,17 +1198,15 @@ private void WebExecute(string method, string name) charset = String.Empty; } } - using (MemoryStream ms = new MemoryStream()) - { - rStream.CopyTo(ms); - _receiveData = ms.ToArray(); - } - int bytesRead = _receiveData.Length; - GXLogging.Debug(log, "BytesRead " + bytesRead); - - if (bytesRead > 0 && !encodingFound) + while (BytesRead > 0) { - _encoding = DetectEncoding(charset, out encodingFound, _receiveData, bytesRead); + if (!encodingFound) + { + _encoding = DetectEncoding(charset, out encodingFound, Buffer, BytesRead); + } + _receiveStream.Write(Buffer, 0, BytesRead); + BytesRead = rStream.Read(Buffer, 0, 1024); + GXLogging.Debug(log, "BytesRead " + BytesRead); } } catch (IOException ioEx) @@ -1219,6 +1217,7 @@ private void WebExecute(string method, string name) throw ioEx; } } + _receiveStream.Seek(0, SeekOrigin.Begin); _statusCode = (short)resp.StatusCode; _statusDescription = resp.StatusDescription; resp.Close(); @@ -1310,23 +1309,38 @@ public override string ToString() { if (_encoding == null) _encoding = Encoding.UTF8; - if (_receiveData == null) + if (_receiveStream == null) return string.Empty; - return _encoding.GetString(_receiveData); + _receiveStream.Seek(0, SeekOrigin.Begin); + byte[] Buffer = _receiveStream.ToArray(); + return _encoding.GetString(Buffer, 0, Buffer.Length); } public void ToFile(string fileName) { + FileStream fs; string pathName = fileName; #if !NETCORE if (HttpContext.Current != null) #endif - if (fileName.IndexOfAny(new char[] { '\\', ':' }) == -1) - pathName = Path.Combine(GxContext.StaticPhysicalPath(), fileName); - - if (_receiveData != null) + if (fileName.IndexOfAny(new char[] { '\\', ':' }) == -1) + pathName = Path.Combine(GxContext.StaticPhysicalPath(), fileName); +#pragma warning disable SCS0018 // Path traversal: injection possible in {1} argument passed to '{0}' + using (fs = new FileStream(pathName, FileMode.Create, FileAccess.Write)) +#pragma warning restore SCS0018 // Path traversal: injection possible in {1} argument passed to '{0}' { - File.WriteAllBytes(pathName, _receiveData); + if (_receiveStream != null) + { + _receiveStream.Seek(0, SeekOrigin.Begin); + Byte[] Buffer = new Byte[1024]; + int BytesRead = _receiveStream.Read(Buffer, 0, 1024); + while (BytesRead > 0) + { + fs.Write(Buffer, 0, BytesRead); + BytesRead = _receiveStream.Read(Buffer, 0, 1024); + } + _receiveStream.Seek(0, SeekOrigin.Begin); + } } } @@ -1400,7 +1414,7 @@ protected virtual void Dispose(bool disposing) { if (disposing) { - _receiveData = null; + _receiveStream?.Dispose(); _sendStream?.Dispose(); } disposedValue = true; From c8e32be592486feff351c9df43953a1de41a1868 Mon Sep 17 00:00:00 2001 From: cmurialdo Date: Tue, 16 Aug 2022 13:23:33 -0300 Subject: [PATCH 09/10] Restore byte array to store the data of httpclient. --- .../GxClasses/Domain/GXXmlReadWrite.cs | 5 +- .../GxClasses/Domain/GXXmlReadWrite.cs | 15 ++- .../GxClasses/Domain/GxHttpClient.cs | 127 ++++++++---------- 3 files changed, 72 insertions(+), 75 deletions(-) diff --git a/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs b/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs index 614ac6337..e2779a881 100644 --- a/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs +++ b/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs @@ -235,9 +235,10 @@ public short OpenResponse(IGxHttpClient httpClient) Close(); EntitiesContainer.Reset(); CreateXMLSettings(); - if (httpClient.ReceiveStream != null) + GxHttpClient gxHttpClient = httpClient as GxHttpClient; + if (gxHttpClient!=null && gxHttpClient.ReceiveData != null) { - XMLInput = httpClient.ReceiveStream; + XMLInput = new MemoryStream(gxHttpClient.ReceiveData); } else { diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs index 26f65bd1a..3ad6a928b 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs @@ -48,6 +48,7 @@ public class GXXMLReader : IDisposable public const int ValidationXDR = 4; private XmlTextReader treader; + private MemoryStream mreader; private XmlValidatingReader vreader; @@ -229,8 +230,12 @@ public short OpenResponse(IGxHttpClient httpClient) { if (treader != null) Close(); EntitiesContainer.Reset(); - if (httpClient.ReceiveStream != null) - treader = new XmlTextReader(httpClient.ReceiveStream); + GxHttpClient gxHttpClient = httpClient as GxHttpClient; + if (gxHttpClient != null && gxHttpClient.ReceiveData != null) + { + mreader = new MemoryStream(gxHttpClient.ReceiveData); + treader = new XmlTextReader(mreader); + } else treader = new XmlTextReader(string.Empty); if (treader != null) @@ -293,6 +298,7 @@ public void OpenFromString(string s) Uri baseUri = new Uri( sBaseDirectory ); Resolver.Myself = baseUri; treader = null; + mreader = null; try { if (File.Exists(s)) @@ -632,6 +638,11 @@ public short Close() treader.Close(); treader = null; } + if (mreader != null) + { + mreader.Close(); + mreader = null; + } if ( vreader != null ) { vreader.Close(); diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs index ecec655b1..201cc6c19 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs @@ -63,8 +63,9 @@ public class GxHttpClient : IGxHttpClient, IDisposable public const int _Digest = 1; public const int _NTLM = 2; public const int _Kerberos = 3; + const int StreamWriterDefaultBufferSize = 1024; Stream _sendStream; - MemoryStream _receiveStream; + byte[] _receiveData; int _timeout = 30000; short _statusCode = 0; string _proxyHost; @@ -125,10 +126,16 @@ public Stream ReceiveStream { get { - return _receiveStream; + return null; + } + } + internal byte[] ReceiveData + { + get + { + return _receiveData; } } - #if NETCORE [SecuritySafeCritical] @@ -405,7 +412,7 @@ public void AddVariable(string name, string value) _formVars.Add(name, value); } - void sendVariables(Stream reqStream) + void SendVariables(Stream reqStream) { List vars = new List(); for (int i = 0; i < _formVars.Count; i++) @@ -416,8 +423,15 @@ void sendVariables(Stream reqStream) if (vars.Count > 0) { string buffer = string.Join(variableSeparator(), vars.ToArray()); - StreamWriter sw = new StreamWriter(reqStream); - sw.Write(buffer); + WriteToStream(buffer, reqStream); + } + } + void WriteToStream(string data, Stream stream, Encoding encoding=null) + { + Encoding streamEncoding = encoding != null ? encoding : new UTF8Encoding(false, true); + using (StreamWriter sw = new StreamWriter(stream, streamEncoding, StreamWriterDefaultBufferSize, true)) + { + sw.Write(data); sw.Flush(); } } @@ -443,13 +457,7 @@ string buildVariableToSend(string key, string value) } public void AddString(string s) { - StreamWriter sw; - if (_contentEncoding != null) - sw = new StreamWriter(SendStream, _contentEncoding); - else - sw = new StreamWriter(SendStream); - sw.Write(s); - sw.Flush(); + WriteToStream(s, SendStream, _contentEncoding); } public void ClearFiles() { @@ -651,7 +659,7 @@ HttpResponseMessage ExecuteRequest(string method, string requestUrl, CookieConta using (MemoryStream reqStream = new MemoryStream()) { - sendVariables(reqStream); + SendVariables(reqStream); SendStream.Seek(0, SeekOrigin.Begin); BytesRead = SendStream.Read(Buffer, 0, 1024); GXLogging.Debug(log, "Start SendStream.Read: BytesRead " + BytesRead); @@ -673,10 +681,7 @@ HttpResponseMessage ExecuteRequest(string method, string requestUrl, CookieConta } void ReadReponseContent(HttpResponseMessage response) { - _receiveStream?.Dispose(); - _receiveStream = new MemoryStream(); - int BytesRead; - Byte[] Buffer = new Byte[1024]; + _receiveData = Array.Empty(); try { Stream stream = response.Content.ReadAsStreamAsync().GetAwaiter().GetResult(); @@ -685,9 +690,6 @@ void ReadReponseContent(HttpResponseMessage response) charset = null; else charset = response.Content.Headers.ContentType.CharSet; - Buffer = new Byte[1024]; - BytesRead = stream.Read(Buffer, 0, 1024); - GXLogging.Debug(log, "BytesRead " + BytesRead); bool encodingFound = false; if (!string.IsNullOrEmpty(charset)) { @@ -705,16 +707,18 @@ void ReadReponseContent(HttpResponseMessage response) charset = String.Empty; } } - while (BytesRead > 0) + + using (MemoryStream ms = new MemoryStream()) { - if (!encodingFound) - { - _encoding = DetectEncoding(charset, out encodingFound, Buffer, BytesRead); - } - _receiveStream.Write(Buffer, 0, BytesRead); - BytesRead = stream.Read(Buffer, 0, 1024); - GXLogging.Debug(log, "BytesRead " + BytesRead); + stream.CopyTo(ms); + _receiveData = ms.ToArray(); } + int bytesRead = _receiveData.Length; + GXLogging.Debug(log, "BytesRead " + _receiveData.Length); + if (bytesRead > 0 && !encodingFound) + { + _encoding = DetectEncoding(charset, out encodingFound, _receiveData, bytesRead); + } } catch (IOException ioEx) { @@ -723,8 +727,9 @@ void ReadReponseContent(HttpResponseMessage response) else throw ioEx; } - _receiveStream.Seek(0, SeekOrigin.Begin); } + + public void Execute(string method, string name) { if (Config.GetValueOf("useoldhttpclient", out string useOld) && useOld.StartsWith("y", StringComparison.OrdinalIgnoreCase)) @@ -1047,7 +1052,7 @@ HttpWebRequest buildRequest(string method, string requestUrl, CookieContainer co using (Stream reqStream = req.GetRequestStreamAsync().GetAwaiter().GetResult()) #endif { - sendVariables(reqStream); + SendVariables(reqStream); SendStream.Seek(0, SeekOrigin.Begin); BytesRead = SendStream.Read(Buffer, 0, 1024); GXLogging.Debug(log, "Start SendStream.Read: BytesRead " + BytesRead); @@ -1119,8 +1124,6 @@ private void WebExecute(string method, string name) { HttpWebRequest req; HttpWebResponse resp = null; - int BytesRead; - Byte[] Buffer = new Byte[1024]; _errCode = 0; _errDescription = string.Empty; @@ -1171,17 +1174,13 @@ private void WebExecute(string method, string name) GXLogging.Debug(log, "Reading response..."); loadResponseHeaders(resp); - _receiveStream?.Dispose(); - _receiveStream = new MemoryStream(); + _receiveData = Array.Empty(); + String charset = resp.ContentType; using (Stream rStream = resp.GetResponseStream()) { try { - Buffer = new Byte[1024]; - BytesRead = rStream.Read(Buffer, 0, 1024); - GXLogging.Debug(log, "BytesRead " + BytesRead); bool encodingFound = false; - String charset = resp.ContentType; if (!string.IsNullOrEmpty(charset)) { int idx = charset.IndexOf("charset="); @@ -1198,15 +1197,17 @@ private void WebExecute(string method, string name) charset = String.Empty; } } - while (BytesRead > 0) + using (MemoryStream ms = new MemoryStream()) { - if (!encodingFound) - { - _encoding = DetectEncoding(charset, out encodingFound, Buffer, BytesRead); - } - _receiveStream.Write(Buffer, 0, BytesRead); - BytesRead = rStream.Read(Buffer, 0, 1024); - GXLogging.Debug(log, "BytesRead " + BytesRead); + rStream.CopyTo(ms); + _receiveData = ms.ToArray(); + } + int bytesRead = _receiveData.Length; + GXLogging.Debug(log, "BytesRead " + bytesRead); + + if (bytesRead > 0 && !encodingFound) + { + _encoding = DetectEncoding(charset, out encodingFound, _receiveData, bytesRead); } } catch (IOException ioEx) @@ -1217,7 +1218,6 @@ private void WebExecute(string method, string name) throw ioEx; } } - _receiveStream.Seek(0, SeekOrigin.Begin); _statusCode = (short)resp.StatusCode; _statusDescription = resp.StatusDescription; resp.Close(); @@ -1309,38 +1309,23 @@ public override string ToString() { if (_encoding == null) _encoding = Encoding.UTF8; - if (_receiveStream == null) + if (_receiveData == null) return string.Empty; - _receiveStream.Seek(0, SeekOrigin.Begin); - byte[] Buffer = _receiveStream.ToArray(); - return _encoding.GetString(Buffer, 0, Buffer.Length); + return _encoding.GetString(_receiveData); } public void ToFile(string fileName) { - FileStream fs; string pathName = fileName; #if !NETCORE if (HttpContext.Current != null) #endif - if (fileName.IndexOfAny(new char[] { '\\', ':' }) == -1) - pathName = Path.Combine(GxContext.StaticPhysicalPath(), fileName); -#pragma warning disable SCS0018 // Path traversal: injection possible in {1} argument passed to '{0}' - using (fs = new FileStream(pathName, FileMode.Create, FileAccess.Write)) -#pragma warning restore SCS0018 // Path traversal: injection possible in {1} argument passed to '{0}' + if (fileName.IndexOfAny(new char[] { '\\', ':' }) == -1) + pathName = Path.Combine(GxContext.StaticPhysicalPath(), fileName); + + if (_receiveData != null) { - if (_receiveStream != null) - { - _receiveStream.Seek(0, SeekOrigin.Begin); - Byte[] Buffer = new Byte[1024]; - int BytesRead = _receiveStream.Read(Buffer, 0, 1024); - while (BytesRead > 0) - { - fs.Write(Buffer, 0, BytesRead); - BytesRead = _receiveStream.Read(Buffer, 0, 1024); - } - _receiveStream.Seek(0, SeekOrigin.Begin); - } + File.WriteAllBytes(pathName, _receiveData); } } @@ -1414,7 +1399,7 @@ protected virtual void Dispose(bool disposing) { if (disposing) { - _receiveStream?.Dispose(); + _receiveData = null; _sendStream?.Dispose(); } disposedValue = true; From 63aa82c5cfe652df523377412bd8331e0ec17d3b Mon Sep 17 00:00:00 2001 From: cmurialdo Date: Thu, 1 Sep 2022 11:42:11 -0300 Subject: [PATCH 10/10] Fix error ArgumentOutOfRangeException: Positive number required at GxHttpRequest.GetStringFromStream. Default value for bufferSize argument in StreamReader constructor is 1024 for .NET Framework and -1 for .NET. --- .../dotnetframework/GxClasses/Core/Web/GxHttpServer.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Core/Web/GxHttpServer.cs b/dotnet/src/dotnetframework/GxClasses/Core/Web/GxHttpServer.cs index 5e365fab0..0be9d4f55 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/Web/GxHttpServer.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/Web/GxHttpServer.cs @@ -396,13 +396,17 @@ public string GetValue( string name) } } // create function to convert stream to string - +#if NETCORE + const int StreamReaderDefaultBufferSize = -1; +#else + const int StreamReaderDefaultBufferSize = 1024; +#endif private string GetStringFromStream(Stream stream) { if (stream == null) return string.Empty; - using (StreamReader reader = new StreamReader(stream, System.Text.Encoding.UTF8, true, -1, true)) + using (StreamReader reader = new StreamReader(stream, System.Text.Encoding.UTF8, true, StreamReaderDefaultBufferSize, true)) { return reader.ReadToEnd(); }