From 5c1e2f21a7284f3aed99a6bae90943fd21f19f48 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Thu, 6 Jul 2023 18:03:40 -0300 Subject: [PATCH 001/164] Add & to allowed characters in sanitized headers. (#831) * Add & to allowed characters in sanitized headers. * Add more characters to log white list to print correctly messages like GXLogging.DebugSanitized(log, "HttpContext.Session.setProperty(", key, ")=", value); --- dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs index 91394ffe7..643419e40 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs @@ -511,8 +511,8 @@ public class StringUtil const char QMARK = '_'; static char[] numbersAndSep = new char[] { '1', '2', '3', '4', '5', '6', '7', '8', '9', '-' }; static char[] numbers = new char[] { '1', '2', '3', '4', '5', '6', '7', '8', '9' }; - internal static Dictionary LogUserEntryWhiteList = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890+-_=/[]{}\":, ".ToDictionary(item => item, item => item); - internal static Dictionary HttpHeaderWhiteList = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890.;+-_=/[]{}\"':, @()?<>\\".ToDictionary(item => item, item => item); + internal static Dictionary LogUserEntryWhiteList = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890.;+-_=/[]{}\"':, @()?<>\\&".ToDictionary(item => item, item => item); + internal static Dictionary HttpHeaderWhiteList = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890.;+-_=/[]{}\"':, @()?<>\\&".ToDictionary(item => item, item => item); internal static string Sanitize(string input, Dictionary WhiteList) { From 098ce413d7844f4c897ba8f54c9315f0e4d542b7 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Fri, 7 Jul 2023 09:37:30 -0300 Subject: [PATCH 002/164] Make fontSubstitutes static since it is loaded only once. (#838) --- dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext.cs b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext.cs index 3a8eb6d38..2faa34b7a 100644 --- a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext.cs +++ b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext.cs @@ -60,7 +60,7 @@ public class PDFReportItextSharp : IReportHandler private bool modal = false; private String docName = "PDFReport.pdf"; private static NativeSharpFunctionsMS nativeCode = new NativeSharpFunctionsMS(); - private Hashtable fontSubstitutes = new Hashtable(); + private static Hashtable fontSubstitutes = new Hashtable(); private static String configurationFile = null; private static String configurationTemplateFile = null; private static String defaultRelativePrepend = null; From 52cee93d58d52702d1a5f6a048456bd3c49bfcd6 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Fri, 7 Jul 2023 10:03:30 -0300 Subject: [PATCH 003/164] Modify SetHeader method in the Context to enable the overriding of existing values. (#839) * Change AppendHeader by SetHeader at SetHeader method in Context in order to override existing headers. * keep using AddHeader for .NET (Core) as it ensures a safe configuration. It sets the header if !response.HasStarted. * Some Cache-Control values were not being taken into account. * Add a unit test for Cache-control header on GxHttpResponse. --- .../GxClasses/Core/GXApplication.cs | 118 +++++++++++------- .../Domain/GxHttpResponseTest.cs | 41 ++++++ 2 files changed, 115 insertions(+), 44 deletions(-) create mode 100644 dotnet/test/DotNetCoreUnitTest/Domain/GxHttpResponseTest.cs diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs index ff39ab1d5..e96e3814e 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs @@ -13,10 +13,12 @@ namespace GeneXus.Application using System.Messaging; using System.ServiceModel.Web; using GeneXus.UserControls; + using System.Net.Http.Headers; #else using Microsoft.AspNetCore.Http; using GxClasses.Helpers; using Experimental.System.Messaging; + using Microsoft.Net.Http.Headers; #endif using GeneXus.Configuration; using GeneXus.Metadata; @@ -2359,8 +2361,8 @@ public short SetCookie(string name, string cookieValue, string path, DateTime ex Secure = cookie.Secure }; string sameSite; - SameSiteMode sameSiteMode = SameSiteMode.Unspecified; - if (Config.GetValueOf("SAMESITE_COOKIE", out sameSite) && Enum.TryParse(sameSite, out sameSiteMode)) + Microsoft.AspNetCore.Http.SameSiteMode sameSiteMode = Microsoft.AspNetCore.Http.SameSiteMode.Unspecified; + if (Config.GetValueOf("SAMESITE_COOKIE", out sameSite) && Enum.TryParse(sameSite, out sameSiteMode)) { cookieOptions.SameSite = sameSiteMode; } @@ -2429,55 +2431,83 @@ public byte SetHeader(string name, string value) private void SetCustomHttpHeader(string name, string value) { - _HttpContext.Response.AppendHeader(name, value); + try + { #if !NETCORE - switch (name.ToUpper()) - { - case "CACHE-CONTROL": - var Cache = _HttpContext.Response.Cache; - string[] values = value.Split(','); - foreach (string v in values) - { - switch (v.Trim().ToUpper()) + + switch (name.ToUpper()) + { + case "CACHE-CONTROL": + if (CacheControlHeaderValue.TryParse(value, out CacheControlHeaderValue parsedValue)) { - case "PUBLIC": - Cache.SetCacheability(HttpCacheability.Public); - break; - case "PRIVATE": - Cache.SetCacheability(HttpCacheability.Private); - break; - case "NO-CACHE": - Cache.SetCacheability(HttpCacheability.NoCache); - break; - case "NO-STORE": - Cache.AppendCacheExtension("no-store, must-revalidate"); - break; - default: - break; + HttpContext.Current.Response.Headers[name] = parsedValue.ToString(); } - } - break; - } + else + { + var Cache = _HttpContext.Response.Cache; + string[] values = value.Split(','); + foreach (string v in values) + { + switch (v.Trim().ToUpper()) + { + case "PUBLIC": + Cache.SetCacheability(HttpCacheability.Public); + break; + case "PRIVATE": + Cache.SetCacheability(HttpCacheability.Private); + break; + case "NO-CACHE": + Cache.SetCacheability(HttpCacheability.NoCache); + break; + case "NO-STORE": + Cache.AppendCacheExtension("no-store, must-revalidate"); + break; + default: + GXLogging.Warn(log, String.Format("Could not set Cache Control Http Header Value '{0}' to HttpResponse", value)); + break; + } + } + } + break; + default: + _HttpContext.Response.Headers[name] = value; + break; + } #else - switch (name.ToUpper()) + switch (name.ToUpper()) + { + case "CACHE-CONTROL": + if (CacheControlHeaderValue.TryParse(value, out CacheControlHeaderValue parsedValue)) + { + _HttpContext.Response.GetTypedHeaders().CacheControl = parsedValue; + } + else + { + switch (value.ToUpper()) + { + case "PUBLIC": + _HttpContext.Response.AddHeader("Cache-Control", "public"); + break; + case "PRIVATE": + _HttpContext.Response.AddHeader("Cache-Control", "private"); + break; + default: + GXLogging.Warn(log, String.Format("Could not set Cache Control Http Header Value '{0}' to HttpResponse", value)); + break; + } + } + break; + default: + _HttpContext.Response.AddHeader(name, value); + break; + } +#endif + } + catch (Exception ex) { - case "CACHE-CONTROL": - switch (value.ToUpper()) - { - case "PUBLIC": - _HttpContext.Response.AddHeader("Cache-Control", "public"); - break; - case "PRIVATE": - _HttpContext.Response.AddHeader("Cache-Control", "private"); - break; - default: - GXLogging.Warn(log, String.Format("Could not set Cache Control Http Header Value '{0}' to HttpResponse", value)); - break; - } - break; + GXLogging.Error(log, ex, "Error adding header ", name, value); } -#endif } public string GetHeader(string name) diff --git a/dotnet/test/DotNetCoreUnitTest/Domain/GxHttpResponseTest.cs b/dotnet/test/DotNetCoreUnitTest/Domain/GxHttpResponseTest.cs new file mode 100644 index 000000000..daf8bb9b6 --- /dev/null +++ b/dotnet/test/DotNetCoreUnitTest/Domain/GxHttpResponseTest.cs @@ -0,0 +1,41 @@ +using System; +using GeneXus.Application; +using GeneXus.Http.Server; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; +using Microsoft.Net.Http.Headers; +using Xunit; + +namespace xUnitTesting +{ + + public class GxHttpResponseTest + { + [Fact] + public void CacheControlHeaderTest() + { + DefaultHttpContext httpContext = new DefaultHttpContext(); + + httpContext.Features.Set(new HttpRequestFeature()); + httpContext.Features.Set(new HttpResponseFeature()); + + int maxAgeSeconds = 1800; + int sharedMaxAgeSeconds = 3900; + GxContext context = new GxContext(); + context.HttpContext = httpContext; + GxHttpResponse httpresponse = new GxHttpResponse(context); + httpresponse.AppendHeader("Cache-Control", $"public, s-maxage={sharedMaxAgeSeconds}, max-age={maxAgeSeconds}, stale-while-revalidate=15, stale-if-error=3600"); + + CacheControlHeaderValue cacheControlHeaderValue = httpresponse.Response.GetTypedHeaders().CacheControl; + + TimeSpan maxAge = TimeSpan.FromSeconds(maxAgeSeconds); + TimeSpan sMaxAge = TimeSpan.FromSeconds(sharedMaxAgeSeconds); + + Assert.True(cacheControlHeaderValue.Public); + Assert.Equal(sMaxAge, cacheControlHeaderValue.SharedMaxAge); + Assert.Equal(maxAge, cacheControlHeaderValue.MaxAge); + Assert.Contains("stale-if-error=3600", cacheControlHeaderValue.ToString(), StringComparison.OrdinalIgnoreCase); + } + + } +} From b37047d25d7a7b24b65f0b7da724de793a524cd4 Mon Sep 17 00:00:00 2001 From: Gonzalo Date: Fri, 7 Jul 2023 14:01:21 -0300 Subject: [PATCH 004/164] Fix log4net GX_LOG_OUTPUT environment variable crash (#840) * Fix log4net exception * Fix log4net exception --- .../GxClasses/Configuration/LogConfiguration.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Configuration/LogConfiguration.cs b/dotnet/src/dotnetframework/GxClasses/Configuration/LogConfiguration.cs index 43495ecf7..38102430c 100644 --- a/dotnet/src/dotnetframework/GxClasses/Configuration/LogConfiguration.cs +++ b/dotnet/src/dotnetframework/GxClasses/Configuration/LogConfiguration.cs @@ -53,10 +53,10 @@ private static void SetupLog4NetFromEnvironmentVariables() if (!String.IsNullOrEmpty(appenderName)) { Hierarchy h = (Hierarchy) LogManager.GetRepository(); - IAppender appenderToAdd = h.GetAppenders().First(a => a.Name == appenderName); + IAppender appenderToAdd = h.GetAppenders().FirstOrDefault(a => a.Name == appenderName); if (appenderToAdd == null) { - LogConfiguration.logger.Error($"Appender '{appenderName}' was not found on Log4Net Config file"); + LogConfiguration.logger.Warn($"Appender '{appenderName}' was not found on Log4Net Config file"); return; } From 182bf36e4ea66ff01ac19b9b0edebff4b4c09dd8 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Sat, 8 Jul 2023 09:41:25 -0300 Subject: [PATCH 005/164] Set header CacheControl explicitly as the alternative way doesn't work in the initial request. (#844) --- dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs index e96e3814e..5f5c71a9f 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs @@ -2441,7 +2441,7 @@ private void SetCustomHttpHeader(string name, string value) case "CACHE-CONTROL": if (CacheControlHeaderValue.TryParse(value, out CacheControlHeaderValue parsedValue)) { - HttpContext.Current.Response.Headers[name] = parsedValue.ToString(); + HttpContext.Current.Response.CacheControl = parsedValue.ToString(); } else { From 22a2c82d21c041161efedd82a406aac660910cfb Mon Sep 17 00:00:00 2001 From: Gonzalo Date: Tue, 11 Jul 2023 22:40:03 -0300 Subject: [PATCH 006/164] Partially Revert PR#823 (#846) --- .../GxClasses/Domain/GxHttpClient.cs | 109 +++--------------- 1 file changed, 18 insertions(+), 91 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs index 67d28923e..debd2d04b 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs @@ -66,7 +66,6 @@ public class GxHttpClient : IGxHttpClient, IDisposable const int StreamWriterDefaultBufferSize = 1024; Stream _sendStream; byte[] _receiveData; - StreamReader _receiveStream; int _timeout = 30000; short _statusCode = 0; string _proxyHost; @@ -134,14 +133,6 @@ internal byte[] ReceiveData { get { - if (_chunkedResponse && _receiveData == null && _receiveStream!=null) - { - using (MemoryStream memstream = new MemoryStream()) - { - _receiveStream.BaseStream.CopyTo(memstream); - _receiveData = memstream.ToArray(); - } - } return _receiveData; } } @@ -423,7 +414,6 @@ public void AddHeader(string name, string value) GXLogging.Error(log, String.Format("Error parsing charset ", value, ex)); } } - _headers.Set(name, value); } public void ClearVariables() @@ -707,7 +697,7 @@ HttpResponseMessage ExecuteRequest(string method, string requestUrl, CookieConta reqStream.Seek(0, SeekOrigin.Begin); request.Content = new ByteArrayContent(reqStream.ToArray()); setHeaders(request, handler.CookieContainer); - response = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).GetAwaiter().GetResult(); + response = client.SendAsync(request).GetAwaiter().GetResult(); } } return response; @@ -718,7 +708,6 @@ void ReadReponseContent(HttpResponseMessage response) try { Stream stream = response.Content.ReadAsStreamAsync().GetAwaiter().GetResult(); - _chunkedResponse = response.Headers.TransferEncodingChunked.HasValue && response.Headers.TransferEncodingChunked.Value; string charset; if (response.Content.Headers.ContentType == null) charset = null; @@ -741,28 +730,18 @@ void ReadReponseContent(HttpResponseMessage response) charset = String.Empty; } } - if (_chunkedResponse) + + using (MemoryStream ms = new MemoryStream()) { - if (_encoding == null) - _encoding = Encoding.UTF8; - - _receiveStream = new StreamReader(stream, _encoding); - _receiveData = null; + stream.CopyTo(ms); + _receiveData = ms.ToArray(); } - else + int bytesRead = _receiveData.Length; + GXLogging.Debug(log, "BytesRead " + _receiveData.Length); + if (bytesRead > 0 && !encodingFound) { - using (MemoryStream ms = new MemoryStream()) - { - 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); - } - } + _encoding = DetectEncoding(charset, out encodingFound, _receiveData, bytesRead); + } } catch (IOException ioEx) { @@ -808,7 +787,7 @@ public void Execute(string method, string name) public void HttpClientExecute(string method, string name) { - response = null; + HttpResponseMessage response = null; Byte[] Buffer = new Byte[1024]; _errCode = 0; _errDescription = string.Empty; @@ -889,11 +868,11 @@ public void HttpClientExecute(string method, string name) _errDescription = "The remote server returned an error: (" + _statusCode + ") " + _statusDescription + "."; } ClearSendStream(); + GXLogging.DebugSanitized(log, "_responseString " + ToString()); } NameValueCollection _respHeaders; private bool disposedValue; - private bool _chunkedResponse; - HttpResponseMessage response; + void LoadResponseHeaders(HttpResponseMessage resp) { _respHeaders = new NameValueCollection(); @@ -1381,65 +1360,14 @@ private Encoding ExtractEncodingFromCharset(string responseText, string regExpP, } return enc; } - public bool Eof - { - get - { - if (_chunkedResponse && _receiveStream != null) - { - return _receiveStream.EndOfStream; - } - return true; - } - } - public string ReadChunk() - { - if (_chunkedResponse) - { - if (_receiveStream != null) - { - if (!_receiveStream.EndOfStream) - { - string line = _receiveStream.ReadLine(); - if (line != null) - return line; - } - else - { - _receiveStream.Dispose(); - _receiveStream = null; - response.Dispose(); - response = null; - } - } - return string.Empty; - } - else - return ToString(); - } public override string ToString() { - string responseString; - if (_chunkedResponse) - { - StringBuilder sb = new StringBuilder(); - while (!Eof){ - sb.Append(ReadChunk()); - } - responseString = sb.ToString(); - } - else - { - if (_encoding == null) - _encoding = Encoding.UTF8; - if (_receiveData == null) - return string.Empty; - - responseString = _encoding.GetString(_receiveData); - } - GXLogging.DebugSanitized(log, "_responseString " + responseString); - return responseString; + if (_encoding == null) + _encoding = Encoding.UTF8; + if (_receiveData == null) + return string.Empty; + return _encoding.GetString(_receiveData); } public void ToFile(string fileName) { @@ -1529,7 +1457,6 @@ protected virtual void Dispose(bool disposing) { _receiveData = null; _sendStream?.Dispose(); - _receiveStream?.Dispose(); } disposedValue = true; } From 3ba6c6852029e8b7c52af2803e43d83d55d0edd1 Mon Sep 17 00:00:00 2001 From: sgrampone <30872877+sgrampone@users.noreply.github.com> Date: Wed, 12 Jul 2023 15:07:17 -0300 Subject: [PATCH 007/164] Manage exceptions on JWT creation with null keys. (#847) --- .../GeneXusJWT/JWT/JWTCreator.cs | 20 +++++++++ .../SecurityAPITestNetCore.csproj | 1 + .../Jwt/Other/TestIssue103626.cs | 45 +++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Jwt/Other/TestIssue103626.cs diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusJWT/JWT/JWTCreator.cs b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusJWT/JWT/JWTCreator.cs index 5b461b901..aead850e9 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusJWT/JWT/JWTCreator.cs +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusJWT/JWT/JWTCreator.cs @@ -182,6 +182,11 @@ private string Create_Aux(string algorithm, PrivateClaims privateClaims, JWTOpti { PrivateKeyManager key = options.GetPrivateKey(); + if(key == null) + { + this.error.setError("JW018", "Add the private key using JWTOptions.SetPrivateKey function"); + return ""; + } if (key.HasError()) { this.error = key.GetError(); @@ -209,6 +214,11 @@ private string Create_Aux(string algorithm, PrivateClaims privateClaims, JWTOpti } else { + if(options.getSecret() == null) + { + this.error.setError("JW021", "Set the secret using JWTOptions.SetSecret function"); + return ""; + } SymmetricSecurityKey symKey = new SymmetricSecurityKey(options.getSecret()); genericKey = symKey; } @@ -318,6 +328,11 @@ private bool DoVerify(string token, string expectedAlgorithm, PrivateClaims priv if (JWTAlgorithmUtils.isPrivate(alg)) { PublicKey cert = options.GetPublicKey(); + if(cert == null) + { + this.error.setError("JW022", "Public key or certificate not loaded for verification"); + return false; + } if (cert.HasError()) { this.error = cert.GetError(); @@ -345,6 +360,11 @@ private bool DoVerify(string token, string expectedAlgorithm, PrivateClaims priv } else { + if(options.getSecret() == null) + { + this.error.setError("JW022", "Symmetric key not loaded for verification"); + return false; + } SymmetricSecurityKey symKey = new SymmetricSecurityKey(options.getSecret()); genericKey = symKey; } diff --git a/dotnet/src/extensions/SecurityAPI/test/dotnetcore/SecurityAPITestNetCore/SecurityAPITestNetCore.csproj b/dotnet/src/extensions/SecurityAPI/test/dotnetcore/SecurityAPITestNetCore/SecurityAPITestNetCore.csproj index e76f072c8..3bc09ce1d 100644 --- a/dotnet/src/extensions/SecurityAPI/test/dotnetcore/SecurityAPITestNetCore/SecurityAPITestNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/test/dotnetcore/SecurityAPITestNetCore/SecurityAPITestNetCore.csproj @@ -38,6 +38,7 @@ + diff --git a/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Jwt/Other/TestIssue103626.cs b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Jwt/Other/TestIssue103626.cs new file mode 100644 index 000000000..b7c66c845 --- /dev/null +++ b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Jwt/Other/TestIssue103626.cs @@ -0,0 +1,45 @@ +using GeneXusJWT.GenexusComons; +using GeneXusJWT.GenexusJWT; +using GeneXusJWT.GenexusJWTClaims; +using NUnit.Framework; +using SecurityAPITest.SecurityAPICommons.commons; + +namespace SecurityAPITest.Jwt.Other +{ + [TestFixture] + public class TestIssue103626: SecurityAPITestObject + { + protected static JWTOptions options; + protected static PrivateClaims claims; + protected static JWTCreator jwt; + protected static string token; + + [SetUp] + public virtual void SetUp() + { + jwt = new JWTCreator(); + options = new JWTOptions(); + claims = new PrivateClaims(); + + claims.setClaim("hola1", "hola1"); + claims.setClaim("hola2", "hola2"); + + } + + [Test] + public void Test_SymmetricError() + { + string dummytoken = jwt.DoCreate("HS256", claims, options); + Assert.IsTrue(jwt.HasError()); + + } + + [Test] + public void Test_AsymmetricError() + { + string dummytoken = jwt.DoCreate("RS256", claims, options); + Assert.IsTrue(jwt.HasError()); + + } + } +} From 650a17c5a44c017f5e157434a7ef3e8f55a00226 Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Wed, 12 Jul 2023 20:27:07 -0300 Subject: [PATCH 008/164] Deploy files conditioned to Azure Functions trigger (#842) --- ...eXus.Deploy.AzureFunctions.Handlers.csproj | 48 +++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj b/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj index 4edc625d9..b8ce2e81d 100644 --- a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj +++ b/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj @@ -6,25 +6,67 @@ false GeneXus.Deploy.AzureFunctions.Handlers 1701;1702;NU1701 + false + + + true + true + true + true + true + + portable none + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + From b334f4adab4c51117708fbd67a05aee5becd2f7c Mon Sep 17 00:00:00 2001 From: sgrampone <30872877+sgrampone@users.noreply.github.com> Date: Fri, 21 Jul 2023 15:48:10 -0300 Subject: [PATCH 009/164] Base64UrlEncoder implementation (#849) --- .../SecurityAPICommonsNetCore.csproj | 3 +- .../Encoders/Base64UrlEncoder.cs | 161 ++++++++++++++++++ .../SecurityAPITestNetCore.csproj | 1 + .../encoders/TestBase64Url.cs | 68 ++++++++ 4 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/Encoders/Base64UrlEncoder.cs create mode 100644 dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/SecurityAPICommons/encoders/TestBase64Url.cs diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/SecurityAPICommonsNetCore/SecurityAPICommonsNetCore.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/SecurityAPICommonsNetCore/SecurityAPICommonsNetCore.csproj index 28c91eaaa..387b02292 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/SecurityAPICommonsNetCore/SecurityAPICommonsNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/SecurityAPICommonsNetCore/SecurityAPICommonsNetCore.csproj @@ -1,4 +1,4 @@ - + net6.0 @@ -23,6 +23,7 @@ + diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/Encoders/Base64UrlEncoder.cs b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/Encoders/Base64UrlEncoder.cs new file mode 100644 index 000000000..f300d761a --- /dev/null +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/Encoders/Base64UrlEncoder.cs @@ -0,0 +1,161 @@ +using System; +using System.Security; +using SecurityAPICommons.Commons; +using SecurityAPICommons.Config; +using Org.BouncyCastle.Utilities.Encoders; +using System.Text; + +namespace SecurityAPICommons.Encoders +{ + [SecuritySafeCritical] + public class Base64UrlEncoder: SecurityAPIObject + { + [SecuritySafeCritical] + public Base64UrlEncoder() : base() + { + + } + + [SecuritySafeCritical] + public string toBase64(string text) + { + this.error.cleanError(); + EncodingUtil eu = new EncodingUtil(); + byte[] textBytes = eu.getBytes(text); + if (eu.HasError()) + { + this.error = eu.GetError(); + return ""; + } + string result = ""; + try + { + byte[] resultBytes = UrlBase64.Encode(textBytes); + result = Encoding.UTF8.GetString(resultBytes); + } + catch (Exception e) + { + this.error.setError("BS001", e.Message); + return ""; + } + return result; + } + + [SecuritySafeCritical] + public string toPlainText(string base64Text) + { + this.error.cleanError(); + byte[] bytes; + try + { + bytes = UrlBase64.Decode(base64Text); + } + catch (Exception e) + { + this.error.setError("BS002", e.Message); + return ""; + } + EncodingUtil eu = new EncodingUtil(); + string result = eu.getString(bytes); + if (eu.HasError()) + { + this.error = eu.GetError(); + return ""; + } + return result; + } + + [SecuritySafeCritical] + public string toStringHexa(string base64Text) + { + this.error.cleanError(); + byte[] bytes; + try + { + bytes = UrlBase64.Decode(base64Text); + } + catch (Exception e) + { + this.error.setError("BS003", e.Message); + return ""; + } + string result = ""; + try + { + result = Hex.ToHexString(bytes).ToUpper(); + } + catch (Exception e) + { + this.error.setError("BS004", e.Message); + return ""; + } + return result; + } + + [SecuritySafeCritical] + public string fromStringHexaToBase64(string stringHexa) + { + this.error.cleanError(); + byte[] stringBytes; + try + { + stringBytes = Hex.Decode(stringHexa); + } + catch (Exception e) + { + this.error.setError("BS005", e.Message); + return ""; + } + string result = ""; + try + { + byte[] resultBytes = UrlBase64.Encode(stringBytes); + result = Encoding.UTF8.GetString(resultBytes); + } + catch (Exception e) + { + this.error.setError("BS006", e.Message); + return ""; + } + return result; + } + + [SecuritySafeCritical] + public string base64ToBase64Url(string base64Text) + { + this.error.cleanError(); + string result = ""; + try + { + byte[] b64bytes = Base64.Decode(base64Text); + byte[] bytes = UrlBase64.Encode(b64bytes); + result = Encoding.UTF8.GetString(bytes); + } + catch (Exception e) + { + this.error.setError("BS007", e.Message); + return ""; + } + return result; + } + + [SecuritySafeCritical] + public string base64UrlToBase64(string base64UrlText) + { + this.error.cleanError(); + string result = ""; + try + { + byte[] b64bytes = UrlBase64.Decode(base64UrlText); + byte[] bytes = Base64.Encode(b64bytes); + result = Encoding.UTF8.GetString(bytes); + } + catch (Exception e) + { + this.error.setError("BS008", e.Message); + return ""; + } + return result; + } + } +} diff --git a/dotnet/src/extensions/SecurityAPI/test/dotnetcore/SecurityAPITestNetCore/SecurityAPITestNetCore.csproj b/dotnet/src/extensions/SecurityAPI/test/dotnetcore/SecurityAPITestNetCore/SecurityAPITestNetCore.csproj index 3bc09ce1d..49600c43b 100644 --- a/dotnet/src/extensions/SecurityAPI/test/dotnetcore/SecurityAPITestNetCore/SecurityAPITestNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/test/dotnetcore/SecurityAPITestNetCore/SecurityAPITestNetCore.csproj @@ -48,6 +48,7 @@ + diff --git a/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/SecurityAPICommons/encoders/TestBase64Url.cs b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/SecurityAPICommons/encoders/TestBase64Url.cs new file mode 100644 index 000000000..d5c3d432c --- /dev/null +++ b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/SecurityAPICommons/encoders/TestBase64Url.cs @@ -0,0 +1,68 @@ +using SecurityAPICommons.Encoders; +using SecurityAPITest.SecurityAPICommons.commons; +using NUnit.Framework; + +namespace SecurityAPITest.SecurityAPICommons.encoders +{ + [TestFixture] + public class TestBase64Url: SecurityAPITestObject + { + protected static string expected_plainText; + protected static string expected_encoded; + protected static string expected_hexaText; + protected static Base64UrlEncoder base64; + protected static string expected_base64; + + [SetUp] + public virtual void SetUp() + { + expected_plainText = "hello world"; + expected_encoded = "aGVsbG8gd29ybGQ."; + expected_hexaText = "68656C6C6F20776F726C64"; + base64 = new Base64UrlEncoder(); + expected_base64 = "aGVsbG8gd29ybGQ="; + } + + [Test] + public void TestToBase64Url() + { + string encoded = base64.toBase64(expected_plainText); + Equals(expected_encoded, encoded, base64); + } + + [Test] + public void TestToPlainTextUrl() + { + string plainText = base64.toPlainText(expected_encoded); + Equals(expected_plainText, plainText, base64); + } + + [Test] + public void TestToStringHexaUrl() + { + string hexaText = base64.toStringHexa(expected_encoded); + Equals(expected_hexaText, hexaText, base64); + } + + [Test] + public void TestFromStringHexaToBase64Url() + { + string encoded = base64.fromStringHexaToBase64(expected_hexaText); + Equals(expected_encoded, encoded, base64); + } + + [Test] + public void TestBase64UrlToBase64() + { + string encoded = base64.base64UrlToBase64(expected_encoded); + Equals(expected_base64, encoded, base64); + } + + [Test] + public void TestBase64ToBase64Url() + { + string encoded = base64.base64ToBase64Url(expected_base64); + Equals(expected_encoded, encoded, base64); + } + } +} From 681d468d0520759243add0be32c9b44ddcadceb0 Mon Sep 17 00:00:00 2001 From: sgrampone <30872877+sgrampone@users.noreply.github.com> Date: Fri, 21 Jul 2023 15:48:32 -0300 Subject: [PATCH 010/164] UnixTimestampCreator Implementation (#850) * UnixTimestamp implementation * Fix error on unix time stamp calculation in time validating claims * Try fix date utc issue on github server * Revert fix time validating claims unix timestamp calculations in utc --- .../GeneXusJWTNetCore.csproj | 1 + .../GeneXusJWT/JWTClaims/RegisteredClaims.cs | 5 +-- .../GeneXusJWT/Utils/UnixTimeStampCreator.cs | 31 ++++++++++++++++ .../SecurityAPITestNetCore.csproj | 1 + .../Jwt/Features/TestUnixTimeStampCreator.cs | 36 +++++++++++++++++++ .../Jwt/Other/TestIssue83649.cs | 8 +++-- 6 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusJWT/Utils/UnixTimeStampCreator.cs create mode 100644 dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Jwt/Features/TestUnixTimeStampCreator.cs diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj index f211b6d98..b6e836963 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj @@ -25,6 +25,7 @@ + diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusJWT/JWTClaims/RegisteredClaims.cs b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusJWT/JWTClaims/RegisteredClaims.cs index f3df80060..f1e3d9794 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusJWT/JWTClaims/RegisteredClaims.cs +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusJWT/JWTClaims/RegisteredClaims.cs @@ -43,8 +43,9 @@ public bool setTimeValidatingClaim(string key, string value, string customValida customTimeValidationClaims.Add(key, customValidationSeconds); try { - date = (Int32)DateTime.ParseExact(value, "yyyy/MM/dd HH:mm:ss", CultureInfo.InvariantCulture).Subtract(new DateTime(1970, 1, 1)).TotalSeconds; - } + // date = (Int32)DateTime.ParseExact(value, "yyyy/MM/dd HH:mm:ss", CultureInfo.InvariantCulture).ToUniversalTime().Subtract(new DateTime(1970, 1, 1)).TotalSeconds; + date = (Int32)DateTime.ParseExact(value, "yyyy/MM/dd HH:mm:ss", CultureInfo.InvariantCulture).Subtract(new DateTime(1970, 1, 1)).TotalSeconds; + } catch (Exception) { error.setError("RCS04", "Date format error; expected yyyy/MM/dd HH:mm:ss"); diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusJWT/Utils/UnixTimeStampCreator.cs b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusJWT/Utils/UnixTimeStampCreator.cs new file mode 100644 index 000000000..e5adec932 --- /dev/null +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusJWT/Utils/UnixTimeStampCreator.cs @@ -0,0 +1,31 @@ +using System; +using System.Globalization; +using System.Security; +using SecurityAPICommons.Commons; + +namespace GeneXusJWT.Utils +{ + [SecuritySafeCritical] + public class UnixTimeStampCreator: SecurityAPIObject + { + [SecuritySafeCritical] + public UnixTimeStampCreator() : base() { } + + [SecuritySafeCritical] + public string Create(string date) + { + long newdate; + try + { + //newdate= (long)DateTime.ParseExact(date, "yyyy/MM/dd HH:mm:ss", CultureInfo.InvariantCulture).ToUniversalTime().Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).ToUniversalTime()).TotalSeconds; + newdate = (long)DateTime.ParseExact(date, "yyyy/MM/dd HH:mm:ss", CultureInfo.InvariantCulture).Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds; + } + catch (Exception) + { + error.setError("UTS01", "Date format error; expected yyyy/MM/dd HH:mm:ss"); + return ""; + } + return newdate.ToString(CultureInfo.InvariantCulture); + } + } +} diff --git a/dotnet/src/extensions/SecurityAPI/test/dotnetcore/SecurityAPITestNetCore/SecurityAPITestNetCore.csproj b/dotnet/src/extensions/SecurityAPI/test/dotnetcore/SecurityAPITestNetCore/SecurityAPITestNetCore.csproj index 49600c43b..c95d421fe 100644 --- a/dotnet/src/extensions/SecurityAPI/test/dotnetcore/SecurityAPITestNetCore/SecurityAPITestNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/test/dotnetcore/SecurityAPITestNetCore/SecurityAPITestNetCore.csproj @@ -37,6 +37,7 @@ + diff --git a/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Jwt/Features/TestUnixTimeStampCreator.cs b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Jwt/Features/TestUnixTimeStampCreator.cs new file mode 100644 index 000000000..4bcf7b62a --- /dev/null +++ b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Jwt/Features/TestUnixTimeStampCreator.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using GeneXusJWT.Utils; +using NUnit.Framework; +using SecurityAPITest.SecurityAPICommons.commons; + +namespace SecurityAPITest.Jwt.Features +{ + [TestFixture] + public class TestUnixTimeStampCreator: SecurityAPITestObject + { + protected static string date; + protected static UnixTimeStampCreator creator; + protected static string expected; + + [SetUp] + public virtual void SetUp() + { + date = "2023/07/19 11:41:00"; + creator = new UnixTimeStampCreator(); + expected = "1689766860"; + + } + + [Test] + public void TestCreate() + { + string obtained = creator.Create(date); + //Console.WriteLine("obt:" + obtained); + Equals(expected, obtained, creator); + } + } +} diff --git a/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Jwt/Other/TestIssue83649.cs b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Jwt/Other/TestIssue83649.cs index 96ca423e4..ce78faac0 100644 --- a/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Jwt/Other/TestIssue83649.cs +++ b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Jwt/Other/TestIssue83649.cs @@ -1,4 +1,4 @@ -using SecurityAPITest.SecurityAPICommons.commons; +using SecurityAPITest.SecurityAPICommons.commons; using System; using System.Collections.Generic; using System.Linq; @@ -42,12 +42,14 @@ public virtual void SetUp() payload = jwt.GetPayload(token); - expected = "{\"hola1\":\"hola1\",\"exp\":1595267811,\"iat\":1595267811,\"nbf\":1595267811}"; - } + //expected = "{\"hola1\":\"hola1\",\"exp\":1595278611,\"iat\":1595278611,\"nbf\":1595278611}"; + expected = "{\"hola1\":\"hola1\",\"exp\":1595267811,\"iat\":1595267811,\"nbf\":1595267811}"; + } [Test] public void Test_timeClaims() { + //Console.WriteLine(payload); Assert.IsTrue(SecurityUtils.compareStrings(expected, payload)); } From a9c0a9d20fa04ded8910ad03d32b9c6810e0dc61 Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Wed, 26 Jul 2023 10:43:18 -0300 Subject: [PATCH 011/164] Azure Event Grid API implementation (#848) --- dotnet/DotNetStandardClasses.sln | 14 + .../GxClasses/Properties/AssemblyInfo.cs | 1 + .../GXAzureEventGrid/AzureEventGrid.cs | 297 ++++++++++++++++++ .../EventGridRouterProvider.cs | 26 ++ .../GXAzureEventGrid/GXAzureEventGrid.csproj | 17 + .../GXAzureQueue/GXAzureQueue.csproj | 2 +- .../GXAzureServiceBus.csproj | 2 +- .../Messaging/GXEventRouter/EventRouter.cs | 27 ++ .../GXEventRouter/EventRouterBase.cs | 33 ++ .../GXEventRouter/EventRouterProvider.cs | 113 +++++++ .../GXEventRouter/EventRouterProviderBase.cs | 226 +++++++++++++ .../GXEventRouter/GXEventRouter.csproj | 17 + .../GXEventRouter/PropertyConstants.cs | 17 + .../Messaging/GXQueue/GXQueue.csproj | 4 + .../Messaging/GXQueue/ServiceSettings.cs | 101 ------ .../GxClasses/Services/Storage/GXServices.cs | 1 + 16 files changed, 795 insertions(+), 103 deletions(-) create mode 100644 dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/AzureEventGrid.cs create mode 100644 dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/EventGridRouterProvider.cs create mode 100644 dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj create mode 100644 dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouter.cs create mode 100644 dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterBase.cs create mode 100644 dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterProvider.cs create mode 100644 dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterProviderBase.cs create mode 100644 dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/GXEventRouter.csproj create mode 100644 dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/PropertyConstants.cs delete mode 100644 dotnet/src/dotnetcore/Providers/Messaging/GXQueue/ServiceSettings.cs diff --git a/dotnet/DotNetStandardClasses.sln b/dotnet/DotNetStandardClasses.sln index 8650b334f..4822f78c0 100644 --- a/dotnet/DotNetStandardClasses.sln +++ b/dotnet/DotNetStandardClasses.sln @@ -243,6 +243,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GxOffice", "src\dotnetcore\ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "excel", "excel", "{B521FF6D-E081-4DE6-AC00-A9BE3B6439D1}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GXEventRouter", "src\dotnetcore\Providers\Messaging\GXEventRouter\GXEventRouter.csproj", "{5BBC75F0-E51A-4EBD-A628-92498D319B1D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GXAzureEventGrid", "src\dotnetcore\Providers\Messaging\GXAzureEventGrid\GXAzureEventGrid.csproj", "{7250CDB1-95C4-4822-B01B-3CBD73324CC9}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -585,6 +589,14 @@ Global {E1CD114A-F8A5-4246-B5E3-FD27EDEC7C82}.Debug|Any CPU.Build.0 = Debug|Any CPU {E1CD114A-F8A5-4246-B5E3-FD27EDEC7C82}.Release|Any CPU.ActiveCfg = Release|Any CPU {E1CD114A-F8A5-4246-B5E3-FD27EDEC7C82}.Release|Any CPU.Build.0 = Release|Any CPU + {5BBC75F0-E51A-4EBD-A628-92498D319B1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5BBC75F0-E51A-4EBD-A628-92498D319B1D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5BBC75F0-E51A-4EBD-A628-92498D319B1D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5BBC75F0-E51A-4EBD-A628-92498D319B1D}.Release|Any CPU.Build.0 = Release|Any CPU + {7250CDB1-95C4-4822-B01B-3CBD73324CC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7250CDB1-95C4-4822-B01B-3CBD73324CC9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7250CDB1-95C4-4822-B01B-3CBD73324CC9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7250CDB1-95C4-4822-B01B-3CBD73324CC9}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -701,6 +713,8 @@ Global {BE108BE8-805D-4FCF-86BA-B2EAF581FFB2} = {F900A4AD-7249-41B4-B918-CB9E8C73747C} {E1CD114A-F8A5-4246-B5E3-FD27EDEC7C82} = {B521FF6D-E081-4DE6-AC00-A9BE3B6439D1} {B521FF6D-E081-4DE6-AC00-A9BE3B6439D1} = {2261B65E-3757-4E5B-9DCD-EAE8D1E236A3} + {5BBC75F0-E51A-4EBD-A628-92498D319B1D} = {4C43F2DA-59E5-46F5-B691-195449498555} + {7250CDB1-95C4-4822-B01B-3CBD73324CC9} = {30159B0F-BE61-4DB7-AC02-02851426BE4B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E18684C9-7D76-45CD-BF24-E3944B7F174C} diff --git a/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs b/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs index 2109ab09c..80e2eff77 100644 --- a/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs +++ b/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs @@ -7,6 +7,7 @@ [assembly: InternalsVisibleTo("AzureFunctionsTest")] [assembly: InternalsVisibleTo("GXQueue")] [assembly: InternalsVisibleTo("GXMessageBroker")] +[assembly: InternalsVisibleTo("GXEventRouter")] [assembly: InternalsVisibleTo("DotNetCoreUnitTest")] [assembly: InternalsVisibleTo("DotNetCoreWebUnitTest")] [assembly: InternalsVisibleTo("GeneXus.Deploy.AzureFunctions.Handlers")] diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/AzureEventGrid.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/AzureEventGrid.cs new file mode 100644 index 000000000..584464ee4 --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/AzureEventGrid.cs @@ -0,0 +1,297 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Text.Json; +using System.Threading.Tasks; +using Azure; +using Azure.Messaging; +using Azure.Messaging.EventGrid; +using GeneXus.Messaging.Common; +using GeneXus.Services; +using GeneXus.Utils; + +namespace GeneXus.Messaging.GXAzureEventGrid +{ + public class AzureEventGrid : EventRouterBase, IEventRouter + { + public static string Name = "AZUREEVENTGRID"; + private EventGridPublisherClient _client; + private string _endpoint; + private string _accessKey; + public AzureEventGrid() : this(null) + { + } + public AzureEventGrid(GXService providerService) : base(providerService) + { + Initialize(providerService); + } + private void Initialize(GXService providerService) + { + ServiceSettings serviceSettings = new(PropertyConstants.EVENT_ROUTER, Name, providerService); + _endpoint = serviceSettings.GetEncryptedPropertyValue(PropertyConstants.URI_ENDPOINT); + _accessKey = serviceSettings.GetEncryptedPropertyValue(PropertyConstants.ACCESS_KEY); + + if (!string.IsNullOrEmpty(_endpoint)) { + + _client = new EventGridPublisherClient( + new Uri(_endpoint), + new AzureKeyCredential(_accessKey)); + } + else + throw new Exception("Endpoint URI must be set."); + } + public override string GetName() + { + return Name; + } + + public bool SendEvent(GXCloudEvent gxCloudEvent, bool binaryData) + { + CloudEvent evt = ToCloudEvent(gxCloudEvent, binaryData); + bool success = false; + try + { + Task task; + if (_client != null) + { + task = Task.Run(async () => await sendEvtAsync(evt).ConfigureAwait(false)); + success = true; + } + else + { + throw new Exception("There was an error at the Event Grid initialization."); + } + } + catch (AggregateException ae) + { + throw ae; + } + return success; + } + public bool SendEvents(IList gxCloudEvents, bool binaryData) + { + List evts = new List(); + foreach (GXCloudEvent e in gxCloudEvents) + evts.Add(ToCloudEvent(e, binaryData)); + + bool success = false; + try + { + Task task; + if (_client != null) + { + task = Task.Run(async () => await sendEvtsAsync(evts).ConfigureAwait(false)); + success = true; + } + else + { + throw new Exception("There was an error at the Event Grid initialization."); + } + } + catch (AggregateException ae) + { + throw ae; + } + return success; + } + public bool SendCustomEvents(string jsonString, bool isBinary) + { + if (string.IsNullOrEmpty(jsonString)) + { + throw new Exception("Events cannot be empty."); + } + try + { + List evts = JsonSerializer.Deserialize>(jsonString); + + IList eventGridEvents = new List(); + foreach (GXEventGridSchema e in evts) + eventGridEvents.Add(ToEventGridSchema(e,isBinary)); + + bool success = false; + try + { + Task task; + if (_client != null) + { + task = Task.Run(async () => await sendEventGridSchemaEventsAsync(eventGridEvents).ConfigureAwait(false)); + success = true; + } + else + { + throw new Exception("There was an error at the Event Grid initialization."); + } + } + catch (AggregateException ae) + { + throw ae; + } + return success; + } + catch (JsonException) + { + try + { + GXEventGridSchema evt = JsonSerializer.Deserialize(jsonString); + bool success = false; + try + { + Task task; + if (_client != null) + { + task = Task.Run(async () => await sendEventGridSchemaEventAsync(ToEventGridSchema(evt, isBinary)).ConfigureAwait(false)); + success = true; + } + else + { + throw new Exception("There was an error at the Event Grid initialization."); + } + } + catch (AggregateException ae) + { + throw ae; + } + return success; + } + catch (JsonException) + { + throw new Exception("jsonEvents parameter format is no correct. Valid format is AzureEventGrid.EventGridSchema SDT."); + } + } + } + + #region Async methods + /// + /// Send asynchronously an event formatted as Azure EventGrid Schema. + /// + /// + /// + private async Task sendEventGridSchemaEventAsync(EventGridEvent evt) + { + await _client.SendEventAsync(evt).ConfigureAwait(false); + + } + /// + /// Send asynchronously a list of events formatted as Azure EventGrid Schema. + /// + /// + /// + private async Task sendEventGridSchemaEventsAsync(IEnumerable evts) + { + await _client.SendEventsAsync(evts).ConfigureAwait(false); + } + /// + /// Send asynchronously an event formatted as CloudEvent Schema. + /// + /// + /// + private async Task sendEvtAsync(CloudEvent cloudEvent) + { + await _client.SendEventAsync(cloudEvent).ConfigureAwait(false); + + } + /// + /// Send asynchronously a list of CloudEvent Schema formatted events. + /// + /// + /// + private async Task sendEvtsAsync(IEnumerable cloudEvents) + { + await _client.SendEventsAsync(cloudEvents).ConfigureAwait(false); + } + + #endregion + + #region TransformMethods + public bool GetMessageFromException(Exception ex, SdtMessages_Message msg) + { + try + { + RequestFailedException az_ex = (RequestFailedException)ex; + msg.gxTpr_Id = az_ex.ErrorCode.ToString(); + msg.gxTpr_Description = az_ex.Message; + return true; + } + catch (Exception) + { + return false; + } + } + private EventGridEvent ToEventGridSchema(GXEventGridSchema gxEventGridSchema, bool isBinary) + { + EventGridEvent evt; + if (isBinary && !string.IsNullOrEmpty(gxEventGridSchema.data)) + { + BinaryData binaryData = new BinaryData(gxEventGridSchema.data); + evt = new EventGridEvent(gxEventGridSchema.subject, gxEventGridSchema.eventtype, gxEventGridSchema.dataversion, binaryData);} + else + evt = new EventGridEvent(gxEventGridSchema.subject, gxEventGridSchema.eventtype, gxEventGridSchema.dataversion, gxEventGridSchema.data, null); + if (!string.IsNullOrEmpty(gxEventGridSchema.id)) + evt.Id = gxEventGridSchema.id; + if (!string.IsNullOrEmpty(gxEventGridSchema.topic)) + evt.Topic = gxEventGridSchema.topic; + if (gxEventGridSchema.eventtime != DateTime.MinValue) + evt.EventTime = gxEventGridSchema.eventtime; + + return evt; + } + private CloudEvent ToCloudEvent(GXCloudEvent gxCloudEvent, bool isBinaryData) + { + CloudEvent evt; + Dictionary emptyData = new Dictionary(); + if (string.IsNullOrEmpty(gxCloudEvent.data)) + evt = new CloudEvent(source:gxCloudEvent.source, type:gxCloudEvent.type, emptyData); + else + { + if (!isBinaryData) + { + if (string.IsNullOrEmpty(gxCloudEvent.datacontenttype)) + gxCloudEvent.datacontenttype = "application/json"; + evt = new CloudEvent(gxCloudEvent.source, gxCloudEvent.type, BinaryData.FromString(gxCloudEvent.data),gxCloudEvent.datacontenttype,CloudEventDataFormat.Json); + } + else + { + if (string.IsNullOrEmpty(gxCloudEvent.datacontenttype)) + gxCloudEvent.datacontenttype = "application/octet-stream"; + evt = new CloudEvent(gxCloudEvent.source, gxCloudEvent.type, BinaryData.FromString(gxCloudEvent.data), gxCloudEvent.datacontenttype,CloudEventDataFormat.Binary); + } + } + if (!string.IsNullOrEmpty(gxCloudEvent.id)) + evt.Id = gxCloudEvent.id; + if (!string.IsNullOrEmpty(gxCloudEvent.dataschema)) + evt.DataSchema = gxCloudEvent.dataschema; + if (!string.IsNullOrEmpty(gxCloudEvent.subject)) + evt.Subject = gxCloudEvent.subject; + if (gxCloudEvent.time != DateTime.MinValue) + evt.Time = gxCloudEvent.time; + return evt; + } + #endregion + } + + [DataContract] + public class GXEventGridSchema + { + [DataMember] + public string topic { get; set; } + [DataMember] + public string eventtype { get; set; } + [DataMember] + public string id { get; set; } + [DataMember] + public string subject { get; set; } + [DataMember] + public string data { get; set; } + [DataMember] + public string dataversion { get; set; } + + [DataMember] + public DateTime eventtime { get; set; } + + [DataMember] + public string metadataversion { get; set; } + + + } +} \ No newline at end of file diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/EventGridRouterProvider.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/EventGridRouterProvider.cs new file mode 100644 index 000000000..f8c9e20ae --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/EventGridRouterProvider.cs @@ -0,0 +1,26 @@ +using GeneXus.Messaging.Common; +using GeneXus.Utils; + +namespace GeneXus.Messaging.GXAzureEventGrid +{ + /// + /// Implementation of EventGridRouterProvider External Object. + /// + public class EventGridRouterProvider + { + public EventRouterProviderBase Connect(string endpoint, string accesskey, out GXBaseCollection errorMessages, out bool success) + { + EventRouterProvider eventRouterProvider = new EventRouterProvider(); + GXProperties properties = new GXProperties + { + { PropertyConstants.EVENTROUTER_AZUREEG_ENDPOINT, endpoint }, + { PropertyConstants.EVENTROUTER_AZUREEG_ACCESS_KEY, accesskey } + }; + + EventRouterProviderBase evtRouterProvider = eventRouterProvider.Connect(PropertyConstants.AZUREEVENTGRID, properties, out GXBaseCollection errorMessagesConnect, out bool successConnect); + errorMessages = errorMessagesConnect; + success = successConnect; + return evtRouterProvider; + } + } +} diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj new file mode 100644 index 000000000..0dd71f20c --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj @@ -0,0 +1,17 @@ + + + + net6.0 + GeneXus.Azure.EventGrid + Azure EventGrid Messaging + + + + + + + + + + + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj index a9fc132d3..491be781c 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj @@ -7,7 +7,7 @@ - + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj index ac8137a4a..2de414bc5 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj @@ -7,7 +7,7 @@ - + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouter.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouter.cs new file mode 100644 index 000000000..56fa53a2a --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouter.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using GeneXus.Utils; + +namespace GeneXus.Messaging.Common +{ + public interface IEventRouter + { + bool SendEvent(GXCloudEvent gxCloudEvent, bool binaryData); + bool SendEvents(IList gxCloudEvents, bool binaryData); + bool SendCustomEvents(string jsonString, bool isBinary); + bool GetMessageFromException(Exception ex, SdtMessages_Message msg); + } + public class GXCloudEvent : GxUserType + { + public string type { get; set; } + public string source { get; set; } + public string data { get; set; } + public string datacontenttype { get; set; } + public string id { get; set; } + public string dataschema { get; set; } + public string subject { get; set; } + public string data_base64 { get; set; } + public DateTime time { get; set; } + } + +} \ No newline at end of file diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterBase.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterBase.cs new file mode 100644 index 000000000..d8db3aeb0 --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterBase.cs @@ -0,0 +1,33 @@ +using System; +using GeneXus.Services; +using log4net; + +namespace GeneXus.Messaging.Common +{ + public abstract class EventRouterBase + { + static readonly ILog logger = LogManager.GetLogger(typeof(EventRouterBase)); + internal GXService service; + public EventRouterBase() + { + } + + public EventRouterBase(GXService s) + { + if (s == null) + { + try + { + s = ServiceFactory.GetGXServices()?.Get(GXServices.EVENTROUTER_SERVICE); + } + catch (Exception) + { + GXLogging.Warn(logger, "EVENTROUTER_SERVICE is not activated"); + } + } + + service = s; + } + public abstract string GetName(); + } +} diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterProvider.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterProvider.cs new file mode 100644 index 000000000..410543865 --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterProvider.cs @@ -0,0 +1,113 @@ +using System; +using GeneXus.Attributes; +using GeneXus.Encryption; +using GeneXus.Services; +using GeneXus.Utils; +using GxClasses.Helpers; +using log4net; + +namespace GeneXus.Messaging.Common +{ + [GXApi] + public class EventRouterProvider : EventRouterProviderBase + { + static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + private static GXService providerService; + public EventRouterProvider() { + } + public EventRouterProviderBase Connect(string providerTypeName, GXProperties properties, out GXBaseCollection errorMessages, out bool success) + { + errorMessages = new GXBaseCollection(); + EventRouterProviderBase eventRouter = new EventRouterProviderBase(); + if (string.IsNullOrEmpty(providerTypeName)) + { + GXUtil.ErrorToMessages("GXEventRouter", "Event Router provider cannot be empty", errorMessages); + GXLogging.Error(logger, "(GXEventRouter)Failed to Connect to a Event Router : Provider cannot be empty."); + success = false; + return eventRouter; + } + try + { + if (providerService == null || !string.Equals(providerService.Name, providerTypeName, StringComparison.OrdinalIgnoreCase)) + { + providerService = new GXService(); + providerService.Type = GXServices.EVENTROUTER_SERVICE; + providerService.Name = providerTypeName; + providerService.AllowMultiple = false; + providerService.Properties = new GXProperties(); + } + Preprocess(providerTypeName, properties); + + GxKeyValuePair prop = properties.GetFirst(); + while (!properties.Eof()) + { + providerService.Properties.Set(prop.Key, prop.Value); + prop = properties.GetNext(); + } + + string typeFullName = providerService.ClassName; + GXLogging.Debug(logger, "Loading Event Router provider: " + typeFullName); + Type type = AssemblyLoader.GetType(typeFullName); + eventRouter.eventRouter = (IEventRouter)Activator.CreateInstance(type, new object[] { providerService }); + + } + catch (Exception ex) + { + GXLogging.Error(logger, "(GXEventRouter)Couldn't connect to Event Router provider: " + ExceptionExtensions.GetInnermostException(ex)); + GXUtil.ErrorToMessages("GXEventRouter", ex, errorMessages); + success = false; + return eventRouter; + } + success = true; + return (eventRouter); + } + private static void Preprocess(string name, GXProperties properties) + { + string className; + + switch (name) + { + case Providers.AzureEventGrid: + className = PropertyConstants.AZURE_EG_CLASSNAME; + SetEncryptedProperty(properties, PropertyConstants.EVENTROUTER_AZUREEG_ENDPOINT); + SetEncryptedProperty(properties, PropertyConstants.EVENTROUTER_AZUREEG_ACCESS_KEY); + if (string.IsNullOrEmpty(providerService.ClassName) || !providerService.ClassName.Contains(className)) + { + providerService.ClassName = PropertyConstants.AZURE_EG_PROVIDER_CLASSNAME; + } + break; + default: + throw new SystemException(string.Format("Provider {0} is not supported.", name)); + } + } + private static void SetEncryptedProperty(GXProperties properties, string prop) + { + string value = properties.Get(prop); + if (string.IsNullOrEmpty(value)) + value = string.Empty; + value = CryptoImpl.Encrypt(value); + properties.Set(prop, value); + } + + } + public static class ExceptionExtensions + { + public static string GetInnermostException(Exception e) + { + Exception ex = e; + if (ex != null) + { + while (ex.InnerException != null) + { + ex = ex.InnerException; + } + + } + return ex.Message; + } + } + static class Providers + { + public const string AzureEventGrid = "AZUREEVENTGRID"; + } +} diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterProviderBase.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterProviderBase.cs new file mode 100644 index 000000000..2ab0a67c8 --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterProviderBase.cs @@ -0,0 +1,226 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using GeneXus.Services; +using GeneXus.Utils; +using GxClasses.Helpers; +using log4net; + +namespace GeneXus.Messaging.Common +{ + public class EventRouterProviderBase + { + internal IEventRouter eventRouter = null; + public static Assembly assembly; + static readonly ILog logger = LogManager.GetLogger(typeof(EventRouterProviderBase)); + private const string MODULE_DLL = @"GeneXusEventMessaging"; + + public EventRouterProviderBase() + { + } + public EventRouterProviderBase(EventRouterProviderBase other) + { + eventRouter = other.eventRouter; + } + void ValidQueue() + { + if (eventRouter == null) + { + GXLogging.Error(logger, "Event Router was not instantiated."); + throw new Exception("Event Router was not instantiated."); + } + } + private static void LoadAssemblyIfRequired() + { + if (assembly == null) + { + assembly = AssemblyLoader.LoadAssembly(new AssemblyName(MODULE_DLL)); + } + } + + public bool SendEvent(GxUserType evt, bool binaryData, out GXBaseCollection errorMessages) + { + bool success = false; + errorMessages = new GXBaseCollection(); + try + { + GXCloudEvent gxCloudEvent = ToGXCloudEvent(evt); + LoadAssemblyIfRequired(); + try + { + ValidQueue(); + if (eventRouter != null) + return(eventRouter.SendEvent(gxCloudEvent, binaryData)); + } + catch (Exception ex) + { + EventRouterErrorMessagesSetup(ex, out errorMessages); + success = false; + GXLogging.Error(logger, ex); + } + } + catch (Exception ex) + { + success = false; + GXLogging.Error(logger,ex); + throw ex; + } + return success; + } + + public bool SendCustomEvents(string evts, bool isBinary, out GXBaseCollection errorMessages) + { + errorMessages = new GXBaseCollection(); + bool success; + try + { + ValidQueue(); + success = eventRouter.SendCustomEvents(evts, isBinary); + } + catch (Exception ex) + { + EventRouterErrorMessagesSetup(ex, out errorMessages); + success = false; + GXLogging.Error(logger, ex); + } + return success; + } + + public bool SendEvents(IList evts, bool binaryData, out GXBaseCollection errorMessages) + { + errorMessages = new GXBaseCollection(); + bool success = false; + LoadAssemblyIfRequired(); + try + { + IList gxCloudEvents = new List(); + foreach (GxUserType e in evts) + { + if (ToGXCloudEvent(e) is GXCloudEvent gxCloudEvent) + gxCloudEvents.Add(gxCloudEvent); + } + try + { + ValidQueue(); + success = eventRouter.SendEvents(gxCloudEvents, binaryData); + } + catch (Exception ex) + { + EventRouterErrorMessagesSetup(ex, out errorMessages); + success = false; + GXLogging.Error(logger, ex); + } + } + catch (Exception ex) + { + GXLogging.Error(logger, ex); + throw ex; + } + return success; + } + + #region Transform operations + protected void EventRouterErrorMessagesSetup(Exception ex, out GXBaseCollection errorMessages) + { + errorMessages = new GXBaseCollection(); + bool foundGeneralException = false; + if (ex != null) + { + SdtMessages_Message msg = new SdtMessages_Message(); + if (eventRouter != null && ex.InnerException != null) + { + do + { + if (eventRouter.GetMessageFromException(ex.InnerException, msg)) + { + msg.gxTpr_Type = 1; + errorMessages.Add(msg); + } + else + { + foundGeneralException = true; + break; + } + ex = ex.InnerException; + } + while (ex.InnerException != null); + if (foundGeneralException) + GXUtil.ErrorToMessages("GXEventRouter", ex, errorMessages); + } + else + { + GXUtil.ErrorToMessages("GXEventRouter", ex, errorMessages); + } + } + } + private GXCloudEvent ToGXCloudEvent(GxUserType evt) + { + if (evt != null) + { + GXCloudEvent gxCloudEvent = new GXCloudEvent(); + gxCloudEvent.type = evt.GetPropertyValue("Type"); + gxCloudEvent.source = evt.GetPropertyValue("Source"); + gxCloudEvent.data = evt.GetPropertyValue("Data"); + gxCloudEvent.datacontenttype = evt.GetPropertyValue("Datacontenttype"); + gxCloudEvent.id = evt.GetPropertyValue("Id"); + gxCloudEvent.subject = evt.GetPropertyValue("Subject"); + gxCloudEvent.dataschema = evt.GetPropertyValue("Dataschema"); + gxCloudEvent.data_base64 = evt.GetPropertyValue("Data_base64"); + gxCloudEvent.time = evt.GetPropertyValue("Time"); + return gxCloudEvent; + } + return null; + } + #endregion + + } + internal class ServiceFactory + { + private static IEventRouter eventRouter; + private static readonly ILog log = LogManager.GetLogger(typeof(Services.ServiceFactory)); + + public static GXServices GetGXServices() + { + return GXServices.Instance; + } + + public static IEventRouter GetEventRouter() + { + if (eventRouter == null) + { + eventRouter = GetRouterImpl(GXServices.EVENTROUTER_SERVICE); + } + return eventRouter; + } + + public static IEventRouter GetRouterImpl(string service) + { + IEventRouter eventRouterImpl = null; + if (GetGXServices() != null) + { + GXService providerService = GetGXServices()?.Get(service); + if (providerService != null) + { + try + { + string typeFullName = providerService.ClassName; + GXLogging.Debug(log, "Loading Event Router settings:", typeFullName); + Type type = AssemblyLoader.GetType(typeFullName); + eventRouterImpl = (IEventRouter)Activator.CreateInstance(type); + } + catch (Exception e) + { + GXLogging.Error(log, "Couldn't connect to the Event Router.", e.Message, e); + throw e; + } + } + } + return eventRouterImpl; + } + } +} + + + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/GXEventRouter.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/GXEventRouter.csproj new file mode 100644 index 000000000..d1e59a220 --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/GXEventRouter.csproj @@ -0,0 +1,17 @@ + + + + net6.0 + GeneXus.Message.EventRouter + Event Bus Messaging Router + TRACE;DEBUG;NETCORE + + + + + + + + + + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/PropertyConstants.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/PropertyConstants.cs new file mode 100644 index 000000000..2aed7d804 --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/PropertyConstants.cs @@ -0,0 +1,17 @@ +namespace GeneXus.Messaging.Common +{ + public static class PropertyConstants + { + //Azure Event Grid + + internal const string AZURE_EG_CLASSNAME = "GeneXus.Messaging.GXAzureEventGrid.AzureEventGrid"; + internal const string AZURE_EG_PROVIDER_CLASSNAME = "GeneXus.Messaging.GXAzureEventGrid.AzureEventGrid, GXAzureEventGrid, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"; + public const string EVENT_ROUTER = "EVENTROUTER"; + public const string URI_ENDPOINT = "ENDPOINT"; + public const string ACCESS_KEY = "ACCESS_KEY"; + public const string AZUREEVENTGRID = "AZUREEVENTGRID"; + public const string EVENTROUTER_AZUREEG_ENDPOINT = "EVENTROUTER_AZUREEVENTGRID_ENDPOINT"; + public const string EVENTROUTER_AZUREEG_ACCESS_KEY = "EVENTROUTER_AZUREEVENTGRID_ACCESS_KEY"; + + } +} diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/GXQueue.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/GXQueue.csproj index b41e066ac..771581f34 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/GXQueue.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/GXQueue.csproj @@ -6,6 +6,10 @@ GeneXus.Message.Queue + + + + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/ServiceSettings.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/ServiceSettings.cs deleted file mode 100644 index 443f5223e..000000000 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/ServiceSettings.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using GeneXus.Encryption; -using GeneXus.Messaging.Common; -using GeneXus.Services; -using log4net; - -namespace GeneXus.Messaging.Queue -{ - public class ServiceSettings - { - static readonly ILog logger = log4net.LogManager.GetLogger(typeof(ServiceSettings)); - - internal GXService service; - public string serviceNameResolver { get; } - public string name { get; } - - public ServiceSettings(string serviceNameResolver, string name, GXService gXService) - { - this.serviceNameResolver = serviceNameResolver; - this.name = name; - this.service = gXService; - } - - public string GetEncryptedPropertyValue(string propertyName, string alternativePropertyName = null) - { - String value = GetEncryptedPropertyValue(propertyName, alternativePropertyName, null); - if (value == null) - { - String errorMessage = String.Format($"Service configuration error - Property name {ResolvePropertyName(propertyName)} must be defined"); - logger.Fatal(errorMessage); - throw new Exception(errorMessage); - } - return value; - } - public string GetEncryptedPropertyValue(string propertyName, string alternativePropertyName, string defaultValue) - { - String value = GetPropertyValue(propertyName, alternativePropertyName, defaultValue); - if (!String.IsNullOrEmpty(value)) - { - try - { - string ret = String.Empty; - if (CryptoImpl.Decrypt(ref ret, value)) - { - value = ret; - } - } - catch (Exception) - { - logger.Warn($"Could not decrypt property name: {ResolvePropertyName(propertyName)}"); - } - } - return value; - } - - internal string GetPropertyValue(string propertyName, string alternativePropertyName = null) - { - String value = GetPropertyValue(propertyName, alternativePropertyName, null); - if (value == null) - { - String errorMessage = String.Format($"Service configuration error - Property name {ResolvePropertyName(propertyName)} must be defined"); - logger.Fatal(errorMessage); - throw new Exception(errorMessage); - } - return value; - } - - internal string GetPropertyValue(string propertyName, string alternativePropertyName, string defaultValue) - { - String value = null; - value = string.IsNullOrEmpty(value) ? GetPropertyValueImpl(ResolvePropertyName(propertyName)) : value; - value = string.IsNullOrEmpty(value) ? GetPropertyValueImpl(propertyName) : value; - value = string.IsNullOrEmpty(value) ? GetPropertyValueImpl(alternativePropertyName) : value; - value = string.IsNullOrEmpty(value) ? defaultValue : value; - return value; - } - - internal string GetPropertyValueImpl(string propertyName) - { - String value = null; - if (!string.IsNullOrEmpty(propertyName)) - { - value = Environment.GetEnvironmentVariable(propertyName); - if (service != null && value == null) - { - value = service.Properties.Get(propertyName); - } - } - return value; - } - - internal string ResolvePropertyName(string propertyName) - { - return $"{serviceNameResolver}_{name}_{propertyName}"; - } - } -} diff --git a/dotnet/src/dotnetframework/GxClasses/Services/Storage/GXServices.cs b/dotnet/src/dotnetframework/GxClasses/Services/Storage/GXServices.cs index 5d0879298..0c652ecf7 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/Storage/GXServices.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/Storage/GXServices.cs @@ -24,6 +24,7 @@ public class GXServices public static string WEBNOTIFICATIONS_SERVICE = "WebNotifications"; public static string QUEUE_SERVICE = "QueueService"; public static string MESSAGEBROKER_SERVICE = "MessageBrokerService"; + public static string EVENTROUTER_SERVICE = "EventRouterService"; private static string[] SERVICES_FILE = new string[] { "CloudServices.dev.config", "CloudServices.config" }; [System.Diagnostics.CodeAnalysis.SuppressMessage("GxFxCopRules", "CR1000:EnforceThreadSafeType")] private Dictionary services = new Dictionary(); From 1638203957392f24aa62432cb135339bebc3bd97 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Thu, 27 Jul 2023 15:50:39 -0300 Subject: [PATCH 012/164] Initial support for Pdf reports in PDF/A 1A and 1B (#762) * Initial support for PDF/A 1a and 1b for .NET and .NET Framework reports. * Initialize default complianceLevel with None (default used until now). * Do not check report name in test until while #761 is open. * Set sRGB Color Space Profile for PDFA_1B. * Turn off test of PDFA. It seems to cause a timeout when running on github actions. --- .../GxPdfReportsCS/GxPdfReportsCS.csproj | 4 + .../GxPdfReportsCS/Properties/AssemblyInfo.cs | 3 + .../GxPdfReportsCS/GxPdfReportsCS.csproj | 6 + .../GxPdfReportsCS/PDFReportItext.cs | 101 ++++++++- .../sRGB Color Space Profile.icm | Bin 0 -> 3144 bytes .../DotNetCoreWebUnitTest.csproj | 9 + .../Middleware/WebReportTest.cs | 61 ++++++ .../test/DotNetCoreWebUnitTest/PDFReport.ini | 27 +++ .../apps/apdfwebbasictest.cs | 196 ++++++++++++++++++ dotnet/test/DotNetCoreWebUnitTest/lamp.png | Bin 0 -> 3232 bytes 10 files changed, 398 insertions(+), 9 deletions(-) create mode 100644 dotnet/src/dotnetcore/GxPdfReportsCS/Properties/AssemblyInfo.cs create mode 100644 dotnet/src/dotnetframework/GxPdfReportsCS/sRGB Color Space Profile.icm create mode 100644 dotnet/test/DotNetCoreWebUnitTest/Middleware/WebReportTest.cs create mode 100644 dotnet/test/DotNetCoreWebUnitTest/PDFReport.ini create mode 100644 dotnet/test/DotNetCoreWebUnitTest/apps/apdfwebbasictest.cs create mode 100644 dotnet/test/DotNetCoreWebUnitTest/lamp.png diff --git a/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj b/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj index 6f996b82c..3818d8a4f 100644 --- a/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj +++ b/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj @@ -12,6 +12,10 @@ + + + + diff --git a/dotnet/src/dotnetcore/GxPdfReportsCS/Properties/AssemblyInfo.cs b/dotnet/src/dotnetcore/GxPdfReportsCS/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..d916f63fa --- /dev/null +++ b/dotnet/src/dotnetcore/GxPdfReportsCS/Properties/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("DotNetCoreWebUnitTest")] diff --git a/dotnet/src/dotnetframework/GxPdfReportsCS/GxPdfReportsCS.csproj b/dotnet/src/dotnetframework/GxPdfReportsCS/GxPdfReportsCS.csproj index 491c8720e..1c2d10b46 100644 --- a/dotnet/src/dotnetframework/GxPdfReportsCS/GxPdfReportsCS.csproj +++ b/dotnet/src/dotnetframework/GxPdfReportsCS/GxPdfReportsCS.csproj @@ -6,6 +6,12 @@ Itext PDF Report GeneXus.PdfReportsCS + + + + + + diff --git a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext.cs b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext.cs index 2faa34b7a..61b8d0b30 100644 --- a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext.cs +++ b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext.cs @@ -22,6 +22,7 @@ using GeneXus.Utils; using System.Reflection; using GeneXus.Metadata; +using GeneXus.Configuration; namespace com.genexus.reports { @@ -45,6 +46,7 @@ public class PDFReportItextSharp : IReportHandler private bool fontUnderline; private bool fontStrikethru; private int fontSize; + private string language; //Color for, BaseColor for => Itext5 private object backColor, foreColor, templateColorFill; @@ -89,6 +91,7 @@ public class PDFReportItextSharp : IReportHandler public static float DOTS_UNITS_ON = 1; public bool lineCapProjectingSquare = true; public bool barcode128AsImage = true; + private PdfConformanceLevel complianceLevel = PdfConformanceLevel.None; internal Dictionary documentImages; float[] STYLE_SOLID = new float[] { 1, 0 };//0 float[] STYLE_NONE = null;//1 @@ -312,7 +315,11 @@ private void loadPrinterSettingsProps(String iniFile, String form, String printe printerSettings.setupProperty(form, Const.COLOR, color + ""); printerSettings.setupProperty(form, Const.DUPLEX, duplex + ""); } - + internal static void SetDefaultComplianceLevel(PdfConformanceLevel level) + { + if (props!=null) + props.setGeneralProperty(Const.COMPLIANCE_LEVEL, level.ToString()); + } private void loadProps() { if (props == null) @@ -350,6 +357,7 @@ private void loadProps() props.setupGeneralProperty(Const.MARGINS_INSIDE_BORDER, Const.DEFAULT_MARGINS_INSIDE_BORDER.ToString().ToLower()); props.setupGeneralProperty(Const.OUTPUT_FILE_DIRECTORY, "."); props.setupGeneralProperty(Const.LEADING, "2"); + props.setupGeneralProperty(Const.COMPLIANCE_LEVEL, PdfConformanceLevel.None.ToString()); props.setupGeneralProperty(Const.RUN_DIRECTION, Const.RUN_DIRECTION_LTR); props.setupGeneralProperty(Const.JUSTIFIED_TYPE_ALL, "false"); @@ -415,16 +423,24 @@ private void init() try { writer = PdfWriter.GetInstance(document, outputStream); + string level = props.getGeneralProperty(Const.COMPLIANCE_LEVEL); + if (Enum.TryParse(level, true, out complianceLevel)) + { + if (SetComplainceLevel(complianceLevel)) + writer.SetTagged(); + } + document.Open(); + } catch (DocumentException de) { - GXLogging.Debug(log,"GxDrawRect error", de); + GXLogging.Debug(log, "init error", de); } - document.Open(); } public void GxRVSetLanguage(String lang) { + language = lang; } public void GxSetTextMode(int nHandle, int nGridX, int nGridY, int nPageLength) @@ -795,6 +811,7 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom { iTextSharp.text.Image image; iTextSharp.text.Image imageRef; + if (documentImages != null && documentImages.TryGetValue(bitmap, out imageRef)) { image = imageRef; @@ -848,7 +865,9 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom image.ScaleToFit(rightAux - leftAux, bottomAux - topAux); PdfContentByte cb = writer.DirectContent; + image.Alt = Path.GetFileName(bitmap); cb.AddImage(image); + } } catch (DocumentException de) @@ -1046,8 +1065,16 @@ public void GxAttris(String fontName, int fontSize, bool fontBold, bool fontItal baseFont = CreateDefaultFont(); } } + BaseFont defaultFont; private BaseFont CreateDefaultFont() { - return BaseFont.CreateFont("Helvetica", BaseFont.WINANSI, BaseFont.NOT_EMBEDDED); + if (defaultFont == null) + { + if (IsPdfA()) + defaultFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.EMBEDDED); + else + defaultFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED); + } + return defaultFont; } private string GetFontLocation(string fontName) { @@ -1082,9 +1109,14 @@ private Hashtable GetFontLocations() private bool IsEmbeddedFont(string fontName) { - bool generalEmbeedFont = props.getBooleanGeneralProperty(Const.EMBEED_SECTION, false); - bool generalEmbeedNotSpecified = props.getBooleanGeneralProperty(Const.EMBEED_NOT_SPECIFIED_SECTION, false); - return generalEmbeedFont && props.getBooleanProperty(Const.EMBEED_SECTION, fontName, generalEmbeedNotSpecified); + if (IsPdfA()) + return true; + else + { + bool generalEmbeedFont = props.getBooleanGeneralProperty(Const.EMBEED_SECTION, false); + bool generalEmbeedNotSpecified = props.getBooleanGeneralProperty(Const.EMBEED_NOT_SPECIFIED_SECTION, false); + return generalEmbeedFont && props.getBooleanProperty(Const.EMBEED_SECTION, fontName, generalEmbeedNotSpecified); + } } private void LoadAsianFontsDll() { @@ -1970,7 +2002,22 @@ public void GxEndDocument() } } + if (IsPdfA()) + { + using (Stream iccProfile = ReadResource("sRGB Color Space Profile.icm")) + { + ICC_Profile icc = ICC_Profile.GetInstance(iccProfile); + writer.SetOutputIntents("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1", icc); + } + writer.ExtraCatalog.Put(PdfName.LANG, new PdfString(Config.GetCultureForLang(language).Name)); + PdfDictionary markInfo = new PdfDictionary(PdfName.MARKINFO); + markInfo.Put(PdfName.MARKED, new PdfBoolean(PdfBoolean.TRUE)); + writer.ExtraCatalog.Put(PdfName.MARKINFO, markInfo); + + writer.CreateXmpMetadata(); + + } document.Close(); @@ -2047,6 +2094,17 @@ public void GxEndDocument() GXLogging.Debug(log,"GxEndDocument End"); } + Stream ReadResource(string fileName) + { + Assembly assembly = GetType().Assembly; + string resourcePath = $"{assembly.GetName().Name}.{fileName}"; + return assembly.GetManifestResourceStream(resourcePath); + } + + private bool IsPdfA() + { + return complianceLevel != 0; + } public void GxEndPrinter() { @@ -2286,6 +2344,20 @@ private void SetSimpleColumn(ColumnText col, Rectangle rect) { col.SetSimpleColumn(rect.Left, rect.Bottom, rect.Right, rect.Top); } + internal bool SetComplainceLevel(PdfConformanceLevel level) + { + switch (level) + { + case PdfConformanceLevel.Pdf_A1A: + writer.PDFXConformance = PdfWriter.PDFA1A; + return true; + case PdfConformanceLevel.Pdf_A1B: + writer.PDFXConformance = PdfWriter.PDFA1B; + return true; + default: + return false; + } + } } public class ParseINI @@ -2737,7 +2809,8 @@ public class Const public static String ADJUST_TO_PAPER = "AdjustToPaper"; //fit to page public static String LINE_CAP_PROJECTING_SQUARE = "LineCapProjectingSquare"; public static String BARCODE128_AS_IMAGE = "Barcode128AsImage"; - public static String LEADING = "Leading"; + public static String LEADING = "Leading"; + internal static String COMPLIANCE_LEVEL = "ComplianceLevel"; //Printer settings public static String PRINTER = "Printer"; @@ -3227,6 +3300,16 @@ public static ArrayList parseLine(String line, String separator) } } - + internal enum PdfConformanceLevel + { + None, + Pdf_A1B, + Pdf_X1A2001, + Pdf_A1A, + Pdf_A2A, + Pdf_A2B, + Pdf_A3A, + Pdf_A3B + } } diff --git a/dotnet/src/dotnetframework/GxPdfReportsCS/sRGB Color Space Profile.icm b/dotnet/src/dotnetframework/GxPdfReportsCS/sRGB Color Space Profile.icm new file mode 100644 index 0000000000000000000000000000000000000000..7f9d18d097d1bcccb32e6d5743ac4af593170b6f GIT binary patch literal 3144 zcmbW3cT`i^7KhKhH@(mjA|NI78hQyJ(mO~M1W}1efKUR4geG=G1x6GRDOO}uzyU{x zB4b4q3xk4U*9r0vP{zSgL`CJ@jB5$+tu^!Bn*GOF-`VH4*V$+9eb>4GQ2c@f!gN>x zfHa|46z=Q6ToMz@#P0Oj{6)6@8zOaL$xnP1H3 zCZTMJGDQ>_?uqgO00@-CIlOWXi}^Wdo&b2JXXJ_miAiFn5!aY$<><&}`th?<`C>6E zl*3KohJ5ztS`M50QMwWn;o;hl~n+=Z3aN);jB;ZAOP|O0JPqm^B#t5UXsM(3?~bV z?CflF0iSCwE9f`-pMr17zlJ&Ynal3`Ry(E_KY=4j6*FZ;<)){mOGM1f3=WsiWc~LL z|Kq?pY0b&QES#Uf7x9JYRZ-}a351DgyM;V~SdcDc3WR^v;eQx5CkGjRoof_mbzcB| zg*i~TNe9SpJpe-^10-%gdIEjxTM#h{$iBR2t&y*Dk1~4x=lUNDT#9btOhF=3=JpJa zWO5~-11?AcX+Q+BK|a_3 z3PCa00d|9GZ~)YSde8(;f;MmlTm)CZ4R8w#fJZ5%ns2D1Ps-Z(rJ@g}V8oCHwgZiKc&>%Dh{Q-T1 z5tstgVGY;-wt(5NI~)i{!pq=9com!n7r@)$O1Kt24!6P=;T!M(EQMdflL$b_2m{eZ zSO^>OL_&~QBmog2Ymp+P0;xrskPf69xs6DXapVIAhoNDZ7#7AEHf9hrf%$@^V%4#xSSPGMb_q5Sn~g2RR$z}{Td>%$GT@D&7?Df)BxS@M3%+z6yUFe;(hDAI85YkO^7@ zYl06UmLMc-BvcR@2gb~6tQGuvWbRvcjdBj{|DY1^&LA*&ECQg$SNrogBQY0yv zw1HGfY9d`GJtn;&lgT<{M{*chKweL-B%dH(B@dE6P?RVp6i-SVMMBw5IZC-ec|dtX zrBV&3Zq!(+n7W->PrXEaN_{U!lQWm|m*dH;ldF+ymFt&#B~O&smv@(6E}th~A%9B# zru?`9QNcjLQ-PzfR-s1Ww8A}wNky8Xm12lunqrA!gW@&CQ6;>Rfs(fpPpLrZu+k-^ zAsRx{rFqi0v`w@++GW}>9Y;5$`_q%@#q=NOz4QrXC1qRXDCHdG8s)RfQU<~>VE8jq z8KsPqjJu4F^EBqU&*RVAHm_-3|GX)c`6_NIe3c@VW|aYzkE%>nZ`BmlovLlBPt-7K zCTd}7*=qaME~|~tr_Xnu&z)a1|K$9K>aeXRCp8onAC8dVyXG{!X< znr@oOn&q13G{>}PS_`!VTIE{jwO%llneNO~W+k(WIiant?WZl#KBV2NJ*{J?vsh=N zPP5JvU6L+aH$k^tw^MgQPfIUYFJG@w@1Z_XpRJ#yzem4Yf6BnnAlhJyL7Ty-p^Blu zVV+^5;bSAJk*m=vqgtao#yDfPafahC5 z+Qgb`U1NR6hHB$uv(Bd7=C!S z*mQO%yM%q!5$ovTxX$s6;|C{uC$ZB>r{A4f&MD3f&Z7$q7w{L-x-1*Nx|P#BIdg*ge_(xce&)OAnDpi^r6wljj=G3totquUC;* zueXx-V()72r#?D9i9U@!6TWu7t9>u{Vf_OAcKY4(*YM~1*ZWTdI0UQ-=nA9+Mg&#| zJ_|Al5(RYx!@&W;yMiAt(qAN8)D{9l{6ltyJP9=nT^0Is7%nU{tS0PvxK((5cy|OX zVnswl#Jfn3$kND1i;Wgb7I#L;N5w_eM@>b0MVCcOmsl)Wv*bpMT8tp3Jr*Au6?-Ih za;f*y-Ajk#?BWXJ?k+Q2mb2{Ia<%2D%g?TmU%^>%Djpjj9p4cDi4(%93l#rC8 zDKn|jsm*DGwD`2sLM35}uq$0NJtw^{!!)BXL%Pao)$UajqCnA+Oek|%X1kb<{!H~q zj3k>SgINo+YO>yEM`fSNQOptM^yHf4Zp$6X^U3>uHD)z;b!WbI{)YU)HSTK;t%cUE zT-&)$cU{4{;q|`jk8L1rNZIhqM$3(58{ck<-qcZ`QLw&XXtVF;#zMJ5QQ^HU&RY&_ z#cUO9?cHXxt!mqsB3{w;V$0%+;!h>qlI!1DeOLM2%=U!sy`}c0`*+}W2zT7w>ALe+ znPOR9+0d@wU9IKJ@}ly$yI1VKR$*IlU=L}JWRJ8msIt9EuWCotr|P8Yff|pR=Dq5B zx9y$U$J^Jx-)(=>0gVI22Rfw1Ho}dP#Y+O@16`i z*?Ee6s_7^FpZ2!UT8dhs*4);Kwxl*`drW)Z>44Ln9nKvsKb!x2^o;hInzPDhOV5$c z6`Y$npLc%pLdJ#hi-{M9I#+Z)y0qldovyI1-phfPuU_%Fa;e+B`}|dxt7on`T|0f9 zeZB35{f*WhyPlR`?0#wKweM}c>2S0CmgB9Cz6E{f`d#}k-uAkE<&OWI8v~05`tB~i zd;ebCJ?VYk{m}=h4_-gadN}=P{bTIoq9+PZDxRu8t^L*b*Ji1`^z5M5V9&FNXOD)s zLoff8`L9pI1<$F^D@L?N>PM|d&y4wu-FmU~#qi6Fm($~gzbXE<_m$DBpMH1yy=P*{ z#PDm;>zO}F-l)Dg`quVs=Va*Q(|2j_rl*SDtG++>f&HQTWAw+7>FiJVPnDmIKX-fy L{PK7vZD!`*_k{EN literal 0 HcmV?d00001 diff --git a/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj b/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj index 75b8a1aaa..bac7e207c 100644 --- a/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj +++ b/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj @@ -14,6 +14,8 @@ + + @@ -34,6 +36,7 @@ + @@ -67,6 +70,12 @@ PreserveNewest + + PreserveNewest + + + Always + PreserveNewest diff --git a/dotnet/test/DotNetCoreWebUnitTest/Middleware/WebReportTest.cs b/dotnet/test/DotNetCoreWebUnitTest/Middleware/WebReportTest.cs new file mode 100644 index 000000000..c03d7d4ae --- /dev/null +++ b/dotnet/test/DotNetCoreWebUnitTest/Middleware/WebReportTest.cs @@ -0,0 +1,61 @@ +using System; +using System.IO; +using System.Net.Http; +using System.Reflection; +using System.Threading.Tasks; +using Codeuctivity; +using com.genexus.reports; +using GeneXus.Metadata; +using GeneXus.Programs; +using Spire.Pdf; +using Xunit; +namespace xUnitTesting +{ + public class WebReportTest : MiddlewareTest + { + public WebReportTest() : base() + { + ClassLoader.FindType("apdfwebbasictest", "GeneXus.Programs", "apdfwebbasictest", Assembly.GetExecutingAssembly(), true);//Force loading assembly for webhook procedure + ClassLoader.FindType("apdfwebwoutimage", "GeneXus.Programs", "apdfwebwoutimage", Assembly.GetExecutingAssembly(), true); + server.AllowSynchronousIO = true; + } + [Fact(Skip = "temporary turned off due to timeout error")] + public void TestPDFA() + { + HttpClient client = server.CreateClient(); + TestPDFA_1AB(client, "apdfwebbasictest.aspx", Spire.Pdf.PdfConformanceLevel.Pdf_A1A).GetAwaiter().GetResult(); + TestPDFA_1AB(client, "apdfwebwoutimage.aspx", Spire.Pdf.PdfConformanceLevel.Pdf_A1A).GetAwaiter().GetResult(); + PDFReportItextSharp.SetDefaultComplianceLevel(com.genexus.reports.PdfConformanceLevel.Pdf_A1B); + TestPDFA_1AB(client, "apdfwebbasictest.aspx", Spire.Pdf.PdfConformanceLevel.Pdf_A1B).GetAwaiter().GetResult(); + TestPDFA_1AB(client, "apdfwebwoutimage.aspx", Spire.Pdf.PdfConformanceLevel.Pdf_A1B).GetAwaiter().GetResult(); + + } + async Task TestPDFA_1AB(HttpClient client, string serviceName, Spire.Pdf.PdfConformanceLevel expectedLevel) + { + HttpResponseMessage response = await client.GetAsync(serviceName); + response.EnsureSuccessStatusCode(); + Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); + String fileName = response.Content.Headers.ContentDisposition.FileName; + //Assert.Equal("Report.pdf", fileName); + using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) + { + await response.Content.CopyToAsync(fs); + } + PdfDocument pdf = new PdfDocument(); + pdf.LoadFromFile(fileName); + Spire.Pdf.PdfConformanceLevel conformance = pdf.Conformance; + + Assert.True(expectedLevel == conformance, $"Conformance level is {conformance} but {expectedLevel} was expected"); + + PdfAValidator pdfAValidator = new PdfAValidator(); + Report result = await pdfAValidator.ValidateWithDetailedReportAsync(fileName); + bool isValid = await pdfAValidator.ValidateAsync(fileName); + Assert.True(isValid, result.RawOutput); + + + + } + + } + +} diff --git a/dotnet/test/DotNetCoreWebUnitTest/PDFReport.ini b/dotnet/test/DotNetCoreWebUnitTest/PDFReport.ini new file mode 100644 index 000000000..10e61db72 --- /dev/null +++ b/dotnet/test/DotNetCoreWebUnitTest/PDFReport.ini @@ -0,0 +1,27 @@ +ComplianceLevel= pdf_a1a +JustifiedTypeAll= false +OutputFileDirectory= . +ServerPrinting= false +EmbeedNotSpecifiedFonts= false +Leading= 2 +Embeed Fonts= false +DottedStyle= 1;2 +LeftMargin= 0.75 +Barcode128AsImage= true +LongDotDashedStyle= 6;2;1;2 +DEBUG= false +SearchNewFontsOnce= true +TopMargin= 0.75 +LongDashedStyle= 6;2 +DashedStyle= 4;2 +SearchNewFonts= false +BottomMargin= 6 +AdjustToPaper= true +MarginsInsideBorder= false +LineCapProjectingSquare= true +RunDirection= 2 +Version= 1.0.0.0 + +[Fonts Location (MS)] +Microsoft Sans Serif= C:\Windows\fonts\micross.ttf +Microsoft Sans Serif,Bold= C:\Windows\fonts\micross.ttf diff --git a/dotnet/test/DotNetCoreWebUnitTest/apps/apdfwebbasictest.cs b/dotnet/test/DotNetCoreWebUnitTest/apps/apdfwebbasictest.cs new file mode 100644 index 000000000..6924bf049 --- /dev/null +++ b/dotnet/test/DotNetCoreWebUnitTest/apps/apdfwebbasictest.cs @@ -0,0 +1,196 @@ +/* + File: PDFBasicTest + Description: PDFBasic Test + Author: GeneXus .NET Framework Generator version 17_0_8-156507 + Generated on: 12/21/2021 16:34:13.62 + Program type: Main program + Main DBMS: SQL Server +*/ +using GeneXus.Application; +using GeneXus.Data.NTier; +using GeneXus.Http.Server; +using GeneXus.Procedure; +using GeneXus.Utils; + +namespace GeneXus.Programs +{ + public class apdfwebbasictest : GXWebProcedure + { + + public apdfwebbasictest( ) + { + context = new GxContext( ); + DataStoreUtil.LoadDataStores( context); + IsMain = true; + context.SetDefaultTheme("Carmine"); + } + + public apdfwebbasictest( IGxContext context ) + { + this.context = context; + IsMain = false; + } + public override void webExecute() + { + context.SetDefaultTheme("PDFReportTest", true); + GxContext gxcontext = context as GxContext; + gxcontext.SetPhysicalPath(System.IO.Directory.GetCurrentDirectory()); + initialize(); + executePrivate(); + cleanup(); + } + + public void execute() + { + initialize(); + executePrivate(); + } + void executePrivate() + { + /* GeneXus formulas */ + /* Output device settings */ + M_top = 0; + M_bot = 6; + P_lines = (int)(66-M_bot); + getPrinter().GxClearAttris() ; + AddMetrics( ) ; + lineHeight = 15; + gxXPage = 100; + gxYPage = 100; + GxHttpResponse httpResponse = new GxHttpResponse(context); + httpResponse.AppendHeader("Content-Disposition", "inline; filename=Report.pdf"); + getPrinter().GxSetDocFormat("PDF") ; + try + { + Gx_out = "FIL" ; + if (!initPrinter (Gx_out, gxXPage, gxYPage, "GXPRN.INI", "", "", 2, 1, 256, 16834, 9504, 0, 1, 1, 0, 1, 1) ) + { + cleanup(); + return; + } + getPrinter().setModal(false) ; + P_lines = (int)(gxYPage-(lineHeight*6)); + Gx_line = (int)(P_lines+1); + getPrinter().setPageLines(P_lines); + getPrinter().setLineHeight(lineHeight); + getPrinter().setM_top(M_top); + getPrinter().setM_bot(M_bot); + AV8htmlvar = "

This is an example of a simple HTML page with one paragraph.

"; + H1N0( false, 193) ; + getPrinter().GxAttris("Microsoft Sans Serif", 14, false, false, false, false, 0, 0, 0, 0, 0, 255, 255, 255) ; + getPrinter().GxDrawText("Item List", 17, Gx_line+33, 400, Gx_line+66, 0, 0, 0, 0) ; + getPrinter().GxDrawRect(33, Gx_line+33, 133, Gx_line+63, 1, 0, 0, 0, 0, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0) ; + getPrinter().GxAttris("Microsoft Sans Serif", 10, true, false, false, false, 0, 0, 0, 0, 0, 255, 255, 255) ; + getPrinter().GxDrawText("Code", 100, Gx_line+83, 140, Gx_line+101, 0+256, 0, 0, 0) ; + getPrinter().GxDrawText("Name", 183, Gx_line+83, 283, Gx_line+101, 0, 0, 0, 0) ; + getPrinter().GxDrawBitMap("lamp.png", 411, Gx_line+33, 619, Gx_line+241) ; + getPrinter().GxAttris("Microsoft Sans Serif", 8, false, false, false, false, 0, 0, 0, 0, 0, 255, 255, 255) ; + getPrinter().GxDrawText(StringUtil.RTrim( AV8htmlvar), 22, Gx_line+122, 400, Gx_line+178, 0, 1, 0, 0) ; + Gx_OldLine = Gx_line; + Gx_line = (int)(Gx_line+193); + /* Print footer for last page */ + ToSkip = (int)(P_lines+1); + H1N0( true, 0) ; + } + catch ( GeneXus.Printer.ProcessInterruptedException ) + { + } + finally + { + /* Close printer file */ + try + { + getPrinter().GxEndPage() ; + getPrinter().GxEndDocument() ; + } + catch ( GeneXus.Printer.ProcessInterruptedException ) + { + } + endPrinter(); + } + this.cleanup(); + } + + protected void H1N0( bool bFoot , + int Inc ) + { + /* Skip the required number of lines */ + while ( ( ToSkip > 0 ) || ( Gx_line + Inc > P_lines ) ) + { + if ( Gx_line + Inc >= P_lines ) + { + if ( Gx_page > 0 ) + { + /* Print footers */ + Gx_line = P_lines; + getPrinter().GxEndPage() ; + if ( bFoot ) + { + return ; + } + } + ToSkip = 0; + Gx_line = 0; + Gx_page = (int)(Gx_page+1); + /* Skip Margin Top Lines */ + Gx_line = (int)(Gx_line+(M_top*lineHeight)); + /* Print headers */ + getPrinter().GxStartPage() ; + if (true) break; + } + else + { + Gx_line = (int)(Gx_line+1); + } + ToSkip = (int)(ToSkip-1); + } + getPrinter().setPage(Gx_page); + } + + protected void AddMetrics( ) + { + AddMetrics0( ) ; + AddMetrics1( ) ; + } + + protected void AddMetrics0( ) + { + getPrinter().setMetrics("Microsoft Sans Serif", false, false, 58, 14, 72, 171, new int[] {48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 18, 20, 23, 36, 36, 57, 43, 12, 21, 21, 25, 37, 18, 21, 18, 18, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 18, 18, 37, 37, 37, 36, 65, 43, 43, 46, 46, 43, 39, 50, 46, 18, 32, 43, 36, 53, 46, 50, 43, 50, 46, 43, 40, 46, 43, 64, 41, 42, 39, 18, 18, 18, 27, 36, 21, 36, 36, 32, 36, 36, 18, 36, 36, 14, 15, 33, 14, 55, 36, 36, 36, 36, 21, 32, 18, 36, 33, 47, 31, 31, 31, 21, 17, 21, 37, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 18, 20, 36, 36, 36, 36, 17, 36, 21, 47, 24, 36, 37, 21, 47, 35, 26, 35, 21, 21, 21, 37, 34, 21, 21, 21, 23, 36, 53, 53, 53, 39, 43, 43, 43, 43, 43, 43, 64, 46, 43, 43, 43, 43, 18, 18, 18, 18, 46, 46, 50, 50, 50, 50, 50, 37, 50, 46, 46, 46, 46, 43, 43, 39, 36, 36, 36, 36, 36, 36, 57, 32, 36, 36, 36, 36, 18, 18, 18, 18, 36, 36, 36, 36, 36, 36, 36, 35, 39, 36, 36, 36, 36, 32, 36, 32}) ; + } + + protected void AddMetrics1( ) + { + getPrinter().setMetrics("Microsoft Sans Serif", true, false, 57, 15, 72, 163, new int[] {47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 17, 19, 29, 34, 34, 55, 45, 15, 21, 21, 24, 36, 17, 21, 17, 17, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, 21, 36, 36, 36, 38, 60, 43, 45, 45, 45, 41, 38, 48, 45, 17, 34, 45, 38, 53, 45, 48, 41, 48, 45, 41, 38, 45, 41, 57, 41, 41, 38, 21, 17, 21, 36, 34, 21, 34, 38, 34, 38, 34, 21, 38, 38, 17, 17, 34, 17, 55, 38, 38, 38, 38, 24, 34, 21, 38, 33, 49, 34, 34, 31, 24, 17, 24, 36, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 17, 21, 34, 34, 34, 34, 17, 34, 21, 46, 23, 34, 36, 21, 46, 34, 25, 34, 21, 21, 21, 36, 34, 21, 20, 21, 23, 34, 52, 52, 52, 38, 45, 45, 45, 45, 45, 45, 62, 45, 41, 41, 41, 41, 17, 17, 17, 17, 45, 45, 48, 48, 48, 48, 48, 36, 48, 45, 45, 45, 45, 41, 41, 38, 34, 34, 34, 34, 34, 34, 55, 34, 34, 34, 34, 34, 17, 17, 17, 17, 38, 38, 38, 38, 38, 38, 38, 34, 38, 38, 38, 38, 38, 34, 38, 34}) ; + } + + public override int getOutputType( ) + { + return GxReportUtils.OUTPUT_PDF ; + } + + public override void cleanup( ) + { + if (IsMain) waitPrinterEnd(); + if ( IsMain ) + { + context.CloseConnections(); + } + ExitApp(); + } + + public override void initialize( ) + { + AV8htmlvar = ""; + /* GeneXus formulas. */ + Gx_line = 0; + context.Gx_err = 0; + } + + private int M_top ; + private int M_bot ; + private int ToSkip ; + private int Gx_OldLine ; + private string AV8htmlvar ; + } + +} diff --git a/dotnet/test/DotNetCoreWebUnitTest/lamp.png b/dotnet/test/DotNetCoreWebUnitTest/lamp.png new file mode 100644 index 0000000000000000000000000000000000000000..840d5d5148aeffe5f60d12eb72b2af91f08b6b6e GIT binary patch literal 3232 zcmV;R3}5q!P)HqoS|LKhX-cxymeT$E9|KxDnzBTR1C;#`< z|L&>(;bQ;WMgQ41ota~%pIqd_F0Z6k|LmIo@wdseLejZAz^+LD=6}u3rGkog-q3gM z(MaOZYuV3&#Lc|G%*VIK&g#)r-P*9`&|lThj_&HoKLOgM000Y{Nkl;DCCB(eIq#)a6+Vw_DYquX0dY5~`|52S6pqF-l+&h+ z>Mz9PMmLbRG8sp^Zj6}+!QB`ZKLC%ycl}Lxj1W)Ghv8w}Obq)g3YL|tQ_8M}W1BoK zhT~yXB*(p1d$QkbHgDI$_v~58Y2QG2^5`I3z6##Gutub>Vm<8~f`^mZ+xND3ocH8$ zuyrV0)|uGSE!6_#`u*Y3*=--+_}3AE&D-1N0m!8G!CN~#6fON}D|_fC;H4-0b3vtM z@>h0bV`LgVDpVW7mlf)yf4HQ@tX{%-sH3>9pvNyLV= zpQT=BPDI&~t>vM&)y#eT9Yh=BhI7a*JM=6%0s7rNhX9;wEipoLwt5SRS9mt^IS zZeJp@r16P7*^}4D?+%OI7J+;9S=64Wr&)wZ8dqA@TOw-p$o1F@O( zY)x&R3(W%mzwH}cnsC>xj2@1chxyWv0|PV$E)kD}a}SjN1=7ee6Fg=!)8i*JB-69; zA)}hTJr=@%rIj$rf(WBZDqdoSh*A@~6PgEV79|e@`3b^MB551eGRZ`;Bd#EG!VSnl)40 zf73u~YY_{?tY(>KBFK4JV1byZaR+76dax%mnw+pWHfQmzgAOr{>iw$_5zdWGHMY*s zxIY4N?d zsyZB&hXE=r6O0kAaECJxipp)D`nPe+*FQ8~hBV{2!=Bvz&!7ML@#Dw8&j7>^eBoK< zF#}>zoie}w`Rm8GZ*vxcD<*l_2udyT062eX<8t?(Kfe8QE&_k8IH+1Dt_}O(aC$4P zx_&^g%cv+#DU;{a29%CgQq5 z9vbS08pNM1=FMU~OwH6E$y$fTe110CLi42yundAlSc|*9CXLaEgiFrJcm<<_hG7t794U`xvMy9kC=A5WGLLeDRbC+YVV;rP^{}Gh%Utrhuo;^a zAj*Pm*_J~1VRTsh?UH)lBAp@}e7juA{YaILUp$}x{#{8U7HCsR;tWt6bm1II9%_Sl zj8fG_fnc_-Ka@lLu0!bv<2KLl%`NY!eAJc|hGtYS{|% zc03DXg;EPNr@3K1S9JZ9@ zfqgz7-fiVfv83}!pjBMlfOank>^4F>(=kc)KFiaP*SZ4}Sw(5W^vJc&(r{W;OIhYH z7M>-^(9(#3-<>f6@pV+$=V-7Q%UNtQQS=rJ5jW5}gF2$3fR<}FQa;-Fz-^%xoD$6DM?ara9DVQ49noVfTnbiEd%_h{K$2)l?$Dg zqcIjjnhr30B#S6@1n`!DdDRNId$^T^3YAFE%#r%6XT>7S_^nQkOm5VNg^~_+MF_Yu zbsw`v8ObUVUv?Qp6umSvw`~ z)Fsr8d?_H3X3UBy#q%-)I#zhxAa33Mpx5In9h*&7K|~yG>ShbUT9ce`aeJ#63=*Ma z(Gn^;7jMa(6QYDY$7o>X;Z_x)0zBotecw?SK=v2dLH8TbLJWeLx^_iL>kdPSl?su9 z3idX=W`c0#v6v;2?KBQVgaZ9aLR z9Z}gvk&XI6BNZ@41g_){;YXLA3^@1NC zsOrds5rGF2#*mu^E8^e^#sG4{Q8f|+>1oU$BO}#pq+!Gk2a+x%Aw+rAB8#m!t3EW~ zRyFECoM3c1pCHPzxOwy>TrhK!>e`a%s38Cj0dj-)r4dY&WRYiB6ePkVOf|5>=9pII zfn1NY8Vx;JMdpjvSvuE5^d|iWZE!WDhp}wBLE=fDqA)Qj%~P7(D{6~RUrZ5xlX4-q z*6I=Utn=wqoRiT+Le@repgdgL0wl`n}SKcY{(A< zAcg)QU&c^^i%p6HG0aGK3taNJ20d%eD1EBuHt4-$IdW1u4!TcHnY$>pR=NaqJ2D<1 zv Date: Thu, 27 Jul 2023 15:59:41 -0300 Subject: [PATCH 013/164] - GAM Security can be now defined on a method by method basis. (#825) * - GAM Security can be now defined on a method by method basis. * - Add security by method in NET Core 103173 * - Auxiliar security methods set as internal as suggested. * - More security methods set as internal as suggested * - Remove ApiIntegratedSecurityEnabled() Method - added permissionMethod variable in RestService Class * revert visibility changes in GXBaseObject.cs * add protected status to IsAuthenticatedMethod --- .../GxClasses/Helpers/GXRestAPIClient.cs | 1 + .../GxClasses/Model/GXBaseObject.cs | 9 +++++++-- .../GxClasses/Services/GXRestServices.cs | 1 + .../GxClasses/Services/GxRestWrapper.cs | 18 ++++++++++++++---- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestAPIClient.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestAPIClient.cs index 170a3c5bf..6cc2ff359 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestAPIClient.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestAPIClient.cs @@ -280,6 +280,7 @@ public string GetJsonStr(string varName) } else if (_responseData.Count >= 1) // can contain the same key (recursive unwrapped) { + #if NETCORE string rData = JsonSerializer.Serialize(_responseData); if (sdt.FromJSonString(rData, null)) diff --git a/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs b/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs index df67abdf5..2f8ef622c 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs @@ -132,9 +132,11 @@ public virtual void cleanup() { } virtual public bool UploadEnabled() { return false; } public bool IntegratedSecurityEnabled2 { get { return IntegratedSecurityEnabled; } } public GAMSecurityLevel IntegratedSecurityLevel2 { get { return IntegratedSecurityLevel; } } + public bool IsSynchronizer2 { get { return IsSynchronizer; } } public string ExecutePermissionPrefix2 { get { return ExecutePermissionPrefix; } } - + internal string ApiExecutePermissionPrefix2(string gxMethod) { return ApiExecutePermissionPrefix(gxMethod); } + internal GAMSecurityLevel ApiIntegratedSecurityLevel2(string gxMethod) { return ApiIntegratedSecurityLevel(gxMethod); } public virtual string ServiceExecutePermissionPrefix { get { return string.Empty; } } public virtual string ServiceDeletePermissionPrefix { get { return string.Empty; } } public virtual string ServiceInsertPermissionPrefix { get { return string.Empty; } } @@ -144,12 +146,15 @@ public virtual void cleanup() { } protected virtual GAMSecurityLevel IntegratedSecurityLevel { get { return 0; } } protected virtual bool IsSynchronizer { get { return false; } } protected virtual string ExecutePermissionPrefix { get { return String.Empty; } } + + protected virtual string ApiExecutePermissionPrefix(string gxMethod) { return ExecutePermissionPrefix2; } + protected virtual GAMSecurityLevel ApiIntegratedSecurityLevel(string gxMethod) { return IntegratedSecurityLevel2; } public virtual void handleException(String gxExceptionType, String gxExceptionDetails, String gxExceptionStack) { } public virtual void CallWebObject(string url) { string target = GetCallTargetFromUrl(url); - if (String.IsNullOrEmpty(target)) + if (String.IsNullOrEmpty(target)) { context.wjLoc = url; } diff --git a/dotnet/src/dotnetframework/GxClasses/Services/GXRestServices.cs b/dotnet/src/dotnetframework/GxClasses/Services/GXRestServices.cs index df1ac4b32..19c37601f 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/GXRestServices.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/GXRestServices.cs @@ -233,6 +233,7 @@ public class GxRestService : System.Web.SessionState.IRequiresSessionState private HttpContext httpContext; private WebOperationContext wcfContext; protected string permissionPrefix; + protected string permissionMethod; bool runAsMain = true; public GxRestService() diff --git a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs index fdaee8dbd..71adbd030 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs @@ -110,7 +110,7 @@ public virtual Task MethodBodyExecute(object key) if (!IsAuthenticated(synchronizer)) return Task.CompletedTask; } - else if (!IsAuthenticated()) + else if (!IsAuthenticatedMethod(this._serviceMethod, _procWorker.IsApiObject)) { return Task.CompletedTask; } @@ -135,7 +135,7 @@ public virtual Task MethodBodyExecute(object key) if (!String.IsNullOrEmpty(this._serviceMethod)) { innerMethod = this._serviceMethod; - bodyParameters = PreProcessApiSdtParameter(_procWorker, innerMethod, bodyParameters, this._variableAlias); + bodyParameters = PreProcessApiSdtParameter( _procWorker, innerMethod, bodyParameters, this._variableAlias); } Dictionary outputParameters = ReflectionHelper.CallMethod(_procWorker, innerMethod, bodyParameters, _gxContext); Dictionary formatParameters = ReflectionHelper.ParametersFormat(_procWorker, innerMethod); @@ -300,7 +300,7 @@ public virtual Task MethodUrlExecute(object key) { try { - if (!IsAuthenticated()) + if (!IsAuthenticatedMethod(this._serviceMethod, _procWorker.IsApiObject)) { return Task.CompletedTask; } @@ -537,9 +537,19 @@ public bool IsAuthenticated(string synchronizer) SetError("0", "Invalid Synchronizer " + synchronizer); } } + protected bool IsAuthenticatedMethod(string serviceMethod, bool isApi) + { + if (!String.IsNullOrEmpty(serviceMethod) && isApi) + { + bool integratedSecurityEnabled = ( Worker.IntegratedSecurityEnabled2 && Worker.ApiIntegratedSecurityLevel2(serviceMethod) != GAMSecurityLevel.SecurityNone); + return IsAuthenticated(Worker.ApiIntegratedSecurityLevel2(serviceMethod), integratedSecurityEnabled, Worker.ApiExecutePermissionPrefix2(serviceMethod)); + } + else + return IsAuthenticated(); + } public bool IsAuthenticated() { - return IsAuthenticated(Worker.IntegratedSecurityLevel2, Worker.IntegratedSecurityEnabled2, Worker.ExecutePermissionPrefix2); + return IsAuthenticated( Worker.IntegratedSecurityLevel2, Worker.IntegratedSecurityEnabled2, Worker.ExecutePermissionPrefix2); } protected bool IsAuthenticated(GAMSecurityLevel objIntegratedSecurityLevel, bool objIntegratedSecurityEnabled, string objPermissionPrefix) { From f8d830ef62a2863827a5c2abfff73eb00ad739cd Mon Sep 17 00:00:00 2001 From: Ana Berta <31777352+anaiberta@users.noreply.github.com> Date: Fri, 28 Jul 2023 11:02:47 -0300 Subject: [PATCH 014/164] Bump System.Security.Cryptography.Pkcs from 6.0.0 to 6.0.3 (#852) Issue: 103960 --- dotnet/src/dotnetcore/GxExcel/GxExcel.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/src/dotnetcore/GxExcel/GxExcel.csproj b/dotnet/src/dotnetcore/GxExcel/GxExcel.csproj index 15df73743..365ebaf33 100644 --- a/dotnet/src/dotnetcore/GxExcel/GxExcel.csproj +++ b/dotnet/src/dotnetcore/GxExcel/GxExcel.csproj @@ -18,7 +18,7 @@ - + From ffdc8d2c8cd0fa8e1280a50c687dbebccece2f69 Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Fri, 28 Jul 2023 17:24:48 -0300 Subject: [PATCH 015/164] Fix security issue in CosmosDB. Log shows sensitive data. (#853) --- .../DynService/Cosmos/CosmosDBConnection.cs | 18 ++++++++++++++++++ .../GxClasses/Data/GXDataCommon.cs | 8 +++++++- .../GxClasses/Data/GXDataNTierService.cs | 2 +- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/dotnet/src/dotnetcore/DynService/Cosmos/CosmosDBConnection.cs b/dotnet/src/dotnetcore/DynService/Cosmos/CosmosDBConnection.cs index 34bf4cea4..756d8c365 100644 --- a/dotnet/src/dotnetcore/DynService/Cosmos/CosmosDBConnection.cs +++ b/dotnet/src/dotnetcore/DynService/Cosmos/CosmosDBConnection.cs @@ -25,6 +25,24 @@ public override IDataReader GetCacheDataReader(CacheItem item, bool computeSize, { return new GxCosmosDBCacheDataReader(item, computeSize, keyCache); } + protected override string BuildConnectionStringForLog(string datasourceName, string userId, + string userPassword, string databaseName, string port, string schema, string extra) + { + StringBuilder connectionString = new StringBuilder(); + if (!string.IsNullOrEmpty(datasourceName)) + { + connectionString.AppendFormat("Data Source={0};", NaV); + } + if (userId != null) + { + connectionString.AppendFormat(";User ID={0};Password={1}", userId, NaV); + } + if (!string.IsNullOrEmpty(extra)) + { + connectionString.AppendFormat(";{0}", extra); + } + return connectionString.ToString(); + } } public class CosmosDBConnection : ServiceConnection diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs index 6a7818d49..71d9f17d0 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs @@ -358,7 +358,13 @@ public string BuildConnectionStringImpl(string datasourceName, string userId, } protected abstract string BuildConnectionString(string datasourceName, string userId, - string userPassword,string databaseName, string port, string schema, string extra); + string userPassword,string databaseName, string port, string schema, string extra); + + protected virtual string BuildConnectionStringForLog(string datasourceName, string userId, + string userPassword, string databaseName, string port, string schema, string extra) + { + return BuildConnectionString(datasourceName, userId, userPassword, databaseName, port, schema, extra); + } public virtual object[] ExecuteStoredProcedure(IDbCommand cmd) { diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierService.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierService.cs index 98b89d3af..e29d0edb0 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierService.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierService.cs @@ -116,7 +116,7 @@ public override GxAbstractConnectionWrapper GetConnection(bool showPrompt, strin { if (string.IsNullOrEmpty(m_connectionString)) m_connectionString = BuildConnectionString(datasourceName, userId, userPassword, databaseName, port, schema, extra); - GXLogging.Debug(log, "Setting connectionString property ", () => BuildConnectionString(datasourceName, userId, NaV, databaseName, port, schema, extra)); + GXLogging.Debug(log, "Setting connectionString property ", () => BuildConnectionStringForLog(datasourceName, userId, NaV, databaseName, port, schema, extra)); return new ServiceConnectionWrapper(m_ServiceType, m_connectionString, connectionCache, isolationLevel, DataSource); } From 17dc39daea5a283d1291a277a48236ca853caa8c Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Mon, 31 Jul 2023 20:11:30 -0300 Subject: [PATCH 016/164] Update Microsoft.Identity.Client version for GXMail (#854) --- dotnet/src/dotnetcore/GxMail/GxMail.csproj | 4 ++-- dotnet/src/dotnetframework/GxMail/GxMail.csproj | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dotnet/src/dotnetcore/GxMail/GxMail.csproj b/dotnet/src/dotnetcore/GxMail/GxMail.csproj index 0b7d837ce..96110449e 100644 --- a/dotnet/src/dotnetcore/GxMail/GxMail.csproj +++ b/dotnet/src/dotnetcore/GxMail/GxMail.csproj @@ -1,7 +1,7 @@ net6.0 - 1701;1702;NU1701 + 1701;1702;NU1701;CS0618 NETCORE SMTP Exchange POP3 GeneXus.Mail.Core @@ -70,7 +70,7 @@ - + diff --git a/dotnet/src/dotnetframework/GxMail/GxMail.csproj b/dotnet/src/dotnetframework/GxMail/GxMail.csproj index 0f121131f..3094e94a5 100644 --- a/dotnet/src/dotnetframework/GxMail/GxMail.csproj +++ b/dotnet/src/dotnetframework/GxMail/GxMail.csproj @@ -12,7 +12,7 @@ - + From 0e4a98ed1cbae4a2b412d555245135aec9bc30a9 Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Wed, 2 Aug 2023 08:36:32 -0300 Subject: [PATCH 017/164] Support Oauth 2.0 Authentication for Event Grid API (#855) --- .../GXAzureEventGrid/AzureEventGrid.cs | 96 ++++++++++--------- .../GXAzureEventGrid/GXAzureEventGrid.csproj | 1 + 2 files changed, 51 insertions(+), 46 deletions(-) diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/AzureEventGrid.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/AzureEventGrid.cs index 584464ee4..19dd0e6d3 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/AzureEventGrid.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/AzureEventGrid.cs @@ -1,15 +1,16 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Runtime.Serialization; using System.Text.Json; using System.Threading.Tasks; using Azure; +using Azure.Identity; using Azure.Messaging; using Azure.Messaging.EventGrid; using GeneXus.Messaging.Common; using GeneXus.Services; using GeneXus.Utils; +using log4net; namespace GeneXus.Messaging.GXAzureEventGrid { @@ -19,6 +20,7 @@ public class AzureEventGrid : EventRouterBase, IEventRouter private EventGridPublisherClient _client; private string _endpoint; private string _accessKey; + static readonly ILog logger = LogManager.GetLogger(typeof(AzureEventGrid)); public AzureEventGrid() : this(null) { } @@ -32,11 +34,20 @@ private void Initialize(GXService providerService) _endpoint = serviceSettings.GetEncryptedPropertyValue(PropertyConstants.URI_ENDPOINT); _accessKey = serviceSettings.GetEncryptedPropertyValue(PropertyConstants.ACCESS_KEY); - if (!string.IsNullOrEmpty(_endpoint)) { + if (!string.IsNullOrEmpty(_endpoint)) { + if (!string.IsNullOrEmpty(_accessKey)) _client = new EventGridPublisherClient( new Uri(_endpoint), new AzureKeyCredential(_accessKey)); + else + //Try authenticating using AD + { + GXLogging.Debug(logger,"Authentication using Oauth 2.0."); + _client = new EventGridPublisherClient( + new Uri(_endpoint), + new DefaultAzureCredential()); + } } else throw new Exception("Endpoint URI must be set."); @@ -50,22 +61,15 @@ public bool SendEvent(GXCloudEvent gxCloudEvent, bool binaryData) { CloudEvent evt = ToCloudEvent(gxCloudEvent, binaryData); bool success = false; - try + Task task; + if (_client != null) { - Task task; - if (_client != null) - { - task = Task.Run(async () => await sendEvtAsync(evt).ConfigureAwait(false)); - success = true; - } - else - { - throw new Exception("There was an error at the Event Grid initialization."); - } + task = Task.Run(async () => await sendEvtAsync(evt).ConfigureAwait(false)); + success = task.Result; } - catch (AggregateException ae) + else { - throw ae; + throw new Exception("There was an error at the Event Grid initialization."); } return success; } @@ -76,22 +80,15 @@ public bool SendEvents(IList gxCloudEvents, bool binaryData) evts.Add(ToCloudEvent(e, binaryData)); bool success = false; - try + Task task; + if (_client != null) { - Task task; - if (_client != null) - { - task = Task.Run(async () => await sendEvtsAsync(evts).ConfigureAwait(false)); - success = true; - } - else - { - throw new Exception("There was an error at the Event Grid initialization."); - } + task = Task.Run(async () => await sendEvtsAsync(evts).ConfigureAwait(false)); + success = task.Result; } - catch (AggregateException ae) + else { - throw ae; + throw new Exception("There was an error at the Event Grid initialization."); } return success; } @@ -112,11 +109,11 @@ public bool SendCustomEvents(string jsonString, bool isBinary) bool success = false; try { - Task task; + Task task; if (_client != null) { task = Task.Run(async () => await sendEventGridSchemaEventsAsync(eventGridEvents).ConfigureAwait(false)); - success = true; + success = task.Result; } else { @@ -137,11 +134,11 @@ public bool SendCustomEvents(string jsonString, bool isBinary) bool success = false; try { - Task task; + Task task; if (_client != null) { task = Task.Run(async () => await sendEventGridSchemaEventAsync(ToEventGridSchema(evt, isBinary)).ConfigureAwait(false)); - success = true; + success = task.Result; } else { @@ -166,39 +163,46 @@ public bool SendCustomEvents(string jsonString, bool isBinary) /// Send asynchronously an event formatted as Azure EventGrid Schema. /// /// - /// - private async Task sendEventGridSchemaEventAsync(EventGridEvent evt) + /// bool + private async Task sendEventGridSchemaEventAsync(EventGridEvent evt) { - await _client.SendEventAsync(evt).ConfigureAwait(false); - + Response response = await _client.SendEventAsync(evt).ConfigureAwait(false); + GXLogging.Debug(logger,string.Format("Send Event GridSchema: {0} {1}", response.Status, response.ReasonPhrase)); + return !response.IsError; + } /// /// Send asynchronously a list of events formatted as Azure EventGrid Schema. /// /// - /// - private async Task sendEventGridSchemaEventsAsync(IEnumerable evts) + /// bool + private async Task sendEventGridSchemaEventsAsync(IEnumerable evts) { - await _client.SendEventsAsync(evts).ConfigureAwait(false); + Response response = await _client.SendEventsAsync(evts).ConfigureAwait(false); + GXLogging.Debug(logger,string.Format("Send Events GridSchema: {0} {1}", response.Status, response.ReasonPhrase)); + return !response.IsError; } /// /// Send asynchronously an event formatted as CloudEvent Schema. /// /// - /// - private async Task sendEvtAsync(CloudEvent cloudEvent) + /// bool + private async Task sendEvtAsync(CloudEvent cloudEvent) { - await _client.SendEventAsync(cloudEvent).ConfigureAwait(false); - + Response response = await _client.SendEventAsync(cloudEvent).ConfigureAwait(false); + GXLogging.Debug(logger,string.Format("Send Event: {0} {1}", response.Status,response.ReasonPhrase)); + return !response.IsError; } /// /// Send asynchronously a list of CloudEvent Schema formatted events. /// /// - /// - private async Task sendEvtsAsync(IEnumerable cloudEvents) + /// bool + private async Task sendEvtsAsync(IEnumerable cloudEvents) { - await _client.SendEventsAsync(cloudEvents).ConfigureAwait(false); + Response response = await _client.SendEventsAsync(cloudEvents).ConfigureAwait(false); + GXLogging.Debug(logger,string.Format("Send Events: {0} {1}", response.Status, response.ReasonPhrase)); + return !response.IsError; } #endregion diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj index 0dd71f20c..e50e530ad 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj @@ -7,6 +7,7 @@ + From c116699c7a011846e6ba25468fdec8af0d5bfa8d Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 2 Aug 2023 14:06:15 -0300 Subject: [PATCH 018/164] Content-type header was not set properly at webservices. (#856) --- .../GxClasses/Core/GXApplication.cs | 117 ++++++++++-------- 1 file changed, 62 insertions(+), 55 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs index 5f5c71a9f..ab0536f02 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs @@ -18,7 +18,6 @@ namespace GeneXus.Application using Microsoft.AspNetCore.Http; using GxClasses.Helpers; using Experimental.System.Messaging; - using Microsoft.Net.Http.Headers; #endif using GeneXus.Configuration; using GeneXus.Metadata; @@ -49,6 +48,7 @@ namespace GeneXus.Application using System.Threading; using System.Security.Claims; using System.Security; + using Microsoft.Net.Http.Headers; public interface IGxContext { @@ -2433,74 +2433,81 @@ private void SetCustomHttpHeader(string name, string value) { try { - #if !NETCORE - - switch (name.ToUpper()) - { - case "CACHE-CONTROL": - if (CacheControlHeaderValue.TryParse(value, out CacheControlHeaderValue parsedValue)) - { - HttpContext.Current.Response.CacheControl = parsedValue.ToString(); - } - else - { - var Cache = _HttpContext.Response.Cache; - string[] values = value.Split(','); - foreach (string v in values) - { - switch (v.Trim().ToUpper()) - { - case "PUBLIC": - Cache.SetCacheability(HttpCacheability.Public); - break; - case "PRIVATE": - Cache.SetCacheability(HttpCacheability.Private); - break; - case "NO-CACHE": - Cache.SetCacheability(HttpCacheability.NoCache); - break; - case "NO-STORE": - Cache.AppendCacheExtension("no-store, must-revalidate"); - break; - default: - GXLogging.Warn(log, String.Format("Could not set Cache Control Http Header Value '{0}' to HttpResponse", value)); - break; - } - } - } - break; - default: - _HttpContext.Response.Headers[name] = value; - break; - } -#else - switch (name.ToUpper()) + + if (name.Equals(HeaderNames.CacheControl, StringComparison.OrdinalIgnoreCase)) { - case "CACHE-CONTROL": - if (CacheControlHeaderValue.TryParse(value, out CacheControlHeaderValue parsedValue)) - { - _HttpContext.Response.GetTypedHeaders().CacheControl = parsedValue; - } - else + if (System.Net.Http.Headers.CacheControlHeaderValue.TryParse(value, out System.Net.Http.Headers.CacheControlHeaderValue parsedValue)) + { + HttpContext.Current.Response.CacheControl = parsedValue.ToString(); + } + else + { + var Cache = _HttpContext.Response.Cache; + string[] values = value.Split(','); + foreach (string v in values) { - switch (value.ToUpper()) + switch (v.Trim().ToUpper()) { case "PUBLIC": - _HttpContext.Response.AddHeader("Cache-Control", "public"); + Cache.SetCacheability(HttpCacheability.Public); break; case "PRIVATE": - _HttpContext.Response.AddHeader("Cache-Control", "private"); + Cache.SetCacheability(HttpCacheability.Private); + break; + case "NO-CACHE": + Cache.SetCacheability(HttpCacheability.NoCache); + break; + case "NO-STORE": + Cache.AppendCacheExtension("no-store, must-revalidate"); break; default: GXLogging.Warn(log, String.Format("Could not set Cache Control Http Header Value '{0}' to HttpResponse", value)); break; } } - break; - default: + } + } + else if (name.Equals(HeaderNames.ContentType, StringComparison.OrdinalIgnoreCase)) + { + _HttpContext.Response.ContentType = value; + } + else + { + if (!string.IsNullOrEmpty(_HttpContext.Response.Headers[name])) + { + _HttpContext.Response.Headers[name] = value; + } + else + { + _HttpContext.Response.AppendHeader(name, value); + } + } +#else + if (name.Equals(HeaderNames.CacheControl, StringComparison.OrdinalIgnoreCase)) + { + if (CacheControlHeaderValue.TryParse(value, out CacheControlHeaderValue parsedValue)) + { + _HttpContext.Response.GetTypedHeaders().CacheControl = parsedValue; + } + else + { + switch (value.ToUpper()) + { + case "PUBLIC": + _HttpContext.Response.AddHeader(HeaderNames.CacheControl, "public"); + break; + case "PRIVATE": + _HttpContext.Response.AddHeader(HeaderNames.CacheControl, "private"); + break; + default: + GXLogging.Warn(log, String.Format("Could not set Cache Control Http Header Value '{0}' to HttpResponse", value)); + break; + } + } + } + else { _HttpContext.Response.AddHeader(name, value); - break; } #endif } From 649f58e7e75ef5d87fc50eafec0b732956d6130f Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 8 Aug 2023 21:19:00 -0300 Subject: [PATCH 019/164] Setting Header no-store was throwing an exception (#859) * Setting Header no-store was throwing an exception when assigned with the expression HttpContext.Current.Response.CacheControl = parsedValue.ToString(); * Fix build error. --- .../GxClasses/Core/GXApplication.cs | 63 +++++++++---------- .../DotNetUnitTest/Domain/GxHttpClientTest.cs | 20 ++++++ 2 files changed, 51 insertions(+), 32 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs index ab0536f02..633758f03 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs @@ -2425,11 +2425,10 @@ public byte SetHeader(string name, string value) _httpHeaders = new NameValueCollection(); } _httpHeaders[name] = value; - SetCustomHttpHeader(name, value); - return 0; + return SetCustomHttpHeader(name, value); } - private void SetCustomHttpHeader(string name, string value) + private byte SetCustomHttpHeader(string name, string value) { try { @@ -2437,34 +2436,27 @@ private void SetCustomHttpHeader(string name, string value) if (name.Equals(HeaderNames.CacheControl, StringComparison.OrdinalIgnoreCase)) { - if (System.Net.Http.Headers.CacheControlHeaderValue.TryParse(value, out System.Net.Http.Headers.CacheControlHeaderValue parsedValue)) - { - HttpContext.Current.Response.CacheControl = parsedValue.ToString(); - } - else + var Cache = _HttpContext.Response.Cache; + string[] values = value.Split(','); + foreach (string v in values) { - var Cache = _HttpContext.Response.Cache; - string[] values = value.Split(','); - foreach (string v in values) + switch (v.Trim().ToUpper()) { - switch (v.Trim().ToUpper()) - { - case "PUBLIC": - Cache.SetCacheability(HttpCacheability.Public); - break; - case "PRIVATE": - Cache.SetCacheability(HttpCacheability.Private); - break; - case "NO-CACHE": - Cache.SetCacheability(HttpCacheability.NoCache); - break; - case "NO-STORE": - Cache.AppendCacheExtension("no-store, must-revalidate"); - break; - default: - GXLogging.Warn(log, String.Format("Could not set Cache Control Http Header Value '{0}' to HttpResponse", value)); - break; - } + case "PUBLIC": + Cache.SetCacheability(HttpCacheability.Public); + break; + case "PRIVATE": + Cache.SetCacheability(HttpCacheability.Private); + break; + case "NO-CACHE": + Cache.SetCacheability(HttpCacheability.NoCache); + break; + case "NO-STORE": + Cache.AppendCacheExtension("no-store, must-revalidate"); + break; + default: + GXLogging.Warn(log, String.Format("Could not set Cache Control Http Header Value '{0}' to HttpResponse", value)); + break; } } } @@ -2472,15 +2464,20 @@ private void SetCustomHttpHeader(string name, string value) { _HttpContext.Response.ContentType = value; } + else if (name.Equals(HeaderNames.Location, StringComparison.OrdinalIgnoreCase)) + { + _HttpContext.Response.RedirectLocation = value; + } else { - if (!string.IsNullOrEmpty(_HttpContext.Response.Headers[name])) + try { _HttpContext.Response.Headers[name] = value; - } - else + + }catch (PlatformNotSupportedException ex) { _HttpContext.Response.AppendHeader(name, value); + GXLogging.Warn(log, ex, "SetHeader ", name, value); } } #else @@ -2510,10 +2507,12 @@ private void SetCustomHttpHeader(string name, string value) _HttpContext.Response.AddHeader(name, value); } #endif + return 0; } catch (Exception ex) { GXLogging.Error(log, ex, "Error adding header ", name, value); + return 1; } } diff --git a/dotnet/test/DotNetUnitTest/Domain/GxHttpClientTest.cs b/dotnet/test/DotNetUnitTest/Domain/GxHttpClientTest.cs index 29e460d76..4dd50cdd7 100644 --- a/dotnet/test/DotNetUnitTest/Domain/GxHttpClientTest.cs +++ b/dotnet/test/DotNetUnitTest/Domain/GxHttpClientTest.cs @@ -1,6 +1,12 @@ +using System.IO; using System.Net; +using GeneXus.Application; using GeneXus.Http.Client; using Xunit; +#if !NETCORE +using System.Web.SessionState; +using System.Web; +#endif namespace xUnitTesting { @@ -39,6 +45,20 @@ public void HttpClientInvalidURLWithCustomPort() Assert.NotEqual(((int)HttpStatusCode.InternalServerError), httpclient.StatusCode); } } +#if !NETCORE + [Fact] + public void NoStoreHeader() + { + var httpRequest = new HttpRequest("", "http://localhost/", ""); + var httpResponce = new HttpResponse(new StringWriter()); + var httpContext = new HttpContext(httpRequest, httpResponce); + HttpContext.Current = httpContext; + GxContext gxcontext = new GxContext(); + gxcontext.HttpContext = HttpContext.Current; + byte result = gxcontext.SetHeader("CACHE", "no-store"); + Assert.Equal(0, result); + } +#endif } } From bc32f1c453d43355903a91164b4a7a1da0e7a722 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 8 Aug 2023 21:19:12 -0300 Subject: [PATCH 020/164] Add timezone validation when reading ClientTimeZoneId (#857) * Add validation of timezone when reading ClientTimeZoneId from headers and cookies. * When reading cookie, try reading from undecoded cookie, otherwise, timezone "Etc/GMT+3" cookie value is read as "Etc/GMT 3" --- .../GxClasses/Core/GXApplication.cs | 29 ++++++++++++++++--- .../GxClasses/Core/GXUtilsCommon.cs | 16 +++++++--- .../DotNetUnitTest/Domain/TimeZoneTest.cs | 1 + 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs index 633758f03..12b78d3ea 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs @@ -2319,6 +2319,20 @@ public string GetCookie(string name) } return cookieVal; } + internal string GetUndecodedCookie(string name) + { + string cookieVal = string.Empty; + HttpCookie cookie = TryGetCookie(localCookies, name); + if (cookie == null && _HttpContext != null) + { + cookie = TryGetCookie(_HttpContext.Request.GetCookies(), name); + } + if (cookie != null && cookie.Value != null) + { + cookieVal = cookie.Value; + } + return cookieVal; + } private HttpCookie TryGetCookie(HttpCookieCollection cookieColl, string name) { @@ -3595,9 +3609,15 @@ internal string ClientTimeZoneId sTZ = (string)GetCookie(GX_REQUEST_TIMEZONE); GXLogging.Debug(log, "ClientTimeZone GX_REQUEST_TIMEZONE cookie:", sTZ); } + if (!DateTimeUtil.ValidTimeZone(sTZ)) + { + sTZ = (string)GetUndecodedCookie(GX_REQUEST_TIMEZONE); + GXLogging.Debug(log, "Try reading undecoded ClientTimeZone GX_REQUEST_TIMEZONE cookie:", sTZ); + } try { - _currentTimeZoneId = String.IsNullOrEmpty(sTZ) ? DateTimeZoneProviders.Tzdb.GetSystemDefault().Id : sTZ; + _currentTimeZoneId = !DateTimeUtil.ValidTimeZone(sTZ) ? DateTimeZoneProviders.Tzdb.GetSystemDefault().Id : sTZ; + } catch (Exception e1) { @@ -3642,14 +3662,15 @@ public String GetTimeZone() public Boolean SetTimeZone(String sTZ) { sTZ = StringUtil.RTrim(sTZ); - Boolean ret = false; + bool ret = false; #if NODATIME string tzId; try { - if (DateTimeZoneProviders.Tzdb[sTZ] != null) + DateTimeZone zone = DateTimeZoneProviders.Tzdb.GetZoneOrNull(sTZ); + if (zone != null) { - tzId = DateTimeZoneProviders.Tzdb[sTZ].Id; + tzId = zone.Id; } else { diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs index 643419e40..e77b73624 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs @@ -2430,9 +2430,9 @@ static public short CurrentOffset(IGxContext context) static private TimeSpan CurrentOffset(string clientTimeZone) { - DateTimeZone clientTimeZoneObj = DateTimeZoneProviders.Tzdb[clientTimeZone]; + DateTimeZone clientTimeZoneObj = DateTimeZoneProviders.Tzdb.GetZoneOrNull(clientTimeZone); if (clientTimeZoneObj == null) - clientTimeZoneObj = DateTimeZoneProviders.Tzdb[LocalTimeZoneId]; + clientTimeZoneObj = DateTimeZoneProviders.Tzdb.GetZoneOrNull(LocalTimeZoneId); Instant now = SystemClock.Instance.GetCurrentInstant(); try @@ -3246,7 +3246,7 @@ private static DateTime ConvertDateTime(DateTime dt, string fromTimezone, string DateTime ret = toUniversalTime(dt, fromTimezone); - if (string.IsNullOrEmpty(toTimezone) || DateTimeZoneProviders.Tzdb[toTimezone]==null) + if (!ValidTimeZone(toTimezone)) toTimezone = DateTimeZoneProviders.Tzdb.GetSystemDefault().Id; if (ret < OlsonMinTime) @@ -3260,6 +3260,11 @@ private static DateTime ConvertDateTime(DateTime dt, string fromTimezone, string } return dtconverted.AddMilliseconds(milliSeconds); } + internal static bool ValidTimeZone(string timeZone) + { + return !string.IsNullOrEmpty(timeZone) && DateTimeZoneProviders.Tzdb.GetZoneOrNull(timeZone) != null; + } + internal static DateTime Local2DBserver(DateTime dt, string clientTimezone) { try @@ -3562,7 +3567,10 @@ static public DateTime toUniversalTime(DateTime dt, IGxContext context) static public DateTime FromTimeZone(DateTime dt, String sTZ, IGxContext context) { #if NODATIME - return ConvertDateTime(dt, sTZ, context.GetTimeZone()); + if (ValidTimeZone(sTZ)) + return ConvertDateTime(dt, sTZ, context.GetTimeZone()); + else + return dt; #else OlsonTimeZone fromTimeZone = TimeZoneUtil.GetInstanceFromOlsonName(sTZ); if (fromTimeZone != null) diff --git a/dotnet/test/DotNetUnitTest/Domain/TimeZoneTest.cs b/dotnet/test/DotNetUnitTest/Domain/TimeZoneTest.cs index eaace6441..b9af8d29c 100644 --- a/dotnet/test/DotNetUnitTest/Domain/TimeZoneTest.cs +++ b/dotnet/test/DotNetUnitTest/Domain/TimeZoneTest.cs @@ -1,4 +1,5 @@ using System; +using GeneXus.Application; using GeneXus.Utils; using TZ4Net; using Xunit; From ff2432b755c9b33e87b6be50f257d13b8d789225 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 9 Aug 2023 11:39:42 -0300 Subject: [PATCH 021/164] Condition content-disposition=inline; filename to reports only. (#826) --- .../GxClasses/Model/GXWebProcedure.cs | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Model/GXWebProcedure.cs b/dotnet/src/dotnetframework/GxClasses/Model/GXWebProcedure.cs index c7f9978d7..43366566d 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/GXWebProcedure.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/GXWebProcedure.cs @@ -26,6 +26,7 @@ public class GXWebProcedure : GXHttpHandler protected IReportHandler oldReportHandler; string outputFileName; string outputType; + bool fileContentInline; protected int lineHeight; protected int Gx_line; @@ -129,18 +130,21 @@ protected override void sendCacheHeaders() private void setOuputFileName() { - string fileName = GetType().Name; - string fileType = "pdf"; - if (!string.IsNullOrEmpty(outputFileName)) + if (fileContentInline) { - fileName = outputFileName; - } - if (!string.IsNullOrEmpty(outputType)) - { - fileType = outputType.ToLower(); - } + string fileName = GetType().Name; + string fileType = "pdf"; + if (!string.IsNullOrEmpty(outputFileName)) + { + fileName = outputFileName; + } + if (!string.IsNullOrEmpty(outputType)) + { + fileType = outputType.ToLower(); + } - context.HttpContext.Response.AddHeader(HttpHeader.CONTENT_DISPOSITION, $"inline; filename={fileName}.{fileType}"); + context.HttpContext.Response.AddHeader(HttpHeader.CONTENT_DISPOSITION, $"inline; filename={fileName}.{fileType}"); + } } public virtual int getOutputType() @@ -152,6 +156,7 @@ protected bool initPrinter(String output, int gxXPage, int gxYPage, String iniFi string idiom; if (!Config.GetValueOf("LANGUAGE", out idiom)) idiom = "eng"; + fileContentInline = true; #if NETCORE setOuputFileName(); #endif From 7bd8980b2ca9365b79a5a02fa801c72b6c8f9823 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Thu, 10 Aug 2023 16:56:42 -0300 Subject: [PATCH 022/164] Improve tracing when reading timezone cookie (#863) --- .../GxClasses/Core/GXApplication.cs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs index 12b78d3ea..33a74fc1f 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs @@ -3616,8 +3616,22 @@ internal string ClientTimeZoneId } try { - _currentTimeZoneId = !DateTimeUtil.ValidTimeZone(sTZ) ? DateTimeZoneProviders.Tzdb.GetSystemDefault().Id : sTZ; - + if (!DateTimeUtil.ValidTimeZone(sTZ)) + { + try + { + string invalidTimezone = DateTimeZoneProviders.Tzdb[sTZ].Id; + }catch(Exception ex)//DateTimeZoneNotFound + { + GXLogging.Warn(log, $"Client timezone not found: {sTZ}", ex); + } + _currentTimeZoneId = DateTimeZoneProviders.Tzdb.GetSystemDefault().Id; + GXLogging.Warn(log, $"Setting Client timezone to System default: {_currentTimeZoneId}"); + } + else + { + _currentTimeZoneId = sTZ; + } } catch (Exception e1) { From a95bc42bab084f0488b3b881babdafcb2d7cf2e7 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 15 Aug 2023 10:33:23 -0300 Subject: [PATCH 023/164] Bump version to 1.26 after creating branch for v18u5 --- dotnet/Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/Directory.Build.props b/dotnet/Directory.Build.props index 760d6f7c4..54923a4af 100644 --- a/dotnet/Directory.Build.props +++ b/dotnet/Directory.Build.props @@ -3,7 +3,7 @@ 11.0.0.0 1 $([MSBuild]::Add($(MajorFileVersion), 100)) - 25 + 26 $(COMMIT_NUMBER) 0 $(MajorFileVersion).$(MinorFileVersion).$(PatchFileVersion) From cd56c7053c5b41d69fca3322bfc7dff512e5289b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Sexenian?= <99925035+tomas-sexenian@users.noreply.github.com> Date: Wed, 16 Aug 2023 10:13:55 -0300 Subject: [PATCH 024/164] RoundBorders method implementation (#858) * RoundBorders method implementation Issue: 104034 * Forgot to remove call to debugger * Use Uri class to check if image its an URL --- .../GxClasses/Core/GXUtilsCommon.cs | 130 ++++++++++++++++-- 1 file changed, 122 insertions(+), 8 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs index e77b73624..06fb16db1 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs @@ -48,6 +48,8 @@ using System.Threading.Tasks; using System.Drawing.Imaging; using System.Net.Http.Headers; +using Image = System.Drawing.Image; +using System.Net.Http; namespace GeneXus.Utils { @@ -5774,20 +5776,65 @@ public static class GxImageUtil private static Bitmap BitmapCreateFromStream(string filePathOrUrl) { - using (Stream s = ImageFile(filePathOrUrl).GetStream()) + Uri uri; + if (Uri.TryCreate(filePathOrUrl, UriKind.Absolute, out uri) && (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps)) { - if (s != null) - return new Bitmap(s); - return null; + using (HttpClient httpClient = new HttpClient()) + { + try + { + byte[] data = httpClient.GetByteArrayAsync(filePathOrUrl).Result; + using (MemoryStream mem = new MemoryStream(data)) + { + return new Bitmap(mem); + } + } + catch + { + return null; + } + } } + else + { + using (Stream s = ImageFile(filePathOrUrl).GetStream()) + { + if (s != null) + return new Bitmap(s); + return null; + } + } + } private static Image ImageCreateFromStream(string filePathOrUrl) { - using (Stream s = ImageFile(filePathOrUrl).GetStream()) + Uri uri; + if (Uri.TryCreate(filePathOrUrl, UriKind.Absolute, out uri) && (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps)) { - if (s != null) - return Image.FromStream(s); - return null; + using (HttpClient httpClient = new HttpClient()) + { + try + { + byte[] data = httpClient.GetByteArrayAsync(filePathOrUrl).Result; + using (MemoryStream mem = new MemoryStream(data)) + { + return Image.FromStream(mem); + } + } + catch + { + return null; + } + } + } + else + { + using (Stream s = ImageFile(filePathOrUrl).GetStream()) + { + if (s != null) + return Image.FromStream(s); + return null; + } } } @@ -5874,6 +5921,68 @@ public static string Crop(string imageFile, int X, int Y, int Width, int Height) } return modifiedImage; } + public static string RoundBorders(string imageFile, int topLeftRadius, int topRightRadius, int bottomLeftRadius, int bottomRightRadius) + { + string modifiedImage = string.Empty; + try + { + using (MemoryStream ms = new MemoryStream()) + { + using (Image OriginalImage = ImageCreateFromStream(imageFile)) + { + int w = OriginalImage.Width; + int h = OriginalImage.Height; + + using (Bitmap roundedImage = new Bitmap(w, h)) + { + roundedImage.SetResolution(OriginalImage.HorizontalResolution, OriginalImage.VerticalResolution); + using (Graphics g = Graphics.FromImage(roundedImage)) + { + g.SmoothingMode = SmoothingMode.AntiAlias; + g.Clear(Color.Transparent); + + using (GraphicsPath path = new GraphicsPath()) + { + path.StartFigure(); + if (topLeftRadius > 0) + path.AddArc(0, 0, 2 * topLeftRadius, 2 * topLeftRadius, (float) 180, (float) 90); + path.AddLine(topLeftRadius, 0, w - topRightRadius, 0); + if (topRightRadius > 0) + path.AddArc(w - 2 * topRightRadius, 0, 2 * topRightRadius, 2 * topRightRadius, (float) 270, (float) 90); + path.AddLine(w, topRightRadius, w, h - bottomRightRadius); + if (bottomRightRadius > 0) + path.AddArc(w - 2 * bottomRightRadius, h - 2 * bottomRightRadius, 2 * bottomRightRadius, 2 * bottomRightRadius, (float) 0, (float) 90); + path.AddLine(w - bottomLeftRadius, h, bottomLeftRadius, h); + if (bottomLeftRadius > 0) + path.AddArc(0, h - 2 * bottomLeftRadius, 2 * bottomLeftRadius, 2 * bottomLeftRadius, (float) 90, (float) 90); + path.CloseFigure(); + + g.FillPath(Brushes.White, path); + + using (TextureBrush br = new TextureBrush(new Bitmap(OriginalImage), WrapMode.Clamp)) + { + g.FillPath(br, path); + } + } + } + // Rounded images are basically images with transparent rounded borders and jpg and jpeg formats do not + // support transparency, so we have to create a new identical image but in png format + if (imageFile.IndexOf(".jpg") > 0) + modifiedImage = Save(roundedImage, imageFile.Replace(".jpg", ".png"), ImageFormat.Png); + else if (imageFile.IndexOf(".jpeg") > 0) + modifiedImage = Save(roundedImage, imageFile.Replace(".jpeg", ".png"), ImageFormat.Png); + else + modifiedImage = Save(roundedImage, imageFile, OriginalImage.RawFormat); + } + } + } + } + catch (Exception ex) + { + GXLogging.Error(log, $"RoundBorders {imageFile} failed", ex); + } + return modifiedImage; + } public static string Rotate(string imageFile, int angle) { string modifiedImage = string.Empty; @@ -5961,6 +6070,11 @@ public static string Save(Image bitmap, string imageFile, ImageFormat format) ms.Position = 0; try { + if (imageFile.StartsWith("http://") || imageFile.StartsWith("https://")) + { + Uri uri = new Uri(imageFile); + imageFile = Path.GetFileName(uri.AbsolutePath); + } GxFile sourceImage = new GxFile(GxContext.StaticPhysicalPath(), imageFile); string destinationImageName = FileUtil.getTempFileName(sourceImage.GetDirectory().GetAbsoluteName(), Path.GetFileNameWithoutExtension(sourceImage.GetName()), sourceImage.GetExtension()); GxFile destinationImage = new GxFile(GxContext.StaticPhysicalPath(), destinationImageName); From b532c2a4194caa8f7fe6c3b3ca208968e8b248a0 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 16 Aug 2023 15:40:27 -0300 Subject: [PATCH 025/164] OpenFromString attempted to read a file using the XML content as the parameter (#861) --- dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs | 9 --------- .../dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs | 9 +-------- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs b/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs index 369c75818..71b13de71 100644 --- a/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs +++ b/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs @@ -32,7 +32,6 @@ public interface IGxXmlFunctions } public class GXXMLReader : IDisposable { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Configuration.Config)); public const short ElementType = 1; public const short EndTagType = 2; public const short TextType = 4; @@ -275,14 +274,6 @@ public void OpenFromString(string s) Uri baseUri = new Uri( sBaseDirectory ); Resolver.Myself = baseUri; CreateXMLSettings(); - try - { - if (File.Exists(s)) - XMLInput = new FileStream(s, FileMode.Open, FileAccess.Read); - } - catch(Exception ex) { - GXLogging.Warn(log, "OpenFromString file failed", ex); - } if (XMLInput ==null) XMLInput = new StringReader(s); } diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs index 3e5981eb1..f18f4a708 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs @@ -299,14 +299,7 @@ public void OpenFromString(string s) Resolver.Myself = baseUri; treader = null; mreader = null; - try - { - if (File.Exists(s)) - treader = new XmlTextReader(s); - } - catch { } - if (treader==null) - treader = new XmlTextReader(new StringReader(s)); + treader = new XmlTextReader(new StringReader(s)); SetDtdProcessing(treader, Resolver, validationType); vreader = new XmlValidatingReader( treader ); vreader.XmlResolver = Resolver; From 08b2d1d1c913186c0b8fd9d4972ed6cd0f5b4d21 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 16 Aug 2023 15:41:11 -0300 Subject: [PATCH 026/164] Cache failed dynamic calls to avoid loading all assemblies each time. (#836) --- .../GxClasses/Helpers/GXMetadata.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXMetadata.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXMetadata.cs index ae6a24b09..770cc499e 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXMetadata.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXMetadata.cs @@ -83,9 +83,8 @@ static public Type FindType(string defaultAssemblyName, string ns, string clssWi string clss = string.IsNullOrEmpty(ns) ? clssWithoutNamespace : string.Format("{0}.{1}", ns, clssWithoutNamespace); Type objType = null; string appNS; - loadedAssemblies.TryGetValue(clss, out objType); - if (objType == null) - { + if (!loadedAssemblies.TryGetValue(clss, out objType)) + { if (defaultAssembly != null) { try @@ -199,15 +198,15 @@ static public Type FindType(string defaultAssemblyName, string ns, string clssWi } } - if (objType == null) - { - GXLogging.Error(log, "Failed to load type: " + clss + " from currentdomain"); - throw new GxClassLoaderException("Failed to load type: " + clss); - } } loadedAssemblies[clss] = objType; } + if (objType == null) + { + GXLogging.Error(log, "Failed to load type: " + clss + " from currentdomain"); + throw new GxClassLoaderException("Failed to load type: " + clss); + } return objType; } From 36fe66a9ba602e9ff0a31ff4692d9e5c72f0e09d Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Mon, 21 Aug 2023 13:44:42 -0300 Subject: [PATCH 027/164] Add explicit reference to newtonsoft, required by BlobTriggerHandler.cs. (#866) It will be needed for PR #862 --- .../GeneXus.Deploy.AzureFunctions.Handlers.csproj | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj b/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj index b8ce2e81d..94db46c2f 100644 --- a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj +++ b/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj @@ -15,6 +15,7 @@ true true true + true @@ -27,9 +28,12 @@ - - + + + + + @@ -44,7 +48,6 @@ - @@ -62,9 +65,9 @@ - +
From 14c9612517a35b3e726f6c51630bb8cd258820ed Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Mon, 21 Aug 2023 15:59:38 -0300 Subject: [PATCH 028/164] Azure AD Authentication for Service Bus and Queue API (#865) --- .../GXAmazonSQS/AWSMessageQueueProvider.cs | 16 ++- .../Messaging/GXAmazonSQS/AWSQueue.cs | 41 +++--- .../GXAzureEventGrid/AzureEventGrid.cs | 3 +- .../GXAzureQueue/AzureMessageQueueProvider.cs | 31 ++++- .../Messaging/GXAzureQueue/AzureQueue.cs | 37 +++-- .../GXAzureQueue/GXAzureQueue.csproj | 1 + .../GXAzureServiceBus/AzureServiceBus.cs | 31 ++++- .../GXAzureServiceBus.csproj | 1 + .../ServiceBusMessageBrokerProvider.cs | 130 ++++++++++++++++-- .../GXMessageBroker/MessageBrokerBase.cs | 2 +- .../GXMessageBroker/MessageBrokerProvider.cs | 11 +- .../Messaging/GXMessageBroker/MessageQueue.cs | 10 +- .../GXMessageBroker/PropertyConstants.cs | 9 ++ .../GXMessageBroker/ServiceSettings.cs | 38 +++-- .../Messaging/GXQueue/MessageQueueProvider.cs | 34 +++-- .../Messaging/GXQueue/PropertyConstants.cs | 35 +++++ 16 files changed, 310 insertions(+), 120 deletions(-) create mode 100644 dotnet/src/dotnetcore/Providers/Messaging/GXQueue/PropertyConstants.cs diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSMessageQueueProvider.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSMessageQueueProvider.cs index ebf20e338..66b5394f0 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSMessageQueueProvider.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSMessageQueueProvider.cs @@ -21,8 +21,10 @@ public SimpleMessageQueue Connect(string queueURL, out GXBaseCollection errorMessagesConnect, out bool successConnect); errorMessages = errorMessagesConnect; success = successConnect; @@ -31,10 +33,12 @@ public SimpleMessageQueue Connect(string queueURL, out GXBaseCollection("Accesskey")); - properties.Add("QUEUE_AWSSQS_SECRET_KEY", awsCredentials.GetPropertyValue("Secretkey")); - properties.Add("QUEUE_AWSSQS_REGION", awsCredentials.GetPropertyValue("Region")); + GXProperties properties = new GXProperties + { + { "QUEUE_AWSSQS_ACCESS_KEY", awsCredentials.GetPropertyValue("Accesskey") }, + { "QUEUE_AWSSQS_SECRET_KEY", awsCredentials.GetPropertyValue("Secretkey") }, + { "QUEUE_AWSSQS_REGION", awsCredentials.GetPropertyValue("Region") } + }; return properties; } } diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs index f0ed5882d..1e76f3b24 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs @@ -16,7 +16,7 @@ namespace GeneXus.Messaging.Queue public class AWSQueue : QueueBase, IQueue { - public static String Name = "AWSSQS"; + public static string Name = "AWSSQS"; const string ACCESS_KEY = "ACCESS_KEY"; const string SECRET_ACCESS_KEY = "SECRET_KEY"; const string REGION = "REGION"; @@ -313,13 +313,14 @@ private MessageQueueResult SetupMessageQueueResult(SendMessageResponse response) messageQueueResult.MessageId = response.MessageId; messageQueueResult.MessageStatus = MessageQueueResultStatus.Sent; - messageQueueResult.MessageAttributes = new GXProperties(); - - messageQueueResult.MessageAttributes.Add("MD5OfMessageSystemAttributes", response.MD5OfMessageSystemAttributes); - messageQueueResult.MessageAttributes.Add("MD5OfMessageAttributes", response.MD5OfMessageAttributes); - messageQueueResult.MessageAttributes.Add("ContentLength", response.ContentLength.ToString()); - messageQueueResult.MessageAttributes.Add("MD5OfMessageBody", response.MD5OfMessageBody); - messageQueueResult.MessageAttributes.Add("SequenceNumber", response.SequenceNumber); + messageQueueResult.MessageAttributes = new GXProperties + { + { "MD5OfMessageSystemAttributes", response.MD5OfMessageSystemAttributes }, + { "MD5OfMessageAttributes", response.MD5OfMessageAttributes }, + { "ContentLength", response.ContentLength.ToString() }, + { "MD5OfMessageBody", response.MD5OfMessageBody }, + { "SequenceNumber", response.SequenceNumber } + }; Type t = response.ResponseMetadata.GetType(); PropertyInfo[] props = t.GetProperties(); @@ -342,12 +343,13 @@ private MessageQueueResult SetupMessageQueueResult(SendMessageBatchResultEntry r messageQueueResult.MessageId = response.Id; messageQueueResult.MessageStatus = MessageQueueResultStatus.Sent; - messageQueueResult.MessageAttributes = new GXProperties(); - - messageQueueResult.MessageAttributes.Add("MD5OfMessageSystemAttributes", response.MD5OfMessageSystemAttributes); - messageQueueResult.MessageAttributes.Add("MD5OfMessageAttributes", response.MD5OfMessageAttributes); - messageQueueResult.MessageAttributes.Add("MD5OfMessageBody", response.MD5OfMessageBody); - messageQueueResult.MessageAttributes.Add("SequenceNumber", response.SequenceNumber); + messageQueueResult.MessageAttributes = new GXProperties + { + { "MD5OfMessageSystemAttributes", response.MD5OfMessageSystemAttributes }, + { "MD5OfMessageAttributes", response.MD5OfMessageAttributes }, + { "MD5OfMessageBody", response.MD5OfMessageBody }, + { "SequenceNumber", response.SequenceNumber } + }; return messageQueueResult; } @@ -378,11 +380,12 @@ private SimpleQueueMessage SetupSimpleQueueMessage(Message response) simpleQueueMessage.MessageBody = response.Body; simpleQueueMessage.MessageHandleId = response.ReceiptHandle; - simpleQueueMessage.MessageAttributes = new GXProperties(); - - simpleQueueMessage.MessageAttributes.Add("MD5OfMessageAttributes", response.MD5OfMessageAttributes); - simpleQueueMessage.MessageAttributes.Add("MD5OfBody", response.MD5OfBody); - + simpleQueueMessage.MessageAttributes = new GXProperties + { + { "MD5OfMessageAttributes", response.MD5OfMessageAttributes }, + { "MD5OfBody", response.MD5OfBody } + }; + foreach (var messageAttribute in response.MessageAttributes) { MessageAttributeValue messageAttributeValue = messageAttribute.Value; diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/AzureEventGrid.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/AzureEventGrid.cs index 19dd0e6d3..921497aac 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/AzureEventGrid.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/AzureEventGrid.cs @@ -43,10 +43,11 @@ private void Initialize(GXService providerService) else //Try authenticating using AD { + ChainedTokenCredential credential = new ChainedTokenCredential(new ManagedIdentityCredential(), new ManagedIdentityCredential(Environment.GetEnvironmentVariable("AZURE_CLIENT_ID")), new EnvironmentCredential(), new AzureCliCredential()); GXLogging.Debug(logger,"Authentication using Oauth 2.0."); _client = new EventGridPublisherClient( new Uri(_endpoint), - new DefaultAzureCredential()); + credential); } } else diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureMessageQueueProvider.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureMessageQueueProvider.cs index 698d7c0cc..93a9f49df 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureMessageQueueProvider.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureMessageQueueProvider.cs @@ -3,16 +3,35 @@ namespace GeneXus.Messaging.Queue { + /// + /// Implementation of AzureQueue.MessageQueueProvider external object. + /// + /// public class AzureMessageQueueProvider { - private const string AZUREQUEUE = "AZUREQUEUE"; - public SimpleMessageQueue Connect(string queueName, string queueURL, out GXBaseCollection errorMessages, out bool success) + public SimpleMessageQueue Connect(string queueName, string connectionString, out GXBaseCollection errorMessages, out bool success) { MessageQueueProvider messageQueueProvider = new MessageQueueProvider(); - GXProperties properties = new GXProperties(); - properties.Add("QUEUE_AZUREQUEUE_QUEUENAME", queueName); - properties.Add("QUEUE_AZUREQUEUE_CONNECTIONSTRING", queueURL); - SimpleMessageQueue simpleMessageQueue = messageQueueProvider.Connect(AZUREQUEUE, properties, out GXBaseCollection errorMessagesConnect, out bool successConnect); + GXProperties properties = new GXProperties + { + { PropertyConstants.QUEUE_AZUREQUEUE_QUEUENAME, queueName }, + { PropertyConstants.QUEUE_AZUREQUEUE_CONNECTIONSTRING, connectionString }, + { PropertyConstants.AUTHENTICATION_METHOD, AuthenticationMethod.Password.ToString()} + }; + SimpleMessageQueue simpleMessageQueue = messageQueueProvider.Connect(PropertyConstants.AZURE_QUEUE_PROVIDERTYPENAME, properties, out GXBaseCollection errorMessagesConnect, out bool successConnect); + errorMessages = errorMessagesConnect; + success = successConnect; + return simpleMessageQueue; + } + public SimpleMessageQueue Authenticate(string queueURI, out GXBaseCollection errorMessages, out bool success) + { + MessageQueueProvider messageQueueProvider = new MessageQueueProvider(); + GXProperties properties = new GXProperties + { + { PropertyConstants.QUEUE_AZUREQUEUE_QUEUEURI, queueURI }, + { PropertyConstants.AUTHENTICATION_METHOD, AuthenticationMethod.ActiveDirectory.ToString()} + }; + SimpleMessageQueue simpleMessageQueue = messageQueueProvider.Connect(PropertyConstants.AZURE_QUEUE_PROVIDERTYPENAME, properties, out GXBaseCollection errorMessagesConnect, out bool successConnect); errorMessages = errorMessagesConnect; success = successConnect; return simpleMessageQueue; diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs index 6953c8080..0435a7a55 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs @@ -1,28 +1,28 @@ using System; using System.Collections.Generic; using System.Reflection; +using Azure.Identity; using Azure.Storage.Queues; using Azure.Storage.Queues.Models; using GeneXus.Messaging.Common; using GeneXus.Services; using GeneXus.Utils; +using log4net; namespace GeneXus.Messaging.Queue { public class AzureQueue : QueueBase, IQueue { + public static string Name = "AZUREQUEUE"; - public static String Name = "AZUREQUEUE"; - const string QUEUE_NAME = "QUEUENAME"; - const string QUEUE_CONNECTION_STRING = "CONNECTIONSTRING"; - + static readonly ILog logger = LogManager.GetLogger(typeof(AzureQueue)); QueueClient _queueClient { get; set; } private string _queueName { get; set; } private string _connectionString { get; set; } + private string _queueURI { get; set; } public AzureQueue() : this(null) - { - } + {} public AzureQueue(GXService providerService) : base(providerService) { @@ -31,16 +31,28 @@ public AzureQueue(GXService providerService) : base(providerService) private void Initialize(GXService providerService) { - ServiceSettings serviceSettings = new("QUEUE", Name, providerService); - _queueName = serviceSettings.GetEncryptedPropertyValue(QUEUE_NAME); - _connectionString = serviceSettings.GetEncryptedPropertyValue(QUEUE_CONNECTION_STRING); + ServiceSettings serviceSettings = new(PropertyConstants.QUEUE_SERVICE_NAME, Name, providerService); + _queueName = serviceSettings.GetEncryptedPropertyValue(PropertyConstants.QUEUENAME); + _connectionString = serviceSettings.GetEncryptedPropertyValue(PropertyConstants.CONNECTIONSTRING); + _queueURI = serviceSettings.GetEncryptedPropertyValue(PropertyConstants.QUEUEURI); + string authenticationMethod = serviceSettings.GetPropertiesValue(PropertyConstants.AUTHENTICATION_METHOD); QueueClientOptions queueClientOptions = new QueueClientOptions() { MessageEncoding = QueueMessageEncoding.Base64 }; - _queueClient = new QueueClient(_connectionString, _queueName, queueClientOptions); + if (authenticationMethod.Equals(AuthenticationMethod.ActiveDirectory.ToString())) + { + ChainedTokenCredential credential = new ChainedTokenCredential(new ManagedIdentityCredential(), new ManagedIdentityCredential(Environment.GetEnvironmentVariable("AZURE_CLIENT_ID")), new EnvironmentCredential(), new AzureCliCredential()); + _queueClient = new QueueClient(new Uri(_queueURI), credential,queueClientOptions); + GXLogging.Debug(logger, "Authenticate to Azure Storage Queue using Active Directory authentication."); + } + else + { + _queueClient = new QueueClient(_connectionString, _queueName, queueClientOptions); + GXLogging.Debug(logger, "Authenticate to Azure Storage Queue using Access Keys."); + } } QueueClient QueueClient @@ -59,11 +71,6 @@ public AzureQueue(string connectionString, string queueName) _connectionString = connectionString; } - //public AzureQueue(Uri uri, TokenCredential tokenCredential) - //{ - //_queueClient = new QueueClient(uri, tokenCredential); - //} - public bool GetMessageFromException(Exception ex, SdtMessages_Message msg) { try diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj index 491be781c..f66d540c0 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj @@ -7,6 +7,7 @@ + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/AzureServiceBus.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/AzureServiceBus.cs index e00d3c3c4..c44390a41 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/AzureServiceBus.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/AzureServiceBus.cs @@ -4,10 +4,12 @@ using System.Reflection; using System.Runtime.Serialization; using System.Threading.Tasks; +using Azure.Identity; using Azure.Messaging.ServiceBus; using GeneXus.Messaging.Common; using GeneXus.Services; using GeneXus.Utils; +using log4net; namespace GeneXus.Messaging.GXAzureServiceBus { @@ -15,12 +17,14 @@ public class AzureServiceBus : MessageBrokerBase, IMessageBroker { private const int MAX_MESSAGES_DEFAULT = 10; private const short LOCK_DURATION = 5; - public static String Name = "AZURESB"; + public static string Name = "AZURESB"; + static readonly ILog logger = LogManager.GetLogger(typeof(AzureServiceBus)); private ConcurrentDictionary> m_messages = new ConcurrentDictionary>(); ServiceBusClient _serviceBusClient { get; set; } private string _queueOrTopicName { get; set; } private string _connectionString { get; set; } + private string _fullyqualifiedNamespace { get; set; } private string _subscriptionName { get; set; } private ServiceBusSender _sender { get; set; } private ServiceBusReceiver _receiver { get; set; } @@ -41,15 +45,17 @@ private void Initialize(GXService providerService) _queueOrTopicName = serviceSettings.GetEncryptedPropertyValue(PropertyConstants.QUEUE_NAME); _connectionString = serviceSettings.GetEncryptedPropertyValue(PropertyConstants.QUEUE_CONNECTION_STRING); _subscriptionName = serviceSettings.GetEncryptedPropertyValue(PropertyConstants.TOPIC_SUBSCRIPTION); + _fullyqualifiedNamespace = serviceSettings.GetEncryptedPropertyValue(PropertyConstants.FULLYQUALIFIEDNAMESPACE); + string authenticationMethod = serviceSettings.GetPropertiesValue(PropertyConstants.AUTHENTICATION_METHOD); - string sessionEnabled = serviceSettings.GetEncryptedOptPropertyValue(PropertyConstants.SESSION_ENABLED); + string sessionEnabled = serviceSettings.GetPropertiesValue(PropertyConstants.SESSION_ENABLED); if (!string.IsNullOrEmpty(sessionEnabled)) _sessionEnabled = Convert.ToBoolean(sessionEnabled); else _sessionEnabled = false; - string senderIdentifier = serviceSettings.GetEncryptedOptPropertyValue(PropertyConstants.SENDER_IDENTIFIER); + string senderIdentifier = serviceSettings.GetPropertiesValue(PropertyConstants.SENDER_IDENTIFIER); ServiceBusSenderOptions serviceBusSenderOptions = new ServiceBusSenderOptions(); if (!string.IsNullOrEmpty(senderIdentifier)) @@ -58,7 +64,18 @@ private void Initialize(GXService providerService) //TO DO Consider connection options here //https://docs.microsoft.com/en-us/javascript/api/@azure/service-bus/servicebusclientoptions?view=azure-node-latest#@azure-service-bus-servicebusclientoptions-websocketoptions - _serviceBusClient = new ServiceBusClient(_connectionString); + if (authenticationMethod.Equals(AuthenticationMethod.ActiveDirectory.ToString())) + { + ChainedTokenCredential credential = new ChainedTokenCredential(new ManagedIdentityCredential(), new ManagedIdentityCredential(Environment.GetEnvironmentVariable("AZURE_CLIENT_ID")), new EnvironmentCredential(), new AzureCliCredential()); + _serviceBusClient = new ServiceBusClient(_fullyqualifiedNamespace, credential); + GXLogging.Debug(logger, "Authenticate to Azure Service Bus using Active Directory authentication."); + } + else + { + _serviceBusClient = new ServiceBusClient(_connectionString); + GXLogging.Debug(logger, "Authenticate to Azure Service Bus using SAS authentication."); + } + if (_serviceBusClient != null) { _sender = _serviceBusClient.CreateSender(_queueOrTopicName, serviceBusSenderOptions); @@ -66,9 +83,9 @@ private void Initialize(GXService providerService) { _serviceBusReceiverOptions = new ServiceBusReceiverOptions(); - string receiveMode = serviceSettings.GetEncryptedOptPropertyValue(PropertyConstants.RECEIVE_MODE); - string prefetchCount = serviceSettings.GetEncryptedOptPropertyValue(PropertyConstants.PREFETCH_COUNT); - string receiverIdentifier = serviceSettings.GetEncryptedOptPropertyValue(PropertyConstants.RECEIVER_IDENTIFIER); + string receiveMode = serviceSettings.GetPropertiesValue(PropertyConstants.RECEIVE_MODE); + string prefetchCount = serviceSettings.GetPropertiesValue(PropertyConstants.PREFETCH_COUNT); + string receiverIdentifier = serviceSettings.GetPropertiesValue(PropertyConstants.RECEIVER_IDENTIFIER); if (!string.IsNullOrEmpty(receiveMode)) _serviceBusReceiverOptions.ReceiveMode = (ServiceBusReceiveMode)Convert.ToInt16(receiveMode); diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj index 2de414bc5..c58643257 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj @@ -7,6 +7,7 @@ + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/ServiceBusMessageBrokerProvider.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/ServiceBusMessageBrokerProvider.cs index 036c89652..e1f0ab226 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/ServiceBusMessageBrokerProvider.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/ServiceBusMessageBrokerProvider.cs @@ -5,14 +5,31 @@ namespace GeneXus.Messaging.GXAzureServiceBus { + /// + /// Implementation of AzureServiceBus.MessageBrokerProvider external object. + /// public class ServiceBusMessageBrokerProvider { - public MessageQueue Connect(string queueName, string connectionString, out GXBaseCollection errorMessages, out bool success) + + #region Azure Active Directory Authentication + + public MessageQueue Authenticate(string queueName, string fullyQualifiedNamespace, bool sessionEnabled, GxUserType receiverOptions, string senderIdentifier, out GXBaseCollection errorMessages, out bool success) { MessageBrokerProvider messageBrokerProvider = new MessageBrokerProvider(); - GXProperties properties = new GXProperties(); - properties.Add(PropertyConstants.MESSAGEBROKER_AZURESB_QUEUENAME, queueName); - properties.Add(PropertyConstants.MESSAGEBROKER_AZURESB_CONNECTIONSTRING, connectionString); + ReceiverOptions options = TransformGXUserTypeToReceiverOptions(receiverOptions); + + GXProperties properties = new GXProperties + { + { PropertyConstants.MESSAGEBROKER_AZURESB_QUEUENAME, queueName }, + { PropertyConstants.MESSAGEBROKER_AZURESB_FULLYQUALIFIEDNAMESPACE, fullyQualifiedNamespace }, + { PropertyConstants.SESSION_ENABLED, sessionEnabled.ToString() }, + { PropertyConstants.RECEIVE_MODE, options.ReceiveMode.ToString() }, + { PropertyConstants.PREFETCH_COUNT, options.PrefetchCount.ToString() }, + { PropertyConstants.RECEIVER_IDENTIFIER, options.Identifier }, + { PropertyConstants.RECEIVER_SESSIONID, options.SessionId }, + { PropertyConstants.SENDER_IDENTIFIER, senderIdentifier }, + { PropertyConstants.AUTHENTICATION_METHOD, AuthenticationMethod.ActiveDirectory.ToString()} + }; MessageQueue messageQueue = messageBrokerProvider.Connect(PropertyConstants.AZURESERVICEBUS, properties, out GXBaseCollection errorMessagesConnect, out bool successConnect); errorMessages = errorMessagesConnect; @@ -20,13 +37,90 @@ public MessageQueue Connect(string queueName, string connectionString, out GXBas return messageQueue; } - public MessageQueue Connect(string topicName, string subcriptionName, string connectionString, out GXBaseCollection errorMessages, out bool success) + public MessageQueue Authenticate(string topicName, string subcriptionName, string fullyQualifiedNamespace, bool sessionEnabled, GxUserType receiverOptions, string senderIdentifier, out GXBaseCollection errorMessages, out bool success) { MessageBrokerProvider messageBrokerProvider = new MessageBrokerProvider(); GXProperties properties = new GXProperties(); + ReceiverOptions options = TransformGXUserTypeToReceiverOptions(receiverOptions); + properties.Add(PropertyConstants.MESSAGEBROKER_AZURESB_QUEUENAME, topicName); properties.Add(PropertyConstants.MESSAGEBROKER_AZURESB_SUBSCRIPTION_NAME, subcriptionName); - properties.Add(PropertyConstants.MESSAGEBROKER_AZURESB_CONNECTIONSTRING, connectionString); + properties.Add(PropertyConstants.MESSAGEBROKER_AZURESB_FULLYQUALIFIEDNAMESPACE, fullyQualifiedNamespace); + properties.Add(PropertyConstants.SESSION_ENABLED, sessionEnabled.ToString()); + properties.Add(PropertyConstants.RECEIVE_MODE, options.ReceiveMode.ToString()); + properties.Add(PropertyConstants.PREFETCH_COUNT, options.PrefetchCount.ToString()); + properties.Add(PropertyConstants.RECEIVER_IDENTIFIER, options.Identifier); + properties.Add(PropertyConstants.RECEIVER_SESSIONID, options.SessionId); + properties.Add(PropertyConstants.SENDER_IDENTIFIER, senderIdentifier); + properties.Add(PropertyConstants.AUTHENTICATION_METHOD, AuthenticationMethod.ActiveDirectory.ToString()); + + MessageQueue messageQueue = messageBrokerProvider.Connect(PropertyConstants.AZURESERVICEBUS, properties, out GXBaseCollection errorMessagesConnect, out bool successConnect); + errorMessages = errorMessagesConnect; + success = successConnect; + return messageQueue; + } + + public MessageQueue Authenticate(string queueName, string fullyQualifiedNamespace, out GXBaseCollection errorMessages, out bool success) + { + MessageBrokerProvider messageBrokerProvider = new MessageBrokerProvider(); + GXProperties properties = new GXProperties + { + { PropertyConstants.MESSAGEBROKER_AZURESB_QUEUENAME, queueName }, + { PropertyConstants.MESSAGEBROKER_AZURESB_FULLYQUALIFIEDNAMESPACE, fullyQualifiedNamespace }, + { PropertyConstants.AUTHENTICATION_METHOD, AuthenticationMethod.ActiveDirectory.ToString()} + }; + + MessageQueue messageQueue = messageBrokerProvider.Connect(PropertyConstants.AZURESERVICEBUS, properties, out GXBaseCollection errorMessagesConnect, out bool successConnect); + errorMessages = errorMessagesConnect; + success = successConnect; + return messageQueue; + } + public MessageQueue Authenticate(string topicName, string subcriptionName, string fullyQualifiedNamespace, out GXBaseCollection errorMessages, out bool success) + { + MessageBrokerProvider messageBrokerProvider = new MessageBrokerProvider(); + GXProperties properties = new GXProperties + { + { PropertyConstants.MESSAGEBROKER_AZURESB_QUEUENAME, topicName }, + { PropertyConstants.MESSAGEBROKER_AZURESB_SUBSCRIPTION_NAME, subcriptionName }, + { PropertyConstants.MESSAGEBROKER_AZURESB_FULLYQUALIFIEDNAMESPACE, fullyQualifiedNamespace }, + { PropertyConstants.AUTHENTICATION_METHOD, AuthenticationMethod.ActiveDirectory.ToString()} + }; + + MessageQueue messageQueue = messageBrokerProvider.Connect(PropertyConstants.AZURESERVICEBUS, properties, out GXBaseCollection errorMessagesConnect, out bool successConnect); + errorMessages = errorMessagesConnect; + success = successConnect; + return messageQueue; + } + #endregion + + #region Connect using SAS (Shared Access Signatures) + public MessageQueue Connect(string queueName, string connectionString, out GXBaseCollection errorMessages, out bool success) + { + MessageBrokerProvider messageBrokerProvider = new MessageBrokerProvider(); + GXProperties properties = new GXProperties + { + { PropertyConstants.MESSAGEBROKER_AZURESB_QUEUENAME, queueName }, + { PropertyConstants.MESSAGEBROKER_AZURESB_CONNECTIONSTRING, connectionString }, + { PropertyConstants.AUTHENTICATION_METHOD, AuthenticationMethod.Password.ToString()} + + }; + + MessageQueue messageQueue = messageBrokerProvider.Connect(PropertyConstants.AZURESERVICEBUS, properties, out GXBaseCollection errorMessagesConnect, out bool successConnect); + errorMessages = errorMessagesConnect; + success = successConnect; + return messageQueue; + } + + public MessageQueue Connect(string topicName, string subcriptionName, string connectionString, out GXBaseCollection errorMessages, out bool success) + { + MessageBrokerProvider messageBrokerProvider = new MessageBrokerProvider(); + GXProperties properties = new GXProperties + { + { PropertyConstants.MESSAGEBROKER_AZURESB_QUEUENAME, topicName }, + { PropertyConstants.MESSAGEBROKER_AZURESB_SUBSCRIPTION_NAME, subcriptionName }, + { PropertyConstants.MESSAGEBROKER_AZURESB_CONNECTIONSTRING, connectionString }, + { PropertyConstants.AUTHENTICATION_METHOD, AuthenticationMethod.Password.ToString()} + }; MessageQueue messageQueue = messageBrokerProvider.Connect(PropertyConstants.AZURESERVICEBUS, properties, out GXBaseCollection errorMessagesConnect, out bool successConnect); errorMessages = errorMessagesConnect; @@ -39,15 +133,18 @@ public MessageQueue Connect(string queueName, string connectionString, bool sess MessageBrokerProvider messageBrokerProvider = new MessageBrokerProvider(); ReceiverOptions options = TransformGXUserTypeToReceiverOptions(receiverOptions); - GXProperties properties = new GXProperties(); - properties.Add(PropertyConstants.MESSAGEBROKER_AZURESB_QUEUENAME, queueName); - properties.Add(PropertyConstants.MESSAGEBROKER_AZURESB_CONNECTIONSTRING, connectionString); - properties.Add(PropertyConstants.SESSION_ENABLED, sessionEnabled.ToString()); - properties.Add(PropertyConstants.RECEIVE_MODE, options.ReceiveMode.ToString()); - properties.Add(PropertyConstants.PREFETCH_COUNT, options.PrefetchCount.ToString()); - properties.Add(PropertyConstants.RECEIVER_IDENTIFIER, options.Identifier); - properties.Add(PropertyConstants.RECEIVER_SESSIONID, options.SessionId); - properties.Add(PropertyConstants.SENDER_IDENTIFIER, senderIdentifier); + GXProperties properties = new GXProperties + { + { PropertyConstants.MESSAGEBROKER_AZURESB_QUEUENAME, queueName }, + { PropertyConstants.MESSAGEBROKER_AZURESB_CONNECTIONSTRING, connectionString }, + { PropertyConstants.SESSION_ENABLED, sessionEnabled.ToString() }, + { PropertyConstants.RECEIVE_MODE, options.ReceiveMode.ToString() }, + { PropertyConstants.PREFETCH_COUNT, options.PrefetchCount.ToString() }, + { PropertyConstants.RECEIVER_IDENTIFIER, options.Identifier }, + { PropertyConstants.RECEIVER_SESSIONID, options.SessionId }, + { PropertyConstants.SENDER_IDENTIFIER, senderIdentifier }, + { PropertyConstants.AUTHENTICATION_METHOD, AuthenticationMethod.Password.ToString()} + }; MessageQueue messageQueue = messageBrokerProvider.Connect(PropertyConstants.AZURESERVICEBUS, properties, out GXBaseCollection errorMessagesConnect, out bool successConnect); errorMessages = errorMessagesConnect; @@ -70,6 +167,7 @@ public MessageQueue Connect(string topicName, string subcriptionName, string con properties.Add(PropertyConstants.RECEIVER_IDENTIFIER, options.Identifier); properties.Add(PropertyConstants.RECEIVER_SESSIONID, options.SessionId); properties.Add(PropertyConstants.SENDER_IDENTIFIER, senderIdentifier); + properties.Add(PropertyConstants.AUTHENTICATION_METHOD, AuthenticationMethod.Password.ToString()); MessageQueue messageQueue = messageBrokerProvider.Connect(PropertyConstants.AZURESERVICEBUS, properties, out GXBaseCollection errorMessagesConnect, out bool successConnect); errorMessages = errorMessagesConnect; @@ -77,6 +175,8 @@ public MessageQueue Connect(string topicName, string subcriptionName, string con return messageQueue; } + #endregion + #region Transformation methods private ReceiverOptions TransformGXUserTypeToReceiverOptions(GxUserType options) { diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageBrokerBase.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageBrokerBase.cs index 031837384..9f1e2ac80 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageBrokerBase.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageBrokerBase.cs @@ -28,6 +28,6 @@ public MessageBrokerBase(GXService s) service = s; } - public abstract String GetName(); + public abstract string GetName(); } } diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageBrokerProvider.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageBrokerProvider.cs index c3acfb7d8..c4bc73447 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageBrokerProvider.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageBrokerProvider.cs @@ -11,7 +11,7 @@ namespace GeneXus.Messaging.Common [GXApi] public class MessageBrokerProvider : MessageQueue { - static readonly ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private static GXService providerService; public MessageBrokerProvider() { @@ -64,7 +64,7 @@ public MessageQueue Connect(string providerTypeName, GXProperties properties, ou success = true; return (messageQueue); } - private static void Preprocess(String name, GXProperties properties) + private static void Preprocess(string name, GXProperties properties) { string className; @@ -75,6 +75,7 @@ private static void Preprocess(String name, GXProperties properties) SetEncryptedProperty(properties, PropertyConstants.MESSAGEBROKER_AZURESB_QUEUENAME); SetEncryptedProperty(properties, PropertyConstants.MESSAGEBROKER_AZURESB_SUBSCRIPTION_NAME); SetEncryptedProperty(properties, PropertyConstants.MESSAGEBROKER_AZURESB_CONNECTIONSTRING); + SetEncryptedProperty(properties, PropertyConstants.MESSAGEBROKER_AZURESB_FULLYQUALIFIEDNAMESPACE); if (string.IsNullOrEmpty(providerService.ClassName) || !providerService.ClassName.Contains(className)) { providerService.ClassName = PropertyConstants.AZURE_SB_PROVIDER_CLASSNAME; @@ -84,11 +85,11 @@ private static void Preprocess(String name, GXProperties properties) throw new SystemException(string.Format("Provider {0} is not supported.", name)); } } - private static void SetEncryptedProperty(GXProperties properties, String prop) + private static void SetEncryptedProperty(GXProperties properties, string prop) { - String value = properties.Get(prop); + string value = properties.Get(prop); if (string.IsNullOrEmpty(value)) - value = String.Empty; + value = string.Empty; value = CryptoImpl.Encrypt(value); properties.Set(prop, value); } diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageQueue.cs index 344626aa0..9f2a58649 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageQueue.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.IO; using System.Reflection; -using System.Text; using GeneXus.Services; using GeneXus.Utils; using GxClasses.Helpers; @@ -257,12 +256,12 @@ protected void QueueErrorMessagesSetup(Exception ex, out GXBaseCollection(); bool foundGeneralException = false; - if (errorMessages != null && ex != null) + if (ex != null) { SdtMessages_Message msg = new SdtMessages_Message(); - if (messageBroker != null) - { - while (ex.InnerException != null) + if (messageBroker != null && ex.InnerException != null) + { + do { if (messageBroker.GetMessageFromException(ex.InnerException, msg)) { @@ -276,6 +275,7 @@ protected void QueueErrorMessagesSetup(Exception ex, out GXBaseCollection errorMessages, out bool success) @@ -69,30 +67,30 @@ public SimpleMessageQueue Connect(string providerTypeName, GXProperties properti return (simpleMessageQueue); } - private static void Preprocess(String name, GXProperties properties) + private static void Preprocess(string name, GXProperties properties) { string className; - switch (name) { case "AZUREQUEUE": - className = "GeneXus.Messaging.Queue.AzureQueue"; - SetEncryptedProperty(properties, "QUEUE_AZUREQUEUE_QUEUENAME"); - SetEncryptedProperty(properties, "QUEUE_AZUREQUEUE_CONNECTIONSTRING"); + className = PropertyConstants.AZURE_QUEUE_CLASSNAME; + SetEncryptedProperty(properties, PropertyConstants.QUEUENAME); + SetEncryptedProperty(properties, PropertyConstants.CONNECTIONSTRING); + SetEncryptedProperty(properties, PropertyConstants.QUEUEURI); if (string.IsNullOrEmpty(providerService.ClassName) || !providerService.ClassName.Contains(className)) { - providerService.ClassName = "GeneXus.Messaging.Queue.AzureQueue, GXAzureQueue, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"; + providerService.ClassName = PropertyConstants.AZURE_QUEUE_PROVIDER_CLASSNAME; } break; case "AWS_SQS": className = "GeneXus.Messaging.Queue.AWSQueue"; - SetEncryptedProperty(properties, "QUEUE_AWSSQS_QUEUE_URL"); - SetEncryptedProperty(properties, "QUEUE_AWSSQS_ACCESS_KEY"); - SetEncryptedProperty(properties, "QUEUE_AWSSQS_SECRET_KEY"); - SetEncryptedProperty(properties, "QUEUE_AWSSQS_REGION"); + SetEncryptedProperty(properties, PropertyConstants.QUEUE_AWSSQS_QUEUE_URL); + SetEncryptedProperty(properties, PropertyConstants.QUEUE_AWSSQS_ACCESS_KEY); + SetEncryptedProperty(properties, PropertyConstants.QUEUE_AWSSQS_SECRET_KEY); + SetEncryptedProperty(properties, PropertyConstants.QUEUE_AWSSQS_REGION); if (string.IsNullOrEmpty(providerService.ClassName) || !providerService.ClassName.Contains(className)) { - providerService.ClassName = "GeneXus.Messaging.Queue.AWSQueue, GXAmazonSQS, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"; + providerService.ClassName = PropertyConstants.AWSSQS_QUEUE_PROVIDERTYPENAME; } break; @@ -100,11 +98,11 @@ private static void Preprocess(String name, GXProperties properties) throw new SystemException(string.Format("Provider {0} is not supported.", name)); } } - private static void SetEncryptedProperty(GXProperties properties, String prop) + private static void SetEncryptedProperty(GXProperties properties, string prop) { - String value = properties.Get(prop); + string value = properties.Get(prop); if (string.IsNullOrEmpty(value)) - value = String.Empty; + value = string.Empty; value = CryptoImpl.Encrypt(value); properties.Set(prop, value); } diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/PropertyConstants.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/PropertyConstants.cs new file mode 100644 index 000000000..32276b68c --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/PropertyConstants.cs @@ -0,0 +1,35 @@ +namespace GeneXus.Messaging.Common +{ + public static class PropertyConstants + { + //Azure Storage Queue + internal const string AZURE_QUEUE_CLASSNAME = "GeneXus.Messaging.Queue.AzureQueue"; + internal const string AZURE_QUEUE_PROVIDER_CLASSNAME = "GeneXus.Messaging.Queue.AzureQueue, GXAzureQueue, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"; + public const string AZURE_QUEUE_PROVIDERTYPENAME = "AZUREQUEUE"; + + public const string QUEUE_SERVICE_NAME = "QUEUE"; + + public const string QUEUE_AZUREQUEUE_QUEUENAME = "QUEUE_AZUREQUEUE_QUEUENAME"; + public const string QUEUE_AZUREQUEUE_CONNECTIONSTRING = "QUEUE_AZUREQUEUE_CONNECTIONSTRING"; + public const string QUEUE_AZUREQUEUE_QUEUEURI = "QUEUE_AZUREQUEUE_QUEUEURI"; + + public const string QUEUENAME = "QUEUENAME"; + public const string CONNECTIONSTRING = "CONNECTIONSTRING"; + public const string QUEUEURI = "QUEUEURI"; + public const string AUTHENTICATION_METHOD = "AUTHENTICATION_METHOD"; + + //AWS SQS + + public const string AWSSQS_QUEUE_PROVIDERTYPENAME = "GeneXus.Messaging.Queue.AWSQueue, GXAmazonSQS, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"; + public const string QUEUE_AWSSQS_QUEUE_URL = "QUEUE_AWSSQS_QUEUE_URL"; + public const string QUEUE_AWSSQS_ACCESS_KEY = "QUEUE_AWSSQS_ACCESS_KEY"; + public const string QUEUE_AWSSQS_SECRET_KEY = "QUEUE_AWSSQS_SECRET_KEY"; + public const string QUEUE_AWSSQS_REGION = "QUEUE_AWSSQS_REGION"; + + } + public enum AuthenticationMethod + { + ActiveDirectory, + Password + } +} From ca443ad1e3f79fe80d0caeb741ee4a2514af0c45 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 22 Aug 2023 10:17:19 -0300 Subject: [PATCH 029/164] Incorporate CSRF token handling into the GAM security provider. (#860) * Incorporate CSRF token handling into the GAM security provider. * Fix build error. * Remove unnecessary assignment. * Rename Config key to ValidateCSRF * Add ValidateCsrfToken routine and reuse code. * validateCSRFToken was not initialized when objIntegratedSecurityLevel = GAMSecurityLevel.SecurityHigh * validateCSRFToken was not initialized when objIntegratedSecurityLevel = GAMSecurityLevel.SecurityHigh in .NET (core) * Add Cookie-to-header AntiForgery token validation. * The ValidateCsrf configuration was always true, regardless of the value at appsettings.json or web.config. * Validate forgery token also in PUT and DELETE verbs. * Add Unit Test for CSRF Validation * Remove unsused package references. * Remove unused package. * Remove unused packages * Move VerificationToken to MapRoute. * Fix test. * SuppressXFrameOptionsHeader is false. * Disable some tests until solve concurrency issue. * Enable Antiforgery validation for rest services in .NET Framework * Remove unneeded using. * Set ReasonPhrase to code InvalidCSRFToken on failed validation. * Fix System.MethodAccessException: Attempt by security transparent method at GeneXus.Utils.GxRestService.WebException. * Revert changes for CSRFTOken validation in GAM layer. * Minor format changes. --- dotnet/DotNetStandardClasses.sln | 11 +- .../GxClasses.Web/Properties/AssemblyInfo.cs | 3 +- .../GxClasses/Properties/AssemblyInfo.cs | 1 + .../dotnetcore/GxNetCoreStartup/Startup.cs | 99 +- .../GxClasses/Core/GXApplication.cs | 10 +- .../GxClasses/Core/gxconfig.cs | 8 +- .../GxClasses/GxClasses.csproj | 1 + .../GxClasses/Helpers/GXRestUtils.cs | 8 +- .../GxClasses/Helpers/HttpHelper.cs | 1 + .../GxClasses/Services/GXRestServices.cs | 51 +- .../GxClasses/Services/GxRestWrapper.cs | 1 - .../DotNetCoreAttackMitigationTest.csproj | 68 + .../Middleware/MiddlewareTest.cs | 33 + .../Middleware/RestServiceTest.cs | 97 + .../Middleware/webhook.cs | 103 + .../apps/apdfwebbasictest.cs | 196 ++ .../apps/append.cs | 97 + .../apps/append.svc | 1 + .../apps/saveimage.cs | 39 + .../apps/saveimage.svc | 1 + .../apps/type_Sdtrappo00b.cs | 1836 +++++++++++++++++ .../appsettings.json | 65 + 22 files changed, 2713 insertions(+), 17 deletions(-) create mode 100644 dotnet/test/DotNetCoreAttackMitigationTest/DotNetCoreAttackMitigationTest.csproj create mode 100644 dotnet/test/DotNetCoreAttackMitigationTest/Middleware/MiddlewareTest.cs create mode 100644 dotnet/test/DotNetCoreAttackMitigationTest/Middleware/RestServiceTest.cs create mode 100644 dotnet/test/DotNetCoreAttackMitigationTest/Middleware/webhook.cs create mode 100644 dotnet/test/DotNetCoreAttackMitigationTest/apps/apdfwebbasictest.cs create mode 100644 dotnet/test/DotNetCoreAttackMitigationTest/apps/append.cs create mode 100644 dotnet/test/DotNetCoreAttackMitigationTest/apps/append.svc create mode 100644 dotnet/test/DotNetCoreAttackMitigationTest/apps/saveimage.cs create mode 100644 dotnet/test/DotNetCoreAttackMitigationTest/apps/saveimage.svc create mode 100644 dotnet/test/DotNetCoreAttackMitigationTest/apps/type_Sdtrappo00b.cs create mode 100644 dotnet/test/DotNetCoreAttackMitigationTest/appsettings.json diff --git a/dotnet/DotNetStandardClasses.sln b/dotnet/DotNetStandardClasses.sln index 4822f78c0..00009ab39 100644 --- a/dotnet/DotNetStandardClasses.sln +++ b/dotnet/DotNetStandardClasses.sln @@ -243,9 +243,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GxOffice", "src\dotnetcore\ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "excel", "excel", "{B521FF6D-E081-4DE6-AC00-A9BE3B6439D1}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GXEventRouter", "src\dotnetcore\Providers\Messaging\GXEventRouter\GXEventRouter.csproj", "{5BBC75F0-E51A-4EBD-A628-92498D319B1D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GXEventRouter", "src\dotnetcore\Providers\Messaging\GXEventRouter\GXEventRouter.csproj", "{5BBC75F0-E51A-4EBD-A628-92498D319B1D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GXAzureEventGrid", "src\dotnetcore\Providers\Messaging\GXAzureEventGrid\GXAzureEventGrid.csproj", "{7250CDB1-95C4-4822-B01B-3CBD73324CC9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GXAzureEventGrid", "src\dotnetcore\Providers\Messaging\GXAzureEventGrid\GXAzureEventGrid.csproj", "{7250CDB1-95C4-4822-B01B-3CBD73324CC9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetCoreAttackMitigationTest", "test\DotNetCoreAttackMitigationTest\DotNetCoreAttackMitigationTest.csproj", "{2D615969-53E2-4B77-9A9A-75C33865CF76}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -597,6 +599,10 @@ Global {7250CDB1-95C4-4822-B01B-3CBD73324CC9}.Debug|Any CPU.Build.0 = Debug|Any CPU {7250CDB1-95C4-4822-B01B-3CBD73324CC9}.Release|Any CPU.ActiveCfg = Release|Any CPU {7250CDB1-95C4-4822-B01B-3CBD73324CC9}.Release|Any CPU.Build.0 = Release|Any CPU + {2D615969-53E2-4B77-9A9A-75C33865CF76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2D615969-53E2-4B77-9A9A-75C33865CF76}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2D615969-53E2-4B77-9A9A-75C33865CF76}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2D615969-53E2-4B77-9A9A-75C33865CF76}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -715,6 +721,7 @@ Global {B521FF6D-E081-4DE6-AC00-A9BE3B6439D1} = {2261B65E-3757-4E5B-9DCD-EAE8D1E236A3} {5BBC75F0-E51A-4EBD-A628-92498D319B1D} = {4C43F2DA-59E5-46F5-B691-195449498555} {7250CDB1-95C4-4822-B01B-3CBD73324CC9} = {30159B0F-BE61-4DB7-AC02-02851426BE4B} + {2D615969-53E2-4B77-9A9A-75C33865CF76} = {1D6F1776-FF4B-46C2-9B3D-BC46CCF049DC} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E18684C9-7D76-45CD-BF24-E3944B7F174C} diff --git a/dotnet/src/dotnetcore/GxClasses.Web/Properties/AssemblyInfo.cs b/dotnet/src/dotnetcore/GxClasses.Web/Properties/AssemblyInfo.cs index 7138fabec..efaae7382 100644 --- a/dotnet/src/dotnetcore/GxClasses.Web/Properties/AssemblyInfo.cs +++ b/dotnet/src/dotnetcore/GxClasses.Web/Properties/AssemblyInfo.cs @@ -5,4 +5,5 @@ [assembly: InternalsVisibleTo("DotNetCoreWebUnitTest")] [assembly: InternalsVisibleTo("GxNetCoreStartup")] [assembly: InternalsVisibleTo("GeneXus.Deploy.AzureFunctions.Handlers")] -[assembly: InternalsVisibleTo("AzureFunctionsTest")] \ No newline at end of file +[assembly: InternalsVisibleTo("AzureFunctionsTest")] +[assembly: InternalsVisibleTo("DotNetCoreAttackMitigationTest")] diff --git a/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs b/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs index 80e2eff77..cb985cdac 100644 --- a/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs +++ b/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs @@ -10,6 +10,7 @@ [assembly: InternalsVisibleTo("GXEventRouter")] [assembly: InternalsVisibleTo("DotNetCoreUnitTest")] [assembly: InternalsVisibleTo("DotNetCoreWebUnitTest")] +[assembly: InternalsVisibleTo("DotNetCoreAttackMitigationTest")] [assembly: InternalsVisibleTo("GeneXus.Deploy.AzureFunctions.Handlers")] [assembly: InternalsVisibleTo("AzureFunctionsTest")] [assembly: InternalsVisibleTo("GXMessageBroker")] diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs index a5d8ceed3..3495ef6c2 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs @@ -1,3 +1,5 @@ + + using System; using System.Collections.Generic; using System.IO; @@ -12,6 +14,7 @@ using GxClasses.Web.Middleware; using log4net; using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Antiforgery; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Diagnostics; @@ -104,6 +107,10 @@ private static void LocatePhysicalLocalPath() public static class GXHandlerExtensions { + public static IApplicationBuilder UseAntiforgeryTokens(this IApplicationBuilder app, string basePath) + { + return app.UseMiddleware(basePath); + } public static IApplicationBuilder UseGXHandlerFactory(this IApplicationBuilder builder, string basePath) { return builder.UseMiddleware(basePath); @@ -199,7 +206,14 @@ public void ConfigureServices(IServiceCollection services) } }); - + if (RestAPIHelpers.ValidateCsrfToken()) + { + services.AddAntiforgery(options => + { + options.HeaderName = HttpHeader.X_GXCSRF_TOKEN; + options.SuppressXFrameOptionsHeader = false; + }); + } services.AddDirectoryBrowser(); if (GXUtil.CompressResponse()) { @@ -386,6 +400,12 @@ public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHos string restBasePath = string.IsNullOrEmpty(VirtualPath) ? REST_BASE_URL : $"{VirtualPath}/{REST_BASE_URL}"; string apiBasePath = string.IsNullOrEmpty(VirtualPath) ? string.Empty : $"{VirtualPath}/"; + IAntiforgery antiforgery = null; + if (RestAPIHelpers.ValidateCsrfToken()) + { + antiforgery = app.ApplicationServices.GetRequiredService(); + app.UseAntiforgeryTokens(restBasePath); + } app.UseMvc(routes => { foreach (string serviceBasePath in servicesBase) @@ -397,6 +417,16 @@ public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHos routes.MapRoute($"{s}", new RequestDelegate(gxRouting.ProcessRestRequest)); } } + routes.MapRoute($"{restBasePath}VerificationToken", (context) => + { + string requestPath = context.Request.Path.Value; + + if (string.Equals(requestPath, $"/{restBasePath}VerificationToken", StringComparison.OrdinalIgnoreCase) && antiforgery!=null) + { + ValidateAntiForgeryTokenMiddleware.SetAntiForgeryTokens(antiforgery, context); + } + return Task.CompletedTask; + }); routes.MapRoute($"{restBasePath}{{*{UrlTemplateControllerWithParms}}}", new RequestDelegate(gxRouting.ProcessRestRequest)); routes.MapRoute("Default", VirtualPath, new { controller = "Home", action = "Index" }); }); @@ -474,9 +504,11 @@ bool IsAspx(HttpContext context, string basePath) } public class CustomExceptionHandlerMiddleware { + const string InvalidCSRFToken = "InvalidCSRFToken"; static readonly ILog log = log4net.LogManager.GetLogger(typeof(CustomExceptionHandlerMiddleware)); public async Task Invoke(HttpContext httpContext) { + string httpReasonPhrase=string.Empty; Exception ex = httpContext.Features.Get()?.Error; HttpStatusCode httpStatusCode = (HttpStatusCode)httpContext.Response.StatusCode; if (ex!=null) @@ -485,6 +517,13 @@ public async Task Invoke(HttpContext httpContext) { httpStatusCode = HttpStatusCode.NotFound; } + else if (ex is AntiforgeryValidationException) + { + //"The required antiforgery header value "X-GXCSRF-TOKEN" is not present. + httpStatusCode = HttpStatusCode.BadRequest; + httpReasonPhrase = InvalidCSRFToken; + GXLogging.Error(log, $"Validation of antiforgery failed", ex); + } else { httpStatusCode = HttpStatusCode.InternalServerError; @@ -495,13 +534,19 @@ public async Task Invoke(HttpContext httpContext) { string redirectPage = Config.MapCustomError(httpStatusCode.ToString(HttpHelper.INT_FORMAT)); if (!string.IsNullOrEmpty(redirectPage)) -{ + { httpContext.Response.Redirect($"{httpContext.Request.GetApplicationPath()}/{redirectPage}"); } else { httpContext.Response.StatusCode = (int)httpStatusCode; } + if (!string.IsNullOrEmpty(httpReasonPhrase)) + { + IHttpResponseFeature responseReason = httpContext.Response.HttpContext.Features.Get(); + if (responseReason!=null) + responseReason.ReasonPhrase = httpReasonPhrase; + } } await Task.CompletedTask; } @@ -542,4 +587,54 @@ public IActionResult Index() return Redirect(defaultFiles[0]); } } + public class ValidateAntiForgeryTokenMiddleware + { + static readonly ILog log = log4net.LogManager.GetLogger(typeof(ValidateAntiForgeryTokenMiddleware)); + + private readonly RequestDelegate _next; + private readonly IAntiforgery _antiforgery; + private string _basePath; + + public ValidateAntiForgeryTokenMiddleware(RequestDelegate next, IAntiforgery antiforgery, String basePath) + { + _next = next; + _antiforgery = antiforgery; + _basePath = "/" + basePath; + } + + public async Task Invoke(HttpContext context) + { + if (context.Request.Path.HasValue && context.Request.Path.Value.StartsWith(_basePath)) + { + if (HttpMethods.IsPost(context.Request.Method) || + HttpMethods.IsDelete(context.Request.Method) || + HttpMethods.IsPut(context.Request.Method)) + { + string cookieToken = context.Request.Cookies[HttpHeader.X_GXCSRF_TOKEN]; + string headerToken = context.Request.Headers[HttpHeader.X_GXCSRF_TOKEN]; + GXLogging.Debug(log, $"Antiforgery validation, cookieToken:{cookieToken}, headerToken:{headerToken}"); + + await _antiforgery.ValidateRequestAsync(context); + GXLogging.Debug(log, $"Antiforgery validation OK"); + } + else if (HttpMethods.IsGet(context.Request.Method)) + { + string tokens = context.Request.Cookies[HttpHeader.X_GXCSRF_TOKEN]; + if (string.IsNullOrEmpty(tokens)) + { + SetAntiForgeryTokens(_antiforgery, context); + } + } + } + await _next(context); + } + internal static void SetAntiForgeryTokens(IAntiforgery _antiforgery, HttpContext context) + { + AntiforgeryTokenSet tokenSet = _antiforgery.GetAndStoreTokens(context); + context.Response.Cookies.Append(HttpHeader.X_GXCSRF_TOKEN, tokenSet.RequestToken, + new CookieOptions { HttpOnly = false, Secure = GxContext.GetHttpSecure(context) == 1 }); + GXLogging.Debug(log, $"Setting cookie ", HttpHeader.X_GXCSRF_TOKEN, "=", tokenSet.RequestToken); + } + + } } diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs index 33a74fc1f..c835ae5d9 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs @@ -2133,18 +2133,22 @@ public string GetBrowserVersion() } } public virtual short GetHttpSecure() + { + return GetHttpSecure(_HttpContext); + } + static internal short GetHttpSecure(HttpContext httpContext) { try { - if (HttpContext == null) + if (httpContext == null) return 0; - if (_HttpContext.Request.GetIsSecureFrontEnd()) + if (httpContext.Request.GetIsSecureFrontEnd()) { GXLogging.Debug(log, "Front-End-Https header activated"); return 1; } else - return _HttpContext.Request.GetIsSecureConnection(); + return httpContext.Request.GetIsSecureConnection(); } catch { diff --git a/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs b/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs index e387eaefa..7254ff5e8 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs @@ -794,8 +794,8 @@ public class Preferences public static string DefaultRewriteFile = "rewrite.config"; const string USE_NAMED_PARAMETERS = "UseNamedParameters"; const string REST_DATES_WITH_MILLIS = "REST_DATES_WITH_MILLIS"; - const string YES = "1"; - const string NO = "0"; + internal const string YES = "1"; + internal const string NO = "0"; static string defaultDatastore; const string DEFAULT_DS = "Default"; static int httpclient_max_per_route = -1; @@ -867,9 +867,9 @@ public static bool RewriteEnabled if (rewriteEnabled == -1) { #if NETCORE - var basePath = FileUtil.GetBasePath(); + string basePath = FileUtil.GetBasePath(); #else - var basePath = Directory.GetParent(FileUtil.GetStartupDirectory()).FullName; + string basePath = Directory.GetParent(FileUtil.GetStartupDirectory()).FullName; #endif string rewriteFile = Path.Combine(basePath, DefaultRewriteFile); rewriteEnabled = File.Exists(rewriteFile)?1:0; diff --git a/dotnet/src/dotnetframework/GxClasses/GxClasses.csproj b/dotnet/src/dotnetframework/GxClasses/GxClasses.csproj index 622226cdd..1e437fe5a 100644 --- a/dotnet/src/dotnetframework/GxClasses/GxClasses.csproj +++ b/dotnet/src/dotnetframework/GxClasses/GxClasses.csproj @@ -12,6 +12,7 @@ + diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestUtils.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestUtils.cs index d5ec2a42d..da14c4012 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestUtils.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestUtils.cs @@ -11,8 +11,7 @@ using log4net; using System.IO; using Jayrock.Json; - - +using GeneXus.Configuration; namespace GeneXus.Utils { @@ -140,5 +139,10 @@ public static Dictionary ReadRestBodyParameters(Stream stream) } return bodyParameters; } + + internal static bool ValidateCsrfToken() + { + return Config.GetValueOf("ValidateCSRF", Preferences.NO) == Preferences.YES; + } } } diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs index 8cebcb0b6..4fd91c649 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs @@ -50,6 +50,7 @@ public class HttpHeader public static string XGXFILENAME = "x-gx-filename"; internal static string ACCEPT = "Accept"; internal static string TRANSFER_ENCODING = "Transfer-Encoding"; + internal static string X_GXCSRF_TOKEN = "X-GXCSRF-TOKEN"; } internal class HttpHeaderValue { diff --git a/dotnet/src/dotnetframework/GxClasses/Services/GXRestServices.cs b/dotnet/src/dotnetframework/GxClasses/Services/GXRestServices.cs index 19c37601f..e13ebb200 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/GXRestServices.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/GXRestServices.cs @@ -7,6 +7,7 @@ using System.Net.Http; using System.Runtime.Serialization; using System.Runtime.Serialization.Json; +using System.Security; using System.ServiceModel; using System.ServiceModel.Channels; using System.ServiceModel.Configuration; @@ -15,6 +16,8 @@ using System.ServiceModel.Web; using System.Text; using System.Web; +using System.Web.Helpers; +using System.Web.Mvc; using GeneXus.Application; using GeneXus.Configuration; using GeneXus.Data; @@ -22,6 +25,7 @@ using GeneXus.Metadata; using GeneXus.Security; using log4net; +using Microsoft.IdentityModel.Tokens; using Microsoft.Net.Http.Headers; namespace GeneXus.Utils @@ -388,7 +392,7 @@ public void WebException(Exception ex) { throw ex; } - else if (ex is FormatException) + else if (ex is FormatException || (RestAPIHelpers.ValidateCsrfToken() && AntiForgeryException(ex))) { HttpHelper.SetUnexpectedError(httpContext, HttpStatusCode.BadRequest, ex); } @@ -397,6 +401,12 @@ public void WebException(Exception ex) HttpHelper.SetUnexpectedError(httpContext, HttpStatusCode.InternalServerError, ex); } } + [SecuritySafeCritical] + private bool AntiForgeryException(Exception ex) + { + return ex is HttpAntiForgeryException; + } + public bool IsAuthenticated(string synchronizer) { GXLogging.Debug(log, "IsMainAuthenticated synchronizer:" + synchronizer); @@ -449,7 +459,6 @@ private bool IsAuthenticated(GAMSecurityLevel objIntegratedSecurityLevel, bool o } else { - token = token.Replace("OAuth ", ""); if (objIntegratedSecurityLevel == GAMSecurityLevel.SecurityLow) { @@ -546,8 +555,13 @@ void AddHeader(string header, string value) httpContext.Response.Headers[header]= value; } } + [SecuritySafeCritical] public bool ProcessHeaders(string queryId) { + if (RestAPIHelpers.ValidateCsrfToken()) + { + ValidateAntiforgery(); + } NameValueCollection headers = GetHeaders(); String language = null, theme = null, etag = null; @@ -587,6 +601,39 @@ public bool ProcessHeaders(string queryId) return true; } + [SecurityCritical] + private void ValidateAntiforgery() + { + string cookieToken, formToken; + string httpMethod = context.HttpContext.Request.HttpMethod; + string tokens = context.HttpContext.Request.Cookies[HttpHeader.X_GXCSRF_TOKEN]?.Value; + string internalCookieToken = context.HttpContext.Request.Cookies[HttpHeader.X_GXCSRF_TOKEN]?.Value; + if (httpMethod == HttpMethod.Get.Method && (string.IsNullOrEmpty(tokens) || string.IsNullOrEmpty(internalCookieToken))) + { + AntiForgery.GetTokens(null, out cookieToken, out formToken); +#pragma warning disable SCS0009 // The cookie is missing security flag HttpOnly + HttpCookie cookie = new HttpCookie(HttpHeader.X_GXCSRF_TOKEN, formToken) + { + HttpOnly = false, + Secure = context.GetHttpSecure() == 1, + }; +#pragma warning restore SCS0009 // The cookie is missing security flag HttpOnly + HttpCookie internalCookie = new HttpCookie(AntiForgeryConfig.CookieName, cookieToken) + { + HttpOnly = true, + Secure = context.GetHttpSecure() == 1, + }; + context.HttpContext.Response.SetCookie(cookie); + context.HttpContext.Response.SetCookie(internalCookie); + } + if (httpMethod == HttpMethod.Delete.Method || httpMethod == HttpMethod.Post.Method || httpMethod == HttpMethod.Put.Method) + { + cookieToken = context.HttpContext.Request.Cookies[AntiForgeryConfig.CookieName]?.Value; + string headerToken = context.HttpContext.Request.Headers[HttpHeader.X_GXCSRF_TOKEN]; + AntiForgery.Validate(cookieToken, headerToken); + } + } + private void SendCacheHeaders() { if (string.IsNullOrEmpty(context.GetHeader(HttpHeader.CACHE_CONTROL))) diff --git a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs index 71adbd030..c0b1c6a74 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs @@ -567,7 +567,6 @@ protected bool IsAuthenticated(GAMSecurityLevel objIntegratedSecurityLevel, bool } else { - token = token.Replace("OAuth ", ""); if (objIntegratedSecurityLevel == GAMSecurityLevel.SecurityLow) { diff --git a/dotnet/test/DotNetCoreAttackMitigationTest/DotNetCoreAttackMitigationTest.csproj b/dotnet/test/DotNetCoreAttackMitigationTest/DotNetCoreAttackMitigationTest.csproj new file mode 100644 index 000000000..659f45156 --- /dev/null +++ b/dotnet/test/DotNetCoreAttackMitigationTest/DotNetCoreAttackMitigationTest.csproj @@ -0,0 +1,68 @@ + + + net6.0 + CS8032;1701;1702;NU1701 + Major + + + TRACE;NETCORE + + + DEBUG;TRACE;NETCORE + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + Always + + + PreserveNewest + + + + + + diff --git a/dotnet/test/DotNetCoreAttackMitigationTest/Middleware/MiddlewareTest.cs b/dotnet/test/DotNetCoreAttackMitigationTest/Middleware/MiddlewareTest.cs new file mode 100644 index 000000000..3142f2ac3 --- /dev/null +++ b/dotnet/test/DotNetCoreAttackMitigationTest/Middleware/MiddlewareTest.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using GeneXus.Application; +using GxClasses.Web.Middleware; +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.TestHost; + +namespace xUnitTesting +{ + public class MiddlewareTest + { + protected TestServer server; + public MiddlewareTest() + { + GXRouting.ContentRootPath = Directory.GetCurrentDirectory(); + server = new TestServer(WebHost.CreateDefaultBuilder().UseStartup()); + server.PreserveExecutionContext= true; + server.CreateClient(); + } + protected string GetHeader(HttpResponseMessage response, string headerName) + { + if (response.Headers.TryGetValues(headerName, out IEnumerable value)) + return value.First(); + else + return string.Empty; + + } + + } +} diff --git a/dotnet/test/DotNetCoreAttackMitigationTest/Middleware/RestServiceTest.cs b/dotnet/test/DotNetCoreAttackMitigationTest/Middleware/RestServiceTest.cs new file mode 100644 index 000000000..7c74cb07e --- /dev/null +++ b/dotnet/test/DotNetCoreAttackMitigationTest/Middleware/RestServiceTest.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Reflection; +using System.Threading.Tasks; +using GeneXus.Http; +using GeneXus.Metadata; +using Microsoft.Net.Http.Headers; +using Xunit; + +namespace xUnitTesting +{ + + public class RestServiceTest : MiddlewareTest + { + public RestServiceTest() : base() + { + ClassLoader.FindType("apps.append", "GeneXus.Programs.apps", "append", Assembly.GetExecutingAssembly(), true);//Force loading assembly for append procedure + ClassLoader.FindType("apps.saveimage", "GeneXus.Programs.apps", "saveimage", Assembly.GetExecutingAssembly(), true);//Force loading assembly for saveimage procedure + server.AllowSynchronousIO = true; + ClassLoader.FindType("webhook", "GeneXus.Programs", "webhook", Assembly.GetExecutingAssembly(), true);//Force loading assembly for webhook procedure + server.AllowSynchronousIO = true; + + } + + [Fact] + public async Task TestSimpleRestPost() + { + server.AllowSynchronousIO = true; + HttpClient client = server.CreateClient(); + StringContent body = new StringContent("{\"Image\":\"imageName\",\"ImageDescription\":\"imageDescription\"}"); + HttpResponseMessage response = await client.PostAsync("rest/apps/saveimage", body); + Assert.Equal(System.Net.HttpStatusCode.BadRequest, response.StatusCode); + } + + [Fact] + public async Task RunController() + { + + + CookieContainer cookies = new System.Net.CookieContainer(); + HttpClient client = server.CreateClient(); + string requestUri = "rest/apps/append"; + Uri requestUriObj = new Uri("http://localhost/" + requestUri); + HttpResponseMessage response = await client.GetAsync(requestUri); + string csrfToken = string.Empty; + + IEnumerable values; + Assert.True(response.Headers.TryGetValues("Set-Cookie", out values)); + + foreach (var item in SetCookieHeaderValue.ParseList(values.ToList())) + cookies.Add(requestUriObj, new Cookie(item.Name.Value, item.Value.Value, item.Path.Value)); + + var setCookie = SetCookieHeaderValue.ParseList(values.ToList()).FirstOrDefault(t => t.Name.Equals(HttpHeader.X_GXCSRF_TOKEN, StringComparison.OrdinalIgnoreCase)); + csrfToken = setCookie.Value.Value; + + response.EnsureSuccessStatusCode(); + Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); //When failed, turn on log.config to see server side error. + + StringContent body = new StringContent("{\"Image\":\"imageName\",\"ImageDescription\":\"imageDescription\"}"); + client.DefaultRequestHeaders.Add(HttpHeader.X_GXCSRF_TOKEN, csrfToken); + client.DefaultRequestHeaders.Add("Cookie", values);// //cookies.GetCookieHeader(requestUriObj)); + + response = await client.PostAsync("rest/apps/saveimage", body); + Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); + } + [Fact] + public async Task HttpFirstPost() + { + HttpClient client = server.CreateClient(); + HttpResponseMessage response = await client.PostAsync("webhook.aspx", null); + IEnumerable cookies = response.Headers.SingleOrDefault(header => header.Key == "Set-Cookie").Value; + foreach (string cookie in cookies) + { + Assert.False(cookie.StartsWith(HttpHeader.X_GXCSRF_TOKEN)); + } + response.EnsureSuccessStatusCode(); + Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); + } + [Fact] + public async Task HttpFirstGet() + { + HttpClient client = server.CreateClient(); + HttpResponseMessage response = await client.GetAsync("webhook.aspx"); + IEnumerable cookies = response.Headers.SingleOrDefault(header => header.Key == "Set-Cookie").Value; + foreach (string cookie in cookies) + { + Assert.False(cookie.StartsWith(HttpHeader.X_GXCSRF_TOKEN)); + } + + response.EnsureSuccessStatusCode(); + Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); + } + } +} diff --git a/dotnet/test/DotNetCoreAttackMitigationTest/Middleware/webhook.cs b/dotnet/test/DotNetCoreAttackMitigationTest/Middleware/webhook.cs new file mode 100644 index 000000000..7dfef187b --- /dev/null +++ b/dotnet/test/DotNetCoreAttackMitigationTest/Middleware/webhook.cs @@ -0,0 +1,103 @@ +using System; +using GeneXus.Application; +using GeneXus.Data.NTier; +using GeneXus.Http.Server; +using GeneXus.Procedure; +using GeneXus.Utils; +namespace GeneXus.Programs +{ + public class webhook : GXWebProcedure + { + public override void webExecute() + { + context.SetDefaultTheme("Carmine"); + initialize(); + executePrivate(); + cleanup(); + } + + public webhook() + { + context = new GxContext(); + DataStoreUtil.LoadDataStores(context); + IsMain = true; + context.SetDefaultTheme("Carmine"); + } + + public webhook(IGxContext context) + { + this.context = context; + IsMain = false; + } + + public void execute() + { + initialize(); + executePrivate(); + } + + public void executeSubmit() + { + webhook objwebhook; + objwebhook = new webhook(); + objwebhook.context.SetSubmitInitialConfig(context); + objwebhook.initialize(); + Submit(executePrivateCatch, objwebhook); + } + + void executePrivateCatch(object stateInfo) + { + try + { + ((webhook)stateInfo).executePrivate(); + } + catch (Exception e) + { + GXUtil.SaveToEventLog("Design", e); + throw; + } + } + + void executePrivate() + { + /* GeneXus formulas */ + /* Output device settings */ + AV9body = AV8httprequest.ToString(); + AV10httpresponse.AddString(AV9body); + if (context.WillRedirect()) + { + context.Redirect(context.wjLoc); + context.wjLoc = ""; + } + this.cleanup(); + } + + public override void cleanup() + { + CloseOpenCursors(); + base.cleanup(); + if (IsMain) + { + context.CloseConnections(); + } + ExitApp(); + } + + protected void CloseOpenCursors() + { + } + + public override void initialize() + { + AV8httprequest = new GxHttpRequest(context); + AV10httpresponse = new GxHttpResponse(context); + /* GeneXus formulas. */ + context.Gx_err = 0; + } + + private string AV9body; + private GxHttpRequest AV8httprequest; + private GxHttpResponse AV10httpresponse; + } + +} diff --git a/dotnet/test/DotNetCoreAttackMitigationTest/apps/apdfwebbasictest.cs b/dotnet/test/DotNetCoreAttackMitigationTest/apps/apdfwebbasictest.cs new file mode 100644 index 000000000..6924bf049 --- /dev/null +++ b/dotnet/test/DotNetCoreAttackMitigationTest/apps/apdfwebbasictest.cs @@ -0,0 +1,196 @@ +/* + File: PDFBasicTest + Description: PDFBasic Test + Author: GeneXus .NET Framework Generator version 17_0_8-156507 + Generated on: 12/21/2021 16:34:13.62 + Program type: Main program + Main DBMS: SQL Server +*/ +using GeneXus.Application; +using GeneXus.Data.NTier; +using GeneXus.Http.Server; +using GeneXus.Procedure; +using GeneXus.Utils; + +namespace GeneXus.Programs +{ + public class apdfwebbasictest : GXWebProcedure + { + + public apdfwebbasictest( ) + { + context = new GxContext( ); + DataStoreUtil.LoadDataStores( context); + IsMain = true; + context.SetDefaultTheme("Carmine"); + } + + public apdfwebbasictest( IGxContext context ) + { + this.context = context; + IsMain = false; + } + public override void webExecute() + { + context.SetDefaultTheme("PDFReportTest", true); + GxContext gxcontext = context as GxContext; + gxcontext.SetPhysicalPath(System.IO.Directory.GetCurrentDirectory()); + initialize(); + executePrivate(); + cleanup(); + } + + public void execute() + { + initialize(); + executePrivate(); + } + void executePrivate() + { + /* GeneXus formulas */ + /* Output device settings */ + M_top = 0; + M_bot = 6; + P_lines = (int)(66-M_bot); + getPrinter().GxClearAttris() ; + AddMetrics( ) ; + lineHeight = 15; + gxXPage = 100; + gxYPage = 100; + GxHttpResponse httpResponse = new GxHttpResponse(context); + httpResponse.AppendHeader("Content-Disposition", "inline; filename=Report.pdf"); + getPrinter().GxSetDocFormat("PDF") ; + try + { + Gx_out = "FIL" ; + if (!initPrinter (Gx_out, gxXPage, gxYPage, "GXPRN.INI", "", "", 2, 1, 256, 16834, 9504, 0, 1, 1, 0, 1, 1) ) + { + cleanup(); + return; + } + getPrinter().setModal(false) ; + P_lines = (int)(gxYPage-(lineHeight*6)); + Gx_line = (int)(P_lines+1); + getPrinter().setPageLines(P_lines); + getPrinter().setLineHeight(lineHeight); + getPrinter().setM_top(M_top); + getPrinter().setM_bot(M_bot); + AV8htmlvar = "

This is an example of a simple HTML page with one paragraph.

"; + H1N0( false, 193) ; + getPrinter().GxAttris("Microsoft Sans Serif", 14, false, false, false, false, 0, 0, 0, 0, 0, 255, 255, 255) ; + getPrinter().GxDrawText("Item List", 17, Gx_line+33, 400, Gx_line+66, 0, 0, 0, 0) ; + getPrinter().GxDrawRect(33, Gx_line+33, 133, Gx_line+63, 1, 0, 0, 0, 0, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0) ; + getPrinter().GxAttris("Microsoft Sans Serif", 10, true, false, false, false, 0, 0, 0, 0, 0, 255, 255, 255) ; + getPrinter().GxDrawText("Code", 100, Gx_line+83, 140, Gx_line+101, 0+256, 0, 0, 0) ; + getPrinter().GxDrawText("Name", 183, Gx_line+83, 283, Gx_line+101, 0, 0, 0, 0) ; + getPrinter().GxDrawBitMap("lamp.png", 411, Gx_line+33, 619, Gx_line+241) ; + getPrinter().GxAttris("Microsoft Sans Serif", 8, false, false, false, false, 0, 0, 0, 0, 0, 255, 255, 255) ; + getPrinter().GxDrawText(StringUtil.RTrim( AV8htmlvar), 22, Gx_line+122, 400, Gx_line+178, 0, 1, 0, 0) ; + Gx_OldLine = Gx_line; + Gx_line = (int)(Gx_line+193); + /* Print footer for last page */ + ToSkip = (int)(P_lines+1); + H1N0( true, 0) ; + } + catch ( GeneXus.Printer.ProcessInterruptedException ) + { + } + finally + { + /* Close printer file */ + try + { + getPrinter().GxEndPage() ; + getPrinter().GxEndDocument() ; + } + catch ( GeneXus.Printer.ProcessInterruptedException ) + { + } + endPrinter(); + } + this.cleanup(); + } + + protected void H1N0( bool bFoot , + int Inc ) + { + /* Skip the required number of lines */ + while ( ( ToSkip > 0 ) || ( Gx_line + Inc > P_lines ) ) + { + if ( Gx_line + Inc >= P_lines ) + { + if ( Gx_page > 0 ) + { + /* Print footers */ + Gx_line = P_lines; + getPrinter().GxEndPage() ; + if ( bFoot ) + { + return ; + } + } + ToSkip = 0; + Gx_line = 0; + Gx_page = (int)(Gx_page+1); + /* Skip Margin Top Lines */ + Gx_line = (int)(Gx_line+(M_top*lineHeight)); + /* Print headers */ + getPrinter().GxStartPage() ; + if (true) break; + } + else + { + Gx_line = (int)(Gx_line+1); + } + ToSkip = (int)(ToSkip-1); + } + getPrinter().setPage(Gx_page); + } + + protected void AddMetrics( ) + { + AddMetrics0( ) ; + AddMetrics1( ) ; + } + + protected void AddMetrics0( ) + { + getPrinter().setMetrics("Microsoft Sans Serif", false, false, 58, 14, 72, 171, new int[] {48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 18, 20, 23, 36, 36, 57, 43, 12, 21, 21, 25, 37, 18, 21, 18, 18, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 18, 18, 37, 37, 37, 36, 65, 43, 43, 46, 46, 43, 39, 50, 46, 18, 32, 43, 36, 53, 46, 50, 43, 50, 46, 43, 40, 46, 43, 64, 41, 42, 39, 18, 18, 18, 27, 36, 21, 36, 36, 32, 36, 36, 18, 36, 36, 14, 15, 33, 14, 55, 36, 36, 36, 36, 21, 32, 18, 36, 33, 47, 31, 31, 31, 21, 17, 21, 37, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 18, 20, 36, 36, 36, 36, 17, 36, 21, 47, 24, 36, 37, 21, 47, 35, 26, 35, 21, 21, 21, 37, 34, 21, 21, 21, 23, 36, 53, 53, 53, 39, 43, 43, 43, 43, 43, 43, 64, 46, 43, 43, 43, 43, 18, 18, 18, 18, 46, 46, 50, 50, 50, 50, 50, 37, 50, 46, 46, 46, 46, 43, 43, 39, 36, 36, 36, 36, 36, 36, 57, 32, 36, 36, 36, 36, 18, 18, 18, 18, 36, 36, 36, 36, 36, 36, 36, 35, 39, 36, 36, 36, 36, 32, 36, 32}) ; + } + + protected void AddMetrics1( ) + { + getPrinter().setMetrics("Microsoft Sans Serif", true, false, 57, 15, 72, 163, new int[] {47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 17, 19, 29, 34, 34, 55, 45, 15, 21, 21, 24, 36, 17, 21, 17, 17, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, 21, 36, 36, 36, 38, 60, 43, 45, 45, 45, 41, 38, 48, 45, 17, 34, 45, 38, 53, 45, 48, 41, 48, 45, 41, 38, 45, 41, 57, 41, 41, 38, 21, 17, 21, 36, 34, 21, 34, 38, 34, 38, 34, 21, 38, 38, 17, 17, 34, 17, 55, 38, 38, 38, 38, 24, 34, 21, 38, 33, 49, 34, 34, 31, 24, 17, 24, 36, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 17, 21, 34, 34, 34, 34, 17, 34, 21, 46, 23, 34, 36, 21, 46, 34, 25, 34, 21, 21, 21, 36, 34, 21, 20, 21, 23, 34, 52, 52, 52, 38, 45, 45, 45, 45, 45, 45, 62, 45, 41, 41, 41, 41, 17, 17, 17, 17, 45, 45, 48, 48, 48, 48, 48, 36, 48, 45, 45, 45, 45, 41, 41, 38, 34, 34, 34, 34, 34, 34, 55, 34, 34, 34, 34, 34, 17, 17, 17, 17, 38, 38, 38, 38, 38, 38, 38, 34, 38, 38, 38, 38, 38, 34, 38, 34}) ; + } + + public override int getOutputType( ) + { + return GxReportUtils.OUTPUT_PDF ; + } + + public override void cleanup( ) + { + if (IsMain) waitPrinterEnd(); + if ( IsMain ) + { + context.CloseConnections(); + } + ExitApp(); + } + + public override void initialize( ) + { + AV8htmlvar = ""; + /* GeneXus formulas. */ + Gx_line = 0; + context.Gx_err = 0; + } + + private int M_top ; + private int M_bot ; + private int ToSkip ; + private int Gx_OldLine ; + private string AV8htmlvar ; + } + +} diff --git a/dotnet/test/DotNetCoreAttackMitigationTest/apps/append.cs b/dotnet/test/DotNetCoreAttackMitigationTest/apps/append.cs new file mode 100644 index 000000000..b8b85712e --- /dev/null +++ b/dotnet/test/DotNetCoreAttackMitigationTest/apps/append.cs @@ -0,0 +1,97 @@ +using GeneXus.Utils; +using GeneXus.Application; +using GeneXus.Data.NTier; +using GeneXus.Procedure; +using System; +using GX; + +namespace GeneXus.Programs.apps +{ + public class append : GXWebProcedure + { + + public append() + { + context = new GxContext(); + DataStoreUtil.LoadDataStores(context); + IsMain = true; + context.SetDefaultTheme("Carmine"); + } + + public append(IGxContext context) + { + this.context = context; + IsMain = false; + } + + public void execute(short aP0_numeric1, + string aP1_Character, + decimal aP2_numeric2, + out string aP3_character2, + [GxJsonFormat("yyyy-MM-dd'T'HH:mm:ss")] out DateTime aP0_datetime, + out Sdtrappo00b aP2_rappo00B + ) + { + this.AV8datetime = DateTime.MinValue; + this.AV18numeric1 = aP0_numeric1; + this.AV17Character = aP1_Character; + this.AV19numeric2 = aP2_numeric2; + this.AV20character2 = ""; + this.AV8rappo00B = new Sdtrappo00b(context); + initialize(); + executePrivate(); + aP3_character2=this.AV20character2; + aP0_datetime=this.AV8datetime; + aP2_rappo00B=this.AV8rappo00B; + } + + void executePrivate() + { + /* GeneXus formulas */ + /* Output device settings */ + AV20character2 = StringUtil.Str((decimal)(AV18numeric1), 10, 0) + AV17Character + StringUtil.Str(AV19numeric2, 10, 0) + ClientInformation.Id.ToString(); + AV8datetime = DateTimeUtil.ResetTime(context.localUtil.YMDToD(2022, 5, 24)); + AV8rappo00B.gxTpr_Rapdaa = DateTimeUtil.ResetTime(context.localUtil.YMDToD(2022, 5, 24)); + AV8rappo00B.gxTpr_Raporafin = context.localUtil.YMDHMSToT(2022, 5, 24, 10, 32, 15); + AV8rappo00B.gxTpr_Raporaini = context.localUtil.YMDHMSToT(2022, 5, 24, 10, 30, 15); + AV8rappo00B.gxTpr_Raporafinall = context.localUtil.YMDHMSToT(2022, 5, 24, 10, 40, 15); + AV8rappo00B.gxTpr_Raporainiall = context.localUtil.YMDHMSToT(2022, 5, 24, 0, 40, 15); + if (context.WillRedirect()) + { + context.Redirect(context.wjLoc); + context.wjLoc = ""; + } + this.cleanup(); + } + + public override void cleanup() + { + CloseOpenCursors(); + base.cleanup(); + if (IsMain) + { + context.CloseConnections(); + } + ExitApp(); + } + + protected void CloseOpenCursors() + { + } + + public override void initialize() + { + AV8rappo00B = new Sdtrappo00b(context); + AV8datetime = (DateTime.MinValue); + /* GeneXus formulas. */ + context.Gx_err = 0; + } + private short AV18numeric1; + private decimal AV19numeric2; + private string AV17Character; + private string AV20character2; + private DateTime AV8datetime; + private Sdtrappo00b AV8rappo00B; + } + +} diff --git a/dotnet/test/DotNetCoreAttackMitigationTest/apps/append.svc b/dotnet/test/DotNetCoreAttackMitigationTest/apps/append.svc new file mode 100644 index 000000000..749502466 --- /dev/null +++ b/dotnet/test/DotNetCoreAttackMitigationTest/apps/append.svc @@ -0,0 +1 @@ +<%@ServiceHost Service= "GeneXus.Programs.apps.append,apps.append" %> diff --git a/dotnet/test/DotNetCoreAttackMitigationTest/apps/saveimage.cs b/dotnet/test/DotNetCoreAttackMitigationTest/apps/saveimage.cs new file mode 100644 index 000000000..e8c415716 --- /dev/null +++ b/dotnet/test/DotNetCoreAttackMitigationTest/apps/saveimage.cs @@ -0,0 +1,39 @@ +using GeneXus.Application; +using GeneXus.Data.NTier; + +using GeneXus.Procedure; +namespace GeneXus.Programs.apps +{ + public class saveimage : GXProcedure + { + public saveimage() + { + context = new GxContext(); + DataStoreUtil.LoadDataStores(context); + IsMain = true; + } + + public saveimage(IGxContext context) + { + this.context = context; + IsMain = false; + } + + public void execute(string aP0_ImageDescription, string aP1_Image) + { + System.Console.WriteLine("SaveImage executed:" + aP0_ImageDescription); + } + + public override bool UploadEnabled() + { + return true; + } + + + public override void initialize() + { + + } + } + +} diff --git a/dotnet/test/DotNetCoreAttackMitigationTest/apps/saveimage.svc b/dotnet/test/DotNetCoreAttackMitigationTest/apps/saveimage.svc new file mode 100644 index 000000000..34eaa0918 --- /dev/null +++ b/dotnet/test/DotNetCoreAttackMitigationTest/apps/saveimage.svc @@ -0,0 +1 @@ +<%@ServiceHost Service= "GeneXus.Programs.apps.saveimage, apps.saveimage" %> diff --git a/dotnet/test/DotNetCoreAttackMitigationTest/apps/type_Sdtrappo00b.cs b/dotnet/test/DotNetCoreAttackMitigationTest/apps/type_Sdtrappo00b.cs new file mode 100644 index 000000000..a54361dca --- /dev/null +++ b/dotnet/test/DotNetCoreAttackMitigationTest/apps/type_Sdtrappo00b.cs @@ -0,0 +1,1836 @@ +using System; +using System.Collections; +using System.Reflection; +using System.Runtime.Serialization; +using System.Xml.Serialization; +using GeneXus.Application; +using GeneXus.Utils; +namespace GeneXus.Programs +{ + [XmlRoot(ElementName = "rappo00b" )] + [XmlType(TypeName = "rappo00b" , Namespace = "NETCoreTest" )] + [Serializable] + public class Sdtrappo00b : GxSilentTrnSdt + { + public Sdtrappo00b( ) + { + } + + public Sdtrappo00b( IGxContext context ) + { + this.context = context; + constructorCallingAssembly = Assembly.GetEntryAssembly(); + initialize(); + } + + private static Hashtable mapper; + public override string JsonMap( string value ) + { + if ( mapper == null ) + { + mapper = new Hashtable(); + } + return (string)mapper[value]; ; + } + public override GXProperties GetMetadata( ) + { + GXProperties metadata = new GXProperties(); + metadata.Set("Name", "rappo00b"); + metadata.Set("BT", "RAPPO00F"); + metadata.Set("PK", "[ \"UteCod\",\"RapPrg\" ]"); + metadata.Set("PKAssigned", "[ \"UteCod\" ]"); + metadata.Set("AllowInsert", "True"); + metadata.Set("AllowUpdate", "True"); + metadata.Set("AllowDelete", "True"); + return metadata ; + } + + public override void Copy( GxUserType source ) + { + Sdtrappo00b sdt; + sdt = (Sdtrappo00b)(source); + gxTv_Sdtrappo00b_Utecod = sdt.gxTv_Sdtrappo00b_Utecod ; + gxTv_Sdtrappo00b_Rapprg = sdt.gxTv_Sdtrappo00b_Rapprg ; + gxTv_Sdtrappo00b_Raptitolo = sdt.gxTv_Sdtrappo00b_Raptitolo ; + gxTv_Sdtrappo00b_Rapdata = sdt.gxTv_Sdtrappo00b_Rapdata ; + gxTv_Sdtrappo00b_Raporafin = sdt.gxTv_Sdtrappo00b_Raporafin ; + gxTv_Sdtrappo00b_Raporaini = sdt.gxTv_Sdtrappo00b_Raporaini ; + gxTv_Sdtrappo00b_Rapore = sdt.gxTv_Sdtrappo00b_Rapore ; + gxTv_Sdtrappo00b_Rapdaa = sdt.gxTv_Sdtrappo00b_Rapdaa ; + gxTv_Sdtrappo00b_Raporafinall = sdt.gxTv_Sdtrappo00b_Raporafinall ; + gxTv_Sdtrappo00b_Raporainiall = sdt.gxTv_Sdtrappo00b_Raporainiall ; + gxTv_Sdtrappo00b_Mode = sdt.gxTv_Sdtrappo00b_Mode ; + gxTv_Sdtrappo00b_Initialized = sdt.gxTv_Sdtrappo00b_Initialized ; + gxTv_Sdtrappo00b_Utecod_Z = sdt.gxTv_Sdtrappo00b_Utecod_Z ; + gxTv_Sdtrappo00b_Rapprg_Z = sdt.gxTv_Sdtrappo00b_Rapprg_Z ; + gxTv_Sdtrappo00b_Raptitolo_Z = sdt.gxTv_Sdtrappo00b_Raptitolo_Z ; + gxTv_Sdtrappo00b_Rapdata_Z = sdt.gxTv_Sdtrappo00b_Rapdata_Z ; + gxTv_Sdtrappo00b_Raporafin_Z = sdt.gxTv_Sdtrappo00b_Raporafin_Z ; + gxTv_Sdtrappo00b_Raporaini_Z = sdt.gxTv_Sdtrappo00b_Raporaini_Z ; + gxTv_Sdtrappo00b_Rapore_Z = sdt.gxTv_Sdtrappo00b_Rapore_Z ; + gxTv_Sdtrappo00b_Rapdaa_Z = sdt.gxTv_Sdtrappo00b_Rapdaa_Z ; + gxTv_Sdtrappo00b_Raporafinall_Z = sdt.gxTv_Sdtrappo00b_Raporafinall_Z ; + gxTv_Sdtrappo00b_Raporainiall_Z = sdt.gxTv_Sdtrappo00b_Raporainiall_Z ; + gxTv_Sdtrappo00b_Raptitolo_N = sdt.gxTv_Sdtrappo00b_Raptitolo_N ; + gxTv_Sdtrappo00b_Rapdata_N = sdt.gxTv_Sdtrappo00b_Rapdata_N ; + gxTv_Sdtrappo00b_Raporafin_N = sdt.gxTv_Sdtrappo00b_Raporafin_N ; + gxTv_Sdtrappo00b_Raporaini_N = sdt.gxTv_Sdtrappo00b_Raporaini_N ; + gxTv_Sdtrappo00b_Rapore_N = sdt.gxTv_Sdtrappo00b_Rapore_N ; + gxTv_Sdtrappo00b_Rapdaa_N = sdt.gxTv_Sdtrappo00b_Rapdaa_N ; + gxTv_Sdtrappo00b_Raporafinall_N = sdt.gxTv_Sdtrappo00b_Raporafinall_N ; + gxTv_Sdtrappo00b_Raporainiall_N = sdt.gxTv_Sdtrappo00b_Raporainiall_N ; + return ; + } + + public override void ToJSON( ) + { + ToJSON( true) ; + return ; + } + + public override void ToJSON( bool includeState ) + { + ToJSON( includeState, true) ; + return ; + } + + public override void ToJSON( bool includeState , + bool includeNonInitialized ) + { + AddObjectProperty("UteCod", StringUtil.LTrim( StringUtil.Str( (decimal)(gxTv_Sdtrappo00b_Utecod), 18, 0)), false, includeNonInitialized); + AddObjectProperty("RapPrg", StringUtil.LTrim( StringUtil.Str( (decimal)(gxTv_Sdtrappo00b_Rapprg), 18, 0)), false, includeNonInitialized); + AddObjectProperty("RapTitolo", gxTv_Sdtrappo00b_Raptitolo, false, includeNonInitialized); + AddObjectProperty("RapTitolo_N", gxTv_Sdtrappo00b_Raptitolo_N, false, includeNonInitialized); + sDateCnv = ""; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Year( gxTv_Sdtrappo00b_Rapdata)), 10, 0)); + sDateCnv += StringUtil.Substring( "0000", 1, 4-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Month( gxTv_Sdtrappo00b_Rapdata)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Day( gxTv_Sdtrappo00b_Rapdata)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + AddObjectProperty("RapData", sDateCnv, false, includeNonInitialized); + AddObjectProperty("RapData_N", gxTv_Sdtrappo00b_Rapdata_N, false, includeNonInitialized); + datetime_STZ = gxTv_Sdtrappo00b_Raporafin; + sDateCnv = ""; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Year( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "0000", 1, 4-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Month( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Day( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "T"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Hour( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += ":"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Minute( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += ":"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Second( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + AddObjectProperty("RapOraFin", sDateCnv, false, includeNonInitialized); + AddObjectProperty("RapOraFin_N", gxTv_Sdtrappo00b_Raporafin_N, false, includeNonInitialized); + datetime_STZ = gxTv_Sdtrappo00b_Raporaini; + sDateCnv = ""; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Year( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "0000", 1, 4-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Month( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Day( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "T"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Hour( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += ":"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Minute( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += ":"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Second( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + AddObjectProperty("RapOraIni", sDateCnv, false, includeNonInitialized); + AddObjectProperty("RapOraIni_N", gxTv_Sdtrappo00b_Raporaini_N, false, includeNonInitialized); + AddObjectProperty("RapOre", gxTv_Sdtrappo00b_Rapore, false, includeNonInitialized); + AddObjectProperty("RapOre_N", gxTv_Sdtrappo00b_Rapore_N, false, includeNonInitialized); + datetime_STZ = gxTv_Sdtrappo00b_Rapdaa; + sDateCnv = ""; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Year( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "0000", 1, 4-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Month( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Day( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "T"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Hour( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += ":"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Minute( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += ":"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Second( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + AddObjectProperty("RapDaa", sDateCnv, false, includeNonInitialized); + AddObjectProperty("RapDaa_N", gxTv_Sdtrappo00b_Rapdaa_N, false, includeNonInitialized); + datetime_STZ = gxTv_Sdtrappo00b_Raporafinall; + sDateCnv = ""; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Year( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "0000", 1, 4-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Month( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Day( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "T"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Hour( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += ":"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Minute( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += ":"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Second( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + AddObjectProperty("RapOraFinAll", sDateCnv, false, includeNonInitialized); + AddObjectProperty("RapOraFinAll_N", gxTv_Sdtrappo00b_Raporafinall_N, false, includeNonInitialized); + datetime_STZ = gxTv_Sdtrappo00b_Raporainiall; + sDateCnv = ""; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Year( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "0000", 1, 4-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Month( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Day( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "T"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Hour( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += ":"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Minute( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += ":"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Second( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + AddObjectProperty("RapOraIniAll", sDateCnv, false, includeNonInitialized); + AddObjectProperty("RapOraIniAll_N", gxTv_Sdtrappo00b_Raporainiall_N, false, includeNonInitialized); + if ( includeState ) + { + AddObjectProperty("Mode", gxTv_Sdtrappo00b_Mode, false, includeNonInitialized); + AddObjectProperty("Initialized", gxTv_Sdtrappo00b_Initialized, false, includeNonInitialized); + AddObjectProperty("UteCod_Z", StringUtil.LTrim( StringUtil.Str( (decimal)(gxTv_Sdtrappo00b_Utecod_Z), 18, 0)), false, includeNonInitialized); + AddObjectProperty("RapPrg_Z", StringUtil.LTrim( StringUtil.Str( (decimal)(gxTv_Sdtrappo00b_Rapprg_Z), 18, 0)), false, includeNonInitialized); + AddObjectProperty("RapTitolo_Z", gxTv_Sdtrappo00b_Raptitolo_Z, false, includeNonInitialized); + sDateCnv = ""; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Year( gxTv_Sdtrappo00b_Rapdata_Z)), 10, 0)); + sDateCnv += StringUtil.Substring( "0000", 1, 4-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Month( gxTv_Sdtrappo00b_Rapdata_Z)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Day( gxTv_Sdtrappo00b_Rapdata_Z)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + AddObjectProperty("RapData_Z", sDateCnv, false, includeNonInitialized); + datetime_STZ = gxTv_Sdtrappo00b_Raporafin_Z; + sDateCnv = ""; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Year( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "0000", 1, 4-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Month( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Day( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "T"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Hour( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += ":"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Minute( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += ":"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Second( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + AddObjectProperty("RapOraFin_Z", sDateCnv, false, includeNonInitialized); + datetime_STZ = gxTv_Sdtrappo00b_Raporaini_Z; + sDateCnv = ""; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Year( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "0000", 1, 4-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Month( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Day( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "T"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Hour( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += ":"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Minute( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += ":"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Second( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + AddObjectProperty("RapOraIni_Z", sDateCnv, false, includeNonInitialized); + AddObjectProperty("RapOre_Z", gxTv_Sdtrappo00b_Rapore_Z, false, includeNonInitialized); + datetime_STZ = gxTv_Sdtrappo00b_Rapdaa_Z; + sDateCnv = ""; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Year( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "0000", 1, 4-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Month( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Day( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "T"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Hour( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += ":"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Minute( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += ":"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Second( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + AddObjectProperty("RapDaa_Z", sDateCnv, false, includeNonInitialized); + datetime_STZ = gxTv_Sdtrappo00b_Raporafinall_Z; + sDateCnv = ""; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Year( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "0000", 1, 4-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Month( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Day( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "T"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Hour( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += ":"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Minute( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += ":"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Second( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + AddObjectProperty("RapOraFinAll_Z", sDateCnv, false, includeNonInitialized); + datetime_STZ = gxTv_Sdtrappo00b_Raporainiall_Z; + sDateCnv = ""; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Year( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "0000", 1, 4-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Month( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Day( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "T"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Hour( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += ":"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Minute( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += ":"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Second( datetime_STZ)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + AddObjectProperty("RapOraIniAll_Z", sDateCnv, false, includeNonInitialized); + AddObjectProperty("RapTitolo_N", gxTv_Sdtrappo00b_Raptitolo_N, false, includeNonInitialized); + AddObjectProperty("RapData_N", gxTv_Sdtrappo00b_Rapdata_N, false, includeNonInitialized); + AddObjectProperty("RapOraFin_N", gxTv_Sdtrappo00b_Raporafin_N, false, includeNonInitialized); + AddObjectProperty("RapOraIni_N", gxTv_Sdtrappo00b_Raporaini_N, false, includeNonInitialized); + AddObjectProperty("RapOre_N", gxTv_Sdtrappo00b_Rapore_N, false, includeNonInitialized); + AddObjectProperty("RapDaa_N", gxTv_Sdtrappo00b_Rapdaa_N, false, includeNonInitialized); + AddObjectProperty("RapOraFinAll_N", gxTv_Sdtrappo00b_Raporafinall_N, false, includeNonInitialized); + AddObjectProperty("RapOraIniAll_N", gxTv_Sdtrappo00b_Raporainiall_N, false, includeNonInitialized); + } + return ; + } + + public void UpdateDirties( Sdtrappo00b sdt ) + { + if ( sdt.IsDirty("UteCod") ) + { + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Utecod = sdt.gxTv_Sdtrappo00b_Utecod ; + } + if ( sdt.IsDirty("RapPrg") ) + { + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Rapprg = sdt.gxTv_Sdtrappo00b_Rapprg ; + } + if ( sdt.IsDirty("RapTitolo") ) + { + gxTv_Sdtrappo00b_Raptitolo_N = (short)(sdt.gxTv_Sdtrappo00b_Raptitolo_N); + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Raptitolo = sdt.gxTv_Sdtrappo00b_Raptitolo ; + } + if ( sdt.IsDirty("RapData") ) + { + gxTv_Sdtrappo00b_Rapdata_N = (short)(sdt.gxTv_Sdtrappo00b_Rapdata_N); + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Rapdata = sdt.gxTv_Sdtrappo00b_Rapdata ; + } + if ( sdt.IsDirty("RapOraFin") ) + { + gxTv_Sdtrappo00b_Raporafin_N = (short)(sdt.gxTv_Sdtrappo00b_Raporafin_N); + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Raporafin = sdt.gxTv_Sdtrappo00b_Raporafin ; + } + if ( sdt.IsDirty("RapOraIni") ) + { + gxTv_Sdtrappo00b_Raporaini_N = (short)(sdt.gxTv_Sdtrappo00b_Raporaini_N); + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Raporaini = sdt.gxTv_Sdtrappo00b_Raporaini ; + } + if ( sdt.IsDirty("RapOre") ) + { + gxTv_Sdtrappo00b_Rapore_N = (short)(sdt.gxTv_Sdtrappo00b_Rapore_N); + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Rapore = sdt.gxTv_Sdtrappo00b_Rapore ; + } + if ( sdt.IsDirty("RapDaa") ) + { + gxTv_Sdtrappo00b_Rapdaa_N = (short)(sdt.gxTv_Sdtrappo00b_Rapdaa_N); + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Rapdaa = sdt.gxTv_Sdtrappo00b_Rapdaa ; + } + if ( sdt.IsDirty("RapOraFinAll") ) + { + gxTv_Sdtrappo00b_Raporafinall_N = (short)(sdt.gxTv_Sdtrappo00b_Raporafinall_N); + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Raporafinall = sdt.gxTv_Sdtrappo00b_Raporafinall ; + } + if ( sdt.IsDirty("RapOraIniAll") ) + { + gxTv_Sdtrappo00b_Raporainiall_N = (short)(sdt.gxTv_Sdtrappo00b_Raporainiall_N); + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Raporainiall = sdt.gxTv_Sdtrappo00b_Raporainiall ; + } + return ; + } + + [ SoapElement( ElementName = "UteCod" )] + [ XmlElement( ElementName = "UteCod" )] + public long gxTpr_Utecod + { + get { + return gxTv_Sdtrappo00b_Utecod ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + if ( gxTv_Sdtrappo00b_Utecod != value ) + { + gxTv_Sdtrappo00b_Mode = "INS"; + this.gxTv_Sdtrappo00b_Utecod_Z_SetNull( ); + this.gxTv_Sdtrappo00b_Rapprg_Z_SetNull( ); + this.gxTv_Sdtrappo00b_Raptitolo_Z_SetNull( ); + this.gxTv_Sdtrappo00b_Rapdata_Z_SetNull( ); + this.gxTv_Sdtrappo00b_Raporafin_Z_SetNull( ); + this.gxTv_Sdtrappo00b_Raporaini_Z_SetNull( ); + this.gxTv_Sdtrappo00b_Rapore_Z_SetNull( ); + this.gxTv_Sdtrappo00b_Rapdaa_Z_SetNull( ); + this.gxTv_Sdtrappo00b_Raporafinall_Z_SetNull( ); + this.gxTv_Sdtrappo00b_Raporainiall_Z_SetNull( ); + } + gxTv_Sdtrappo00b_Utecod = value; + SetDirty("Utecod"); + } + + } + + [ SoapElement( ElementName = "RapPrg" )] + [ XmlElement( ElementName = "RapPrg" )] + public long gxTpr_Rapprg + { + get { + return gxTv_Sdtrappo00b_Rapprg ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + if ( gxTv_Sdtrappo00b_Rapprg != value ) + { + gxTv_Sdtrappo00b_Mode = "INS"; + this.gxTv_Sdtrappo00b_Utecod_Z_SetNull( ); + this.gxTv_Sdtrappo00b_Rapprg_Z_SetNull( ); + this.gxTv_Sdtrappo00b_Raptitolo_Z_SetNull( ); + this.gxTv_Sdtrappo00b_Rapdata_Z_SetNull( ); + this.gxTv_Sdtrappo00b_Raporafin_Z_SetNull( ); + this.gxTv_Sdtrappo00b_Raporaini_Z_SetNull( ); + this.gxTv_Sdtrappo00b_Rapore_Z_SetNull( ); + this.gxTv_Sdtrappo00b_Rapdaa_Z_SetNull( ); + this.gxTv_Sdtrappo00b_Raporafinall_Z_SetNull( ); + this.gxTv_Sdtrappo00b_Raporainiall_Z_SetNull( ); + } + gxTv_Sdtrappo00b_Rapprg = value; + SetDirty("Rapprg"); + } + + } + + [ SoapElement( ElementName = "RapTitolo" )] + [ XmlElement( ElementName = "RapTitolo" )] + public string gxTpr_Raptitolo + { + get { + return gxTv_Sdtrappo00b_Raptitolo ; + } + + set { + gxTv_Sdtrappo00b_Raptitolo_N = 0; + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Raptitolo = value; + SetDirty("Raptitolo"); + } + + } + + public void gxTv_Sdtrappo00b_Raptitolo_SetNull( ) + { + gxTv_Sdtrappo00b_Raptitolo_N = 1; + gxTv_Sdtrappo00b_Raptitolo = ""; + SetDirty("Raptitolo"); + return ; + } + + public bool gxTv_Sdtrappo00b_Raptitolo_IsNull( ) + { + return (gxTv_Sdtrappo00b_Raptitolo_N==1) ; + } + + [ SoapElement( ElementName = "RapData" )] + [ XmlElement( ElementName = "RapData" , IsNullable=true )] + public string gxTpr_Rapdata_Nullable + { + get { + if ( gxTv_Sdtrappo00b_Rapdata == DateTime.MinValue) + return null; + return new GxDateString(gxTv_Sdtrappo00b_Rapdata).value ; + } + + set { + gxTv_Sdtrappo00b_Rapdata_N = 0; + gxTv_Sdtrappo00b_N = 0; + if (String.IsNullOrEmpty(value) || value == GxDateString.NullValue ) + gxTv_Sdtrappo00b_Rapdata = DateTime.MinValue; + else + gxTv_Sdtrappo00b_Rapdata = DateTime.Parse( value); + } + + } + + [XmlIgnore] + public DateTime gxTpr_Rapdata + { + get { + return gxTv_Sdtrappo00b_Rapdata ; + } + + set { + gxTv_Sdtrappo00b_Rapdata_N = 0; + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Rapdata = value; + SetDirty("Rapdata"); + } + + } + + public void gxTv_Sdtrappo00b_Rapdata_SetNull( ) + { + gxTv_Sdtrappo00b_Rapdata_N = 1; + gxTv_Sdtrappo00b_Rapdata = (DateTime)(DateTime.MinValue); + SetDirty("Rapdata"); + return ; + } + + public bool gxTv_Sdtrappo00b_Rapdata_IsNull( ) + { + return (gxTv_Sdtrappo00b_Rapdata_N==1) ; + } + + [ SoapElement( ElementName = "RapOraFin" )] + [ XmlElement( ElementName = "RapOraFin" , IsNullable=true )] + public string gxTpr_Raporafin_Nullable + { + get { + if ( gxTv_Sdtrappo00b_Raporafin == DateTime.MinValue) + return null; + return new GxDatetimeString(gxTv_Sdtrappo00b_Raporafin).value ; + } + + set { + gxTv_Sdtrappo00b_Raporafin_N = 0; + gxTv_Sdtrappo00b_N = 0; + if (String.IsNullOrEmpty(value) || value == GxDatetimeString.NullValue ) + gxTv_Sdtrappo00b_Raporafin = DateTime.MinValue; + else + gxTv_Sdtrappo00b_Raporafin = DateTime.Parse( value); + } + + } + + [XmlIgnore] + public DateTime gxTpr_Raporafin + { + get { + return gxTv_Sdtrappo00b_Raporafin ; + } + + set { + gxTv_Sdtrappo00b_Raporafin_N = 0; + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Raporafin = value; + SetDirty("Raporafin"); + } + + } + + public void gxTv_Sdtrappo00b_Raporafin_SetNull( ) + { + gxTv_Sdtrappo00b_Raporafin_N = 1; + gxTv_Sdtrappo00b_Raporafin = (DateTime)(DateTime.MinValue); + SetDirty("Raporafin"); + return ; + } + + public bool gxTv_Sdtrappo00b_Raporafin_IsNull( ) + { + return (gxTv_Sdtrappo00b_Raporafin_N==1) ; + } + + [ SoapElement( ElementName = "RapOraIni" )] + [ XmlElement( ElementName = "RapOraIni" , IsNullable=true )] + public string gxTpr_Raporaini_Nullable + { + get { + if ( gxTv_Sdtrappo00b_Raporaini == DateTime.MinValue) + return null; + return new GxDatetimeString(gxTv_Sdtrappo00b_Raporaini).value ; + } + + set { + gxTv_Sdtrappo00b_Raporaini_N = 0; + gxTv_Sdtrappo00b_N = 0; + if (String.IsNullOrEmpty(value) || value == GxDatetimeString.NullValue ) + gxTv_Sdtrappo00b_Raporaini = DateTime.MinValue; + else + gxTv_Sdtrappo00b_Raporaini = DateTime.Parse( value); + } + + } + + [XmlIgnore] + public DateTime gxTpr_Raporaini + { + get { + return gxTv_Sdtrappo00b_Raporaini ; + } + + set { + gxTv_Sdtrappo00b_Raporaini_N = 0; + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Raporaini = value; + SetDirty("Raporaini"); + } + + } + + public void gxTv_Sdtrappo00b_Raporaini_SetNull( ) + { + gxTv_Sdtrappo00b_Raporaini_N = 1; + gxTv_Sdtrappo00b_Raporaini = (DateTime)(DateTime.MinValue); + SetDirty("Raporaini"); + return ; + } + + public bool gxTv_Sdtrappo00b_Raporaini_IsNull( ) + { + return (gxTv_Sdtrappo00b_Raporaini_N==1) ; + } + + [ SoapElement( ElementName = "RapOre" )] + [ XmlElement( ElementName = "RapOre" )] + public decimal gxTpr_Rapore + { + get { + return gxTv_Sdtrappo00b_Rapore ; + } + + set { + gxTv_Sdtrappo00b_Rapore_N = 0; + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Rapore = value; + SetDirty("Rapore"); + } + + } + + public void gxTv_Sdtrappo00b_Rapore_SetNull( ) + { + gxTv_Sdtrappo00b_Rapore_N = 1; + gxTv_Sdtrappo00b_Rapore = 0; + SetDirty("Rapore"); + return ; + } + + public bool gxTv_Sdtrappo00b_Rapore_IsNull( ) + { + return (gxTv_Sdtrappo00b_Rapore_N==1) ; + } + + [ SoapElement( ElementName = "RapDaa" )] + [ XmlElement( ElementName = "RapDaa" , IsNullable=true )] + public string gxTpr_Rapdaa_Nullable + { + get { + if ( gxTv_Sdtrappo00b_Rapdaa == DateTime.MinValue) + return null; + return new GxDatetimeString(gxTv_Sdtrappo00b_Rapdaa).value ; + } + + set { + gxTv_Sdtrappo00b_Rapdaa_N = 0; + gxTv_Sdtrappo00b_N = 0; + if (String.IsNullOrEmpty(value) || value == GxDatetimeString.NullValue ) + gxTv_Sdtrappo00b_Rapdaa = DateTime.MinValue; + else + gxTv_Sdtrappo00b_Rapdaa = DateTime.Parse( value); + } + + } + + [XmlIgnore] + public DateTime gxTpr_Rapdaa + { + get { + return gxTv_Sdtrappo00b_Rapdaa ; + } + + set { + gxTv_Sdtrappo00b_Rapdaa_N = 0; + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Rapdaa = value; + SetDirty("Rapdaa"); + } + + } + + public void gxTv_Sdtrappo00b_Rapdaa_SetNull( ) + { + gxTv_Sdtrappo00b_Rapdaa_N = 1; + gxTv_Sdtrappo00b_Rapdaa = (DateTime)(DateTime.MinValue); + SetDirty("Rapdaa"); + return ; + } + + public bool gxTv_Sdtrappo00b_Rapdaa_IsNull( ) + { + return (gxTv_Sdtrappo00b_Rapdaa_N==1) ; + } + + [ SoapElement( ElementName = "RapOraFinAll" )] + [ XmlElement( ElementName = "RapOraFinAll" , IsNullable=true )] + public string gxTpr_Raporafinall_Nullable + { + get { + if ( gxTv_Sdtrappo00b_Raporafinall == DateTime.MinValue) + return null; + return new GxDatetimeString(gxTv_Sdtrappo00b_Raporafinall).value ; + } + + set { + gxTv_Sdtrappo00b_Raporafinall_N = 0; + gxTv_Sdtrappo00b_N = 0; + if (String.IsNullOrEmpty(value) || value == GxDatetimeString.NullValue ) + gxTv_Sdtrappo00b_Raporafinall = DateTime.MinValue; + else + gxTv_Sdtrappo00b_Raporafinall = DateTime.Parse( value); + } + + } + + [XmlIgnore] + public DateTime gxTpr_Raporafinall + { + get { + return gxTv_Sdtrappo00b_Raporafinall ; + } + + set { + gxTv_Sdtrappo00b_Raporafinall_N = 0; + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Raporafinall = value; + SetDirty("Raporafinall"); + } + + } + + public void gxTv_Sdtrappo00b_Raporafinall_SetNull( ) + { + gxTv_Sdtrappo00b_Raporafinall_N = 1; + gxTv_Sdtrappo00b_Raporafinall = (DateTime)(DateTime.MinValue); + SetDirty("Raporafinall"); + return ; + } + + public bool gxTv_Sdtrappo00b_Raporafinall_IsNull( ) + { + return (gxTv_Sdtrappo00b_Raporafinall_N==1) ; + } + + [ SoapElement( ElementName = "RapOraIniAll" )] + [ XmlElement( ElementName = "RapOraIniAll" , IsNullable=true )] + public string gxTpr_Raporainiall_Nullable + { + get { + if ( gxTv_Sdtrappo00b_Raporainiall == DateTime.MinValue) + return null; + return new GxDatetimeString(gxTv_Sdtrappo00b_Raporainiall).value ; + } + + set { + gxTv_Sdtrappo00b_Raporainiall_N = 0; + gxTv_Sdtrappo00b_N = 0; + if (String.IsNullOrEmpty(value) || value == GxDatetimeString.NullValue ) + gxTv_Sdtrappo00b_Raporainiall = DateTime.MinValue; + else + gxTv_Sdtrappo00b_Raporainiall = DateTime.Parse( value); + } + + } + + [XmlIgnore] + public DateTime gxTpr_Raporainiall + { + get { + return gxTv_Sdtrappo00b_Raporainiall ; + } + + set { + gxTv_Sdtrappo00b_Raporainiall_N = 0; + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Raporainiall = value; + SetDirty("Raporainiall"); + } + + } + + public void gxTv_Sdtrappo00b_Raporainiall_SetNull( ) + { + gxTv_Sdtrappo00b_Raporainiall_N = 1; + gxTv_Sdtrappo00b_Raporainiall = (DateTime)(DateTime.MinValue); + SetDirty("Raporainiall"); + return ; + } + + public bool gxTv_Sdtrappo00b_Raporainiall_IsNull( ) + { + return (gxTv_Sdtrappo00b_Raporainiall_N==1) ; + } + + [ SoapElement( ElementName = "Mode" )] + [ XmlElement( ElementName = "Mode" )] + public string gxTpr_Mode + { + get { + return gxTv_Sdtrappo00b_Mode ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Mode = value; + SetDirty("Mode"); + } + + } + + public void gxTv_Sdtrappo00b_Mode_SetNull( ) + { + gxTv_Sdtrappo00b_Mode = ""; + SetDirty("Mode"); + return ; + } + + public bool gxTv_Sdtrappo00b_Mode_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "Initialized" )] + [ XmlElement( ElementName = "Initialized" )] + public short gxTpr_Initialized + { + get { + return gxTv_Sdtrappo00b_Initialized ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Initialized = value; + SetDirty("Initialized"); + } + + } + + public void gxTv_Sdtrappo00b_Initialized_SetNull( ) + { + gxTv_Sdtrappo00b_Initialized = 0; + SetDirty("Initialized"); + return ; + } + + public bool gxTv_Sdtrappo00b_Initialized_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "UteCod_Z" )] + [ XmlElement( ElementName = "UteCod_Z" )] + public long gxTpr_Utecod_Z + { + get { + return gxTv_Sdtrappo00b_Utecod_Z ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Utecod_Z = value; + SetDirty("Utecod_Z"); + } + + } + + public void gxTv_Sdtrappo00b_Utecod_Z_SetNull( ) + { + gxTv_Sdtrappo00b_Utecod_Z = 0; + SetDirty("Utecod_Z"); + return ; + } + + public bool gxTv_Sdtrappo00b_Utecod_Z_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "RapPrg_Z" )] + [ XmlElement( ElementName = "RapPrg_Z" )] + public long gxTpr_Rapprg_Z + { + get { + return gxTv_Sdtrappo00b_Rapprg_Z ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Rapprg_Z = value; + SetDirty("Rapprg_Z"); + } + + } + + public void gxTv_Sdtrappo00b_Rapprg_Z_SetNull( ) + { + gxTv_Sdtrappo00b_Rapprg_Z = 0; + SetDirty("Rapprg_Z"); + return ; + } + + public bool gxTv_Sdtrappo00b_Rapprg_Z_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "RapTitolo_Z" )] + [ XmlElement( ElementName = "RapTitolo_Z" )] + public string gxTpr_Raptitolo_Z + { + get { + return gxTv_Sdtrappo00b_Raptitolo_Z ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Raptitolo_Z = value; + SetDirty("Raptitolo_Z"); + } + + } + + public void gxTv_Sdtrappo00b_Raptitolo_Z_SetNull( ) + { + gxTv_Sdtrappo00b_Raptitolo_Z = ""; + SetDirty("Raptitolo_Z"); + return ; + } + + public bool gxTv_Sdtrappo00b_Raptitolo_Z_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "RapData_Z" )] + [ XmlElement( ElementName = "RapData_Z" , IsNullable=true )] + public string gxTpr_Rapdata_Z_Nullable + { + get { + if ( gxTv_Sdtrappo00b_Rapdata_Z == DateTime.MinValue) + return null; + return new GxDateString(gxTv_Sdtrappo00b_Rapdata_Z).value ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + if (String.IsNullOrEmpty(value) || value == GxDateString.NullValue ) + gxTv_Sdtrappo00b_Rapdata_Z = DateTime.MinValue; + else + gxTv_Sdtrappo00b_Rapdata_Z = DateTime.Parse( value); + } + + } + + [XmlIgnore] + public DateTime gxTpr_Rapdata_Z + { + get { + return gxTv_Sdtrappo00b_Rapdata_Z ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Rapdata_Z = value; + SetDirty("Rapdata_Z"); + } + + } + + public void gxTv_Sdtrappo00b_Rapdata_Z_SetNull( ) + { + gxTv_Sdtrappo00b_Rapdata_Z = (DateTime)(DateTime.MinValue); + SetDirty("Rapdata_Z"); + return ; + } + + public bool gxTv_Sdtrappo00b_Rapdata_Z_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "RapOraFin_Z" )] + [ XmlElement( ElementName = "RapOraFin_Z" , IsNullable=true )] + public string gxTpr_Raporafin_Z_Nullable + { + get { + if ( gxTv_Sdtrappo00b_Raporafin_Z == DateTime.MinValue) + return null; + return new GxDatetimeString(gxTv_Sdtrappo00b_Raporafin_Z).value ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + if (String.IsNullOrEmpty(value) || value == GxDatetimeString.NullValue ) + gxTv_Sdtrappo00b_Raporafin_Z = DateTime.MinValue; + else + gxTv_Sdtrappo00b_Raporafin_Z = DateTime.Parse( value); + } + + } + + [XmlIgnore] + public DateTime gxTpr_Raporafin_Z + { + get { + return gxTv_Sdtrappo00b_Raporafin_Z ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Raporafin_Z = value; + SetDirty("Raporafin_Z"); + } + + } + + public void gxTv_Sdtrappo00b_Raporafin_Z_SetNull( ) + { + gxTv_Sdtrappo00b_Raporafin_Z = (DateTime)(DateTime.MinValue); + SetDirty("Raporafin_Z"); + return ; + } + + public bool gxTv_Sdtrappo00b_Raporafin_Z_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "RapOraIni_Z" )] + [ XmlElement( ElementName = "RapOraIni_Z" , IsNullable=true )] + public string gxTpr_Raporaini_Z_Nullable + { + get { + if ( gxTv_Sdtrappo00b_Raporaini_Z == DateTime.MinValue) + return null; + return new GxDatetimeString(gxTv_Sdtrappo00b_Raporaini_Z).value ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + if (String.IsNullOrEmpty(value) || value == GxDatetimeString.NullValue ) + gxTv_Sdtrappo00b_Raporaini_Z = DateTime.MinValue; + else + gxTv_Sdtrappo00b_Raporaini_Z = DateTime.Parse( value); + } + + } + + [XmlIgnore] + public DateTime gxTpr_Raporaini_Z + { + get { + return gxTv_Sdtrappo00b_Raporaini_Z ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Raporaini_Z = value; + SetDirty("Raporaini_Z"); + } + + } + + public void gxTv_Sdtrappo00b_Raporaini_Z_SetNull( ) + { + gxTv_Sdtrappo00b_Raporaini_Z = (DateTime)(DateTime.MinValue); + SetDirty("Raporaini_Z"); + return ; + } + + public bool gxTv_Sdtrappo00b_Raporaini_Z_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "RapOre_Z" )] + [ XmlElement( ElementName = "RapOre_Z" )] + public decimal gxTpr_Rapore_Z + { + get { + return gxTv_Sdtrappo00b_Rapore_Z ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Rapore_Z = value; + SetDirty("Rapore_Z"); + } + + } + + public void gxTv_Sdtrappo00b_Rapore_Z_SetNull( ) + { + gxTv_Sdtrappo00b_Rapore_Z = 0; + SetDirty("Rapore_Z"); + return ; + } + + public bool gxTv_Sdtrappo00b_Rapore_Z_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "RapDaa_Z" )] + [ XmlElement( ElementName = "RapDaa_Z" , IsNullable=true )] + public string gxTpr_Rapdaa_Z_Nullable + { + get { + if ( gxTv_Sdtrappo00b_Rapdaa_Z == DateTime.MinValue) + return null; + return new GxDatetimeString(gxTv_Sdtrappo00b_Rapdaa_Z).value ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + if (String.IsNullOrEmpty(value) || value == GxDatetimeString.NullValue ) + gxTv_Sdtrappo00b_Rapdaa_Z = DateTime.MinValue; + else + gxTv_Sdtrappo00b_Rapdaa_Z = DateTime.Parse( value); + } + + } + + [XmlIgnore] + public DateTime gxTpr_Rapdaa_Z + { + get { + return gxTv_Sdtrappo00b_Rapdaa_Z ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Rapdaa_Z = value; + SetDirty("Rapdaa_Z"); + } + + } + + public void gxTv_Sdtrappo00b_Rapdaa_Z_SetNull( ) + { + gxTv_Sdtrappo00b_Rapdaa_Z = (DateTime)(DateTime.MinValue); + SetDirty("Rapdaa_Z"); + return ; + } + + public bool gxTv_Sdtrappo00b_Rapdaa_Z_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "RapOraFinAll_Z" )] + [ XmlElement( ElementName = "RapOraFinAll_Z" , IsNullable=true )] + public string gxTpr_Raporafinall_Z_Nullable + { + get { + if ( gxTv_Sdtrappo00b_Raporafinall_Z == DateTime.MinValue) + return null; + return new GxDatetimeString(gxTv_Sdtrappo00b_Raporafinall_Z).value ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + if (String.IsNullOrEmpty(value) || value == GxDatetimeString.NullValue ) + gxTv_Sdtrappo00b_Raporafinall_Z = DateTime.MinValue; + else + gxTv_Sdtrappo00b_Raporafinall_Z = DateTime.Parse( value); + } + + } + + [XmlIgnore] + public DateTime gxTpr_Raporafinall_Z + { + get { + return gxTv_Sdtrappo00b_Raporafinall_Z ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Raporafinall_Z = value; + SetDirty("Raporafinall_Z"); + } + + } + + public void gxTv_Sdtrappo00b_Raporafinall_Z_SetNull( ) + { + gxTv_Sdtrappo00b_Raporafinall_Z = (DateTime)(DateTime.MinValue); + SetDirty("Raporafinall_Z"); + return ; + } + + public bool gxTv_Sdtrappo00b_Raporafinall_Z_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "RapOraIniAll_Z" )] + [ XmlElement( ElementName = "RapOraIniAll_Z" , IsNullable=true )] + public string gxTpr_Raporainiall_Z_Nullable + { + get { + if ( gxTv_Sdtrappo00b_Raporainiall_Z == DateTime.MinValue) + return null; + return new GxDatetimeString(gxTv_Sdtrappo00b_Raporainiall_Z).value ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + if (String.IsNullOrEmpty(value) || value == GxDatetimeString.NullValue ) + gxTv_Sdtrappo00b_Raporainiall_Z = DateTime.MinValue; + else + gxTv_Sdtrappo00b_Raporainiall_Z = DateTime.Parse( value); + } + + } + + [XmlIgnore] + public DateTime gxTpr_Raporainiall_Z + { + get { + return gxTv_Sdtrappo00b_Raporainiall_Z ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Raporainiall_Z = value; + SetDirty("Raporainiall_Z"); + } + + } + + public void gxTv_Sdtrappo00b_Raporainiall_Z_SetNull( ) + { + gxTv_Sdtrappo00b_Raporainiall_Z = (DateTime)(DateTime.MinValue); + SetDirty("Raporainiall_Z"); + return ; + } + + public bool gxTv_Sdtrappo00b_Raporainiall_Z_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "RapTitolo_N" )] + [ XmlElement( ElementName = "RapTitolo_N" )] + public short gxTpr_Raptitolo_N + { + get { + return gxTv_Sdtrappo00b_Raptitolo_N ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Raptitolo_N = value; + SetDirty("Raptitolo_N"); + } + + } + + public void gxTv_Sdtrappo00b_Raptitolo_N_SetNull( ) + { + gxTv_Sdtrappo00b_Raptitolo_N = 0; + SetDirty("Raptitolo_N"); + return ; + } + + public bool gxTv_Sdtrappo00b_Raptitolo_N_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "RapData_N" )] + [ XmlElement( ElementName = "RapData_N" )] + public short gxTpr_Rapdata_N + { + get { + return gxTv_Sdtrappo00b_Rapdata_N ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Rapdata_N = value; + SetDirty("Rapdata_N"); + } + + } + + public void gxTv_Sdtrappo00b_Rapdata_N_SetNull( ) + { + gxTv_Sdtrappo00b_Rapdata_N = 0; + SetDirty("Rapdata_N"); + return ; + } + + public bool gxTv_Sdtrappo00b_Rapdata_N_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "RapOraFin_N" )] + [ XmlElement( ElementName = "RapOraFin_N" )] + public short gxTpr_Raporafin_N + { + get { + return gxTv_Sdtrappo00b_Raporafin_N ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Raporafin_N = value; + SetDirty("Raporafin_N"); + } + + } + + public void gxTv_Sdtrappo00b_Raporafin_N_SetNull( ) + { + gxTv_Sdtrappo00b_Raporafin_N = 0; + SetDirty("Raporafin_N"); + return ; + } + + public bool gxTv_Sdtrappo00b_Raporafin_N_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "RapOraIni_N" )] + [ XmlElement( ElementName = "RapOraIni_N" )] + public short gxTpr_Raporaini_N + { + get { + return gxTv_Sdtrappo00b_Raporaini_N ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Raporaini_N = value; + SetDirty("Raporaini_N"); + } + + } + + public void gxTv_Sdtrappo00b_Raporaini_N_SetNull( ) + { + gxTv_Sdtrappo00b_Raporaini_N = 0; + SetDirty("Raporaini_N"); + return ; + } + + public bool gxTv_Sdtrappo00b_Raporaini_N_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "RapOre_N" )] + [ XmlElement( ElementName = "RapOre_N" )] + public short gxTpr_Rapore_N + { + get { + return gxTv_Sdtrappo00b_Rapore_N ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Rapore_N = value; + SetDirty("Rapore_N"); + } + + } + + public void gxTv_Sdtrappo00b_Rapore_N_SetNull( ) + { + gxTv_Sdtrappo00b_Rapore_N = 0; + SetDirty("Rapore_N"); + return ; + } + + public bool gxTv_Sdtrappo00b_Rapore_N_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "RapDaa_N" )] + [ XmlElement( ElementName = "RapDaa_N" )] + public short gxTpr_Rapdaa_N + { + get { + return gxTv_Sdtrappo00b_Rapdaa_N ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Rapdaa_N = value; + SetDirty("Rapdaa_N"); + } + + } + + public void gxTv_Sdtrappo00b_Rapdaa_N_SetNull( ) + { + gxTv_Sdtrappo00b_Rapdaa_N = 0; + SetDirty("Rapdaa_N"); + return ; + } + + public bool gxTv_Sdtrappo00b_Rapdaa_N_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "RapOraFinAll_N" )] + [ XmlElement( ElementName = "RapOraFinAll_N" )] + public short gxTpr_Raporafinall_N + { + get { + return gxTv_Sdtrappo00b_Raporafinall_N ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Raporafinall_N = value; + SetDirty("Raporafinall_N"); + } + + } + + public void gxTv_Sdtrappo00b_Raporafinall_N_SetNull( ) + { + gxTv_Sdtrappo00b_Raporafinall_N = 0; + SetDirty("Raporafinall_N"); + return ; + } + + public bool gxTv_Sdtrappo00b_Raporafinall_N_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "RapOraIniAll_N" )] + [ XmlElement( ElementName = "RapOraIniAll_N" )] + public short gxTpr_Raporainiall_N + { + get { + return gxTv_Sdtrappo00b_Raporainiall_N ; + } + + set { + gxTv_Sdtrappo00b_N = 0; + gxTv_Sdtrappo00b_Raporainiall_N = value; + SetDirty("Raporainiall_N"); + } + + } + + public void gxTv_Sdtrappo00b_Raporainiall_N_SetNull( ) + { + gxTv_Sdtrappo00b_Raporainiall_N = 0; + SetDirty("Raporainiall_N"); + return ; + } + + public bool gxTv_Sdtrappo00b_Raporainiall_N_IsNull( ) + { + return false ; + } + + public void initialize( ) + { + gxTv_Sdtrappo00b_Utecod = 1; + gxTv_Sdtrappo00b_N = 1; + gxTv_Sdtrappo00b_Raptitolo = ""; + gxTv_Sdtrappo00b_Rapdata = DateTime.MinValue; + gxTv_Sdtrappo00b_Raporafin = (DateTime)(DateTime.MinValue); + gxTv_Sdtrappo00b_Raporaini = (DateTime)(DateTime.MinValue); + gxTv_Sdtrappo00b_Rapdaa = (DateTime)(DateTime.MinValue); + gxTv_Sdtrappo00b_Raporafinall = (DateTime)(DateTime.MinValue); + gxTv_Sdtrappo00b_Raporainiall = (DateTime)(DateTime.MinValue); + gxTv_Sdtrappo00b_Mode = ""; + gxTv_Sdtrappo00b_Raptitolo_Z = ""; + gxTv_Sdtrappo00b_Rapdata_Z = DateTime.MinValue; + gxTv_Sdtrappo00b_Raporafin_Z = (DateTime)(DateTime.MinValue); + gxTv_Sdtrappo00b_Raporaini_Z = (DateTime)(DateTime.MinValue); + gxTv_Sdtrappo00b_Rapdaa_Z = (DateTime)(DateTime.MinValue); + gxTv_Sdtrappo00b_Raporafinall_Z = (DateTime)(DateTime.MinValue); + gxTv_Sdtrappo00b_Raporainiall_Z = (DateTime)(DateTime.MinValue); + sDateCnv = ""; + sNumToPad = ""; + datetime_STZ = (DateTime)(DateTime.MinValue); + /*IGxSilentTrn obj; + obj = (IGxSilentTrn)ClassLoader.FindInstance( "rappo00b", "GeneXus.Programs.rappo00b_bc", new Object[] {context}, constructorCallingAssembly);; + obj.initialize(); + obj.SetSDT(this, 1); + setTransaction( obj) ; + obj.SetMode("INS");*/ + return ; + } + + public short isNull( ) + { + return gxTv_Sdtrappo00b_N ; + } + + private short gxTv_Sdtrappo00b_N ; + private short gxTv_Sdtrappo00b_Initialized ; + private short gxTv_Sdtrappo00b_Raptitolo_N ; + private short gxTv_Sdtrappo00b_Rapdata_N ; + private short gxTv_Sdtrappo00b_Raporafin_N ; + private short gxTv_Sdtrappo00b_Raporaini_N ; + private short gxTv_Sdtrappo00b_Rapore_N ; + private short gxTv_Sdtrappo00b_Rapdaa_N ; + private short gxTv_Sdtrappo00b_Raporafinall_N ; + private short gxTv_Sdtrappo00b_Raporainiall_N ; + private long gxTv_Sdtrappo00b_Utecod ; + private long gxTv_Sdtrappo00b_Rapprg ; + private long gxTv_Sdtrappo00b_Utecod_Z ; + private long gxTv_Sdtrappo00b_Rapprg_Z ; + private decimal gxTv_Sdtrappo00b_Rapore ; + private decimal gxTv_Sdtrappo00b_Rapore_Z ; + private string gxTv_Sdtrappo00b_Mode ; + private string sDateCnv ; + private string sNumToPad ; + private DateTime gxTv_Sdtrappo00b_Raporafin ; + private DateTime gxTv_Sdtrappo00b_Raporaini ; + private DateTime gxTv_Sdtrappo00b_Rapdaa ; + private DateTime gxTv_Sdtrappo00b_Raporafinall ; + private DateTime gxTv_Sdtrappo00b_Raporainiall ; + private DateTime gxTv_Sdtrappo00b_Raporafin_Z ; + private DateTime gxTv_Sdtrappo00b_Raporaini_Z ; + private DateTime gxTv_Sdtrappo00b_Rapdaa_Z ; + private DateTime gxTv_Sdtrappo00b_Raporafinall_Z ; + private DateTime gxTv_Sdtrappo00b_Raporainiall_Z ; + private DateTime datetime_STZ ; + private DateTime gxTv_Sdtrappo00b_Rapdata ; + private DateTime gxTv_Sdtrappo00b_Rapdata_Z ; + private string gxTv_Sdtrappo00b_Raptitolo ; + private string gxTv_Sdtrappo00b_Raptitolo_Z ; + } + + [DataContract(Name = @"rappo00b", Namespace = "NETCoreTest")] + public class Sdtrappo00b_RESTInterface : GxGenericCollectionItem + { + public Sdtrappo00b_RESTInterface( ) : base() + { + } + + public Sdtrappo00b_RESTInterface( Sdtrappo00b psdt ) : base(psdt) + { + } + + [DataMember( Name = "UteCod" , Order = 0 )] + [GxSeudo()] + public string gxTpr_Utecod + { + get { + return StringUtil.LTrim( StringUtil.Str( (decimal)(sdt.gxTpr_Utecod), 18, 0)) ; + } + + set { + sdt.gxTpr_Utecod = (long)(NumberUtil.Val( value, ".")); + } + + } + + [DataMember( Name = "RapPrg" , Order = 1 )] + [GxSeudo()] + public string gxTpr_Rapprg + { + get { + return StringUtil.LTrim( StringUtil.Str( (decimal)(sdt.gxTpr_Rapprg), 18, 0)) ; + } + + set { + sdt.gxTpr_Rapprg = (long)(NumberUtil.Val( value, ".")); + } + + } + + [DataMember( Name = "RapTitolo" , Order = 2 )] + [GxSeudo()] + public string gxTpr_Raptitolo + { + get { + return sdt.gxTpr_Raptitolo ; + } + + set { + sdt.gxTpr_Raptitolo = value; + } + + } + + [DataMember( Name = "RapData" , Order = 3 )] + [GxSeudo()] + public string gxTpr_Rapdata + { + get { + return DateTimeUtil.DToC2( sdt.gxTpr_Rapdata) ; + } + + set { + sdt.gxTpr_Rapdata = DateTimeUtil.CToD2( value); + } + + } + + [DataMember( Name = "RapOraFin" , Order = 4 )] + [GxSeudo()] + public string gxTpr_Raporafin + { + get { + return DateTimeUtil.TToC2( sdt.gxTpr_Raporafin) ; + } + + set { + GXt_dtime1 = DateTimeUtil.ResetDate(DateTimeUtil.CToT2( value)); + sdt.gxTpr_Raporafin = GXt_dtime1; + } + + } + + [DataMember( Name = "RapOraIni" , Order = 5 )] + [GxSeudo()] + public string gxTpr_Raporaini + { + get { + return DateTimeUtil.TToC2( sdt.gxTpr_Raporaini) ; + } + + set { + GXt_dtime1 = DateTimeUtil.ResetDate(DateTimeUtil.CToT2( value)); + sdt.gxTpr_Raporaini = GXt_dtime1; + } + + } + + [DataMember( Name = "RapOre" , Order = 6 )] + [GxSeudo()] + public string gxTpr_Rapore + { + get { + return StringUtil.LTrim( StringUtil.Str( sdt.gxTpr_Rapore, 9, 2)) ; + } + + set { + sdt.gxTpr_Rapore = NumberUtil.Val( value, "."); + } + + } + + [DataMember( Name = "RapDaa" , Order = 7 )] + [GxSeudo()] + public string gxTpr_Rapdaa + { + get { + return DateTimeUtil.TToC2( sdt.gxTpr_Rapdaa) ; + } + + set { + sdt.gxTpr_Rapdaa = DateTimeUtil.CToT2( value); + } + + } + + [DataMember( Name = "RapOraFinAll" , Order = 8 )] + [GxSeudo()] + public string gxTpr_Raporafinall + { + get { + return DateTimeUtil.TToC2( sdt.gxTpr_Raporafinall) ; + } + + set { + sdt.gxTpr_Raporafinall = DateTimeUtil.CToT2( value); + } + + } + + [DataMember( Name = "RapOraIniAll" , Order = 9 )] + [GxSeudo()] + public string gxTpr_Raporainiall + { + get { + return DateTimeUtil.TToC2( sdt.gxTpr_Raporainiall) ; + } + + set { + sdt.gxTpr_Raporainiall = DateTimeUtil.CToT2( value); + } + + } + + public Sdtrappo00b sdt + { + get { + return (Sdtrappo00b)Sdt ; + } + + set { + Sdt = value ; + } + + } + + [OnDeserializing] + void checkSdt( StreamingContext ctx ) + { + if ( sdt == null ) + { + sdt = new Sdtrappo00b() ; + } + } + + [DataMember( Name = "gx_md5_hash", Order = 10 )] + public string Hash + { + get { + if ( StringUtil.StrCmp(md5Hash, null) == 0 ) + { + md5Hash = (string)(getHash()); + } + return md5Hash ; + } + + set { + md5Hash = value ; + } + + } + + private string md5Hash ; + private DateTime GXt_dtime1 ; + } + + [DataContract(Name = @"rappo00b", Namespace = "NETCoreTest")] + public class Sdtrappo00b_RESTLInterface : GxGenericCollectionItem + { + public Sdtrappo00b_RESTLInterface( ) : base() + { + } + + public Sdtrappo00b_RESTLInterface( Sdtrappo00b psdt ) : base(psdt) + { + } + + [DataMember( Name = "RapTitolo" , Order = 0 )] + [GxSeudo()] + public string gxTpr_Raptitolo + { + get { + return sdt.gxTpr_Raptitolo ; + } + + set { + sdt.gxTpr_Raptitolo = value; + } + + } + + [DataMember( Name = "uri", Order = 1 )] + public string Uri + { + get { + return "" ; + } + + set { + } + + } + + public Sdtrappo00b sdt + { + get { + return (Sdtrappo00b)Sdt ; + } + + set { + Sdt = value ; + } + + } + + [OnDeserializing] + void checkSdt( StreamingContext ctx ) + { + if ( sdt == null ) + { + sdt = new Sdtrappo00b() ; + } + } + + } + +} diff --git a/dotnet/test/DotNetCoreAttackMitigationTest/appsettings.json b/dotnet/test/DotNetCoreAttackMitigationTest/appsettings.json new file mode 100644 index 000000000..4eb415947 --- /dev/null +++ b/dotnet/test/DotNetCoreAttackMitigationTest/appsettings.json @@ -0,0 +1,65 @@ +{ + "appSettings": { + "AppMainNamespace": "GeneXus.Programs", + "DataStore1": "Default", + "DataStore-Count": "1", + "DataStore-Default": "Default", + "Connection-Default-DBMS": "sqlserver", + "Connection-Default-Port": "", + "Connection-Default-LockTimeout": "0", + "Connection-Default-LockRetryCount": "10", + "Connection-Default-IsolationLevel": "CR", + "Connection-Default-Datasource": "", + "Connection-Default-User": "", + "Connection-Default-Password": "", + "Connection-Default-DB": "", + "Connection-Default-Schema": "", + "Connection-Default-Opts": "", + "Connection-Default-TrnInt": "1", + "DateFormat": "MDY", + "YearLimit": "1940", + "TimeAmPmFormat": "12", + "VER_STAMP": "20210602.093942", + "CS_BLOB_PATH": "PublicTempStorage", + "TMPMEDIA_DIR": "PrivateTempStorage", + "PRINT_LAYOUT_METADATA_DIR": "LayoutMetadata", + "StorageTimeZone": "1", + "LOGIN_AS_USERID": "0", + "LANGUAGE": "eng", + "LANG_NAME": "English", + "DECIMAL_POINT": ".", + "DATE_FMT": "MDY", + "CTOD_DATE_FMT": "L", + "Culture": "en-US", + "Theme": "Carmine", + "UseNamedParameters": "1", + "EnableIntegratedSecurity": "0", + "MAX_CURSOR": "100", + "STATIC_CONTENT": "", + "GX_BUILD_NUMBER": "11103481", + "CACHE_CONTENT_EXPIRATION": "36", + "ENABLE_MANAGEMENT": "0", + "COMPRESS_HTML": "1", + "IE_COMPATIBILITY_VIEW": "EmulateIE7", + "DocumentType": "HTML5", + "EXPOSE_METADATA": "0", + "SMART_CACHING": "0", + "wcf:serviceHostingEnvironment:useClassicReadEntityBodyMode": "true", + "HTTP_PROTOCOL": "Unsecure", + "SAMESITE_COOKIE": "Lax", + "CACHE_INVALIDATION_TOKEN": "20216211291931", + "CORS_ALLOW_ORIGIN": "https://normal-website.com", + "MY_CUSTOM_PTY": "DEFAULT_VALUE", + "ValidateCSRF": "1" + }, + "languages": { + "English": { + "code": "eng", + "culture": "en-US", + "date_fmt": "MDY", + "decimal_point": ".", + "thousand_sep": ",", + "time_fmt": "12" + } + } +} \ No newline at end of file From 0a83336353c156d11204b1b9fe7efb9ba02c7188 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 23 Aug 2023 09:49:21 -0300 Subject: [PATCH 030/164] Upgrade Microsoft.Data.SqlClient from 1.1.4 to 2.1.2 (#862) * Upgrade Microsoft.Data.SqlClient from 1.1.4 to 2.0.1. This version supports Azure Active Directory authentication. * Upgrade Microsoft.Data.SqlClient Version=2.0.1 to Version=2.1.2 (because of known vulnerabilities) Upgrade Microsoft.IdentityModel.* Version=6.5.1 to Version=6.8.0 required by Microsoft.Data.SqlClient 2.1.2 * Revert wrong change at GeneXusJWT.csproj. It is not required to upgrade Microsoft.IdentityModel* for .NET Framework projects. * Remove invalid unnecessary condition at xpath. The condition is checked at TestPackageVersionConsistencyAcrossProjects * Omit the password and username in the connection string based on the Azure Active Directory authentication method. * Omit the password and username in the connection string based on the Azure Active Directory authentication method. * Fix build error. * GeneXus.Deploy.AzureFunctions.Handlers.csproj uses newtonsoft package. Explicitly add the reference to newtonsoft since it was removed with the upgrade of Microsoft.Data.SQLClient 1.1.4 to 2.1.2 (newtonsoft was a transitive dependency of Microsoft.Data.SQLClient 1.1.4, but not for 2.1.2). * Revert "GeneXus.Deploy.AzureFunctions.Handlers.csproj uses newtonsoft package. Explicitly add the reference to newtonsoft since it was removed with the upgrade of Microsoft.Data.SQLClient 1.1.4 to 2.1.2 (newtonsoft was a transitive dependency of Microsoft.Data.SQLClient 1.1.4, but not for 2.1.2)." This reverts commit ba5be2644b204a7e07aacca005168b41dfd3ba18. * Include the inner exception in the trace to help diagnose loading errors related to Microsoft.Data.SqlClient as well as any missing dependencies. * Omit Integrated security keyword when Authentication is defined in additional connection string attributes. Cannot use 'Authentication' with 'Integrated Security'. * Fix build error. --- .../dotnetcommon/GxEncrypt/GxEncrypt.csproj | 8 +- .../src/dotnetcore/GxClasses/GxClasses.csproj | 6 +- .../GxNetCoreStartup/GxNetCoreStartup.csproj | 2 +- .../GxClasses/Data/GXDataADO.cs | 5 +- .../GxClasses/Data/GXDataCommon.cs | 262 +++++++++++------- ...eXus.Deploy.AzureFunctions.Handlers.csproj | 2 +- .../GeneXusJWTNetCore.csproj | 8 +- .../TestMockDBAccess/TestMockDBAccess.csproj | 2 +- .../DotNetCoreOpenTelemetryTest.csproj | 6 +- .../Domain/GxConnectionTest.cs | 53 ++++ .../DotNetCoreUnitTest.csproj | 4 +- .../DotNetCoreWebUnitTest.csproj | 4 +- .../PackageVersionsConsistency.cs | 11 + 13 files changed, 259 insertions(+), 114 deletions(-) create mode 100644 dotnet/test/DotNetCoreUnitTest/Domain/GxConnectionTest.cs diff --git a/dotnet/src/dotnetcommon/GxEncrypt/GxEncrypt.csproj b/dotnet/src/dotnetcommon/GxEncrypt/GxEncrypt.csproj index a46827308..9ebbb61f4 100644 --- a/dotnet/src/dotnetcommon/GxEncrypt/GxEncrypt.csproj +++ b/dotnet/src/dotnetcommon/GxEncrypt/GxEncrypt.csproj @@ -6,7 +6,11 @@ Encrypt64 Decrypt64 GeneXus.Encrypt - - + + + + + +
\ No newline at end of file diff --git a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj index a153ec7c7..b42acd3bc 100644 --- a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj +++ b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj @@ -151,7 +151,7 @@ - + all @@ -167,9 +167,9 @@ - + - + diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj b/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj index 2118c21f1..525ff717a 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj @@ -12,7 +12,7 @@ - + diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataADO.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataADO.cs index 3aeb551d8..206a66c79 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataADO.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataADO.cs @@ -1728,7 +1728,10 @@ public IDataReader ExecuteReader() catch (Exception e) { GXLogging.Error(log, "Return GxCommand.ExecuteReader Error ", e); - + if (e.InnerException != null) + { + GXLogging.Error(log, "Inner Error", e.InnerException); + } throw (new GxADODataException(e)); } diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs index 71d9f17d0..35b966913 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs @@ -1016,6 +1016,33 @@ public virtual string ReplaceKeyword(string data, string keyword, string newKeyw res.Append(newKeyword); res.Append('='); res.Append(prop[1]); + res.Append(';'); + } + else + { + res.Append(s); + res.Append(';'); + } + } + } + return res.ToString(); + } + public virtual string ReplaceKeyValue(string data, string keyword, string newValue) + { + char[] sep = { ';' }; + StringBuilder res = new StringBuilder(""); + string[] props = data.Split(sep); + foreach (string s in props) + { + if (s != null && s.Length > 0) + { + string[] prop = s.Split('='); + if (prop != null && prop.Length == 2 && prop[0].Trim().Equals(keyword, StringComparison.OrdinalIgnoreCase)) + { + res.Append(keyword); + res.Append('='); + res.Append(newValue); + res.Append(';'); } else { @@ -1066,21 +1093,19 @@ public string GetParameterValue(string conStr, string searchParam) return string.Empty; else { - - int posBegin = 0; - int posEnd = 0; string paramVal = string.Empty; - posBegin = conStr.IndexOf(searchParam, StringComparison.OrdinalIgnoreCase); + int posBegin = conStr.IndexOf(searchParam, StringComparison.OrdinalIgnoreCase); if (posBegin > -1) { posBegin += searchParam.Length + 1; + int posEnd; if (conStr.LastIndexOf(';') > posBegin) - + posEnd = conStr.IndexOf(';', posBegin); else - + posEnd = conStr.Length; paramVal = conStr.Substring(posBegin, (posEnd - posBegin)); @@ -1567,18 +1592,22 @@ public class GxSqlServer : GxDataRecord private int m_FailedConnections; private int m_FailedCreate; private int MAX_TRIES; - private int MAX_CREATE_TRIES=3; - private const int MILLISECONDS_BETWEEN_RETRY_ATTEMPTS=500; + private int MAX_CREATE_TRIES = 3; + private const int MILLISECONDS_BETWEEN_RETRY_ATTEMPTS = 500; private const string MULTIPLE_DATAREADERS = "MultipleActiveResultSets"; +#if NETCORE + private const string INTEGRATED_SECURITY = "Integrated Security"; + private const string INTEGRATED_SECURITY_NO = "no"; +#endif private bool multipleDatareadersEnabled; - public override int GetCommandTimeout() - { - return base.GetCommandTimeout(); - } + public override int GetCommandTimeout() + { + return base.GetCommandTimeout(); + } - public override GxAbstractConnectionWrapper GetConnection(bool showPrompt, string datasourceName, string userId, - string userPassword,string databaseName, string port, string schema, string extra, GxConnectionCache connectionCache) + public override GxAbstractConnectionWrapper GetConnection(bool showPrompt, string datasourceName, string userId, + string userPassword, string databaseName, string port, string schema, string extra, GxConnectionCache connectionCache) { #if !NETCORE if (showPrompt) @@ -1589,48 +1618,48 @@ public override GxAbstractConnectionWrapper GetConnection(bool showPrompt, strin #endif { if (m_connectionString == null) - m_connectionString=BuildConnectionString(datasourceName, userId, userPassword, databaseName, port, schema, extra); + m_connectionString = BuildConnectionString(datasourceName, userId, userPassword, databaseName, port, schema, extra); } - GXLogging.Debug(log, "Setting connectionString property ", ()=> BuildConnectionString(datasourceName, userId, NaV, databaseName, port, schema, extra)); - MssqlConnectionWrapper connection=new MssqlConnectionWrapper(m_connectionString,connectionCache, isolationLevel); + GXLogging.Debug(log, "Setting connectionString property ", () => BuildConnectionString(datasourceName, userId, NaV, databaseName, port, schema, extra)); + MssqlConnectionWrapper connection = new MssqlConnectionWrapper(m_connectionString, connectionCache, isolationLevel); m_FailedConnections = 0; - m_FailedCreate=0; + m_FailedCreate = 0; return connection; } - public override bool AllowsDuplicateParameters - { - get - { - return false; - } - } + public override bool AllowsDuplicateParameters + { + get + { + return false; + } + } public override IDbDataParameter CreateParameter() { return new SqlParameter(); } public override IDbDataParameter CreateParameter(string name, Object dbtype, int gxlength, int gxdec) { - SqlParameter parm =new SqlParameter(); - SqlDbType type= GXTypeToSqlDbType(dbtype); - parm.SqlDbType=type; - parm.IsNullable=true; + SqlParameter parm = new SqlParameter(); + SqlDbType type = GXTypeToSqlDbType(dbtype); + parm.SqlDbType = type; + parm.IsNullable = true; parm.Size = gxlength; - if(type==SqlDbType.Decimal) + if (type == SqlDbType.Decimal) { parm.Precision = (byte)gxlength; - parm.Scale= (byte)gxdec; + parm.Scale = (byte)gxdec; } - + #if !NETCORE else if (type == SqlDbType.Udt) { parm.UdtTypeName = "Geography"; } #endif - parm.ParameterName=name; + parm.ParameterName = name; return parm; } private SqlDbType GXTypeToSqlDbType(object type) @@ -1653,11 +1682,11 @@ private SqlDbType GXTypeToSqlDbType(object type) case GXType.Geopolygon: return SqlDbType.Udt; #endif - case GXType.Int16: return SqlDbType.SmallInt; + case GXType.Int16: return SqlDbType.SmallInt; case GXType.Int32: return SqlDbType.Int; case GXType.Int64: return SqlDbType.BigInt; case GXType.Number: return SqlDbType.Float; - case GXType.Decimal: return SqlDbType.Decimal; + case GXType.Decimal: return SqlDbType.Decimal; case GXType.DateTime: return SqlDbType.DateTime; case GXType.DateTime2: return SqlDbType.DateTime2; case GXType.NChar: return SqlDbType.NChar; @@ -1683,7 +1712,7 @@ public override IDbCommand GetCachedCommand(IGxConnection con, string stmt) { if (multipleDatareadersEnabled) { - + return con.ConnectionCache.GetAvailablePreparedCommand(stmt); } else @@ -1692,10 +1721,10 @@ public override IDbCommand GetCachedCommand(IGxConnection con, string stmt) } } public override DbDataAdapter CreateDataAdapeter() - { - return new SqlDataAdapter(); - } - public override bool MultiThreadSafe + { + return new SqlDataAdapter(); + } + public override bool MultiThreadSafe { get { @@ -1704,23 +1733,23 @@ public override bool MultiThreadSafe } public override IDataReader GetDataReader( IGxConnectionManager connManager, - IGxConnection con, - GxParameterCollection parameters , - string stmt, ushort fetchSize, - bool forFirst, int handle, + IGxConnection con, + GxParameterCollection parameters, + string stmt, ushort fetchSize, + bool forFirst, int handle, bool cached, SlidingTime expiration, bool hasNested, bool dynStmt) { - + IDataReader idatareader; if (!hasNested || multipleDatareadersEnabled)//Client Cursor { - idatareader= new GxSqlDataReader(connManager,this, con,parameters,stmt,fetchSize,forFirst,handle,cached,expiration,dynStmt); + idatareader = new GxSqlDataReader(connManager, this, con, parameters, stmt, fetchSize, forFirst, handle, cached, expiration, dynStmt); } else //Server Cursor { - idatareader= new GxSqlCursorDataReader(connManager,this, con,parameters,stmt,fetchSize,forFirst,handle,cached,expiration,dynStmt); + idatareader = new GxSqlCursorDataReader(connManager, this, con, parameters, stmt, fetchSize, forFirst, handle, cached, expiration, dynStmt); } return idatareader; @@ -1728,7 +1757,7 @@ public override IDataReader GetDataReader( public override bool IsBlobType(IDbDataParameter idbparameter) { - SqlDbType type = ((SqlParameter)idbparameter).SqlDbType; + SqlDbType type = ((SqlParameter)idbparameter).SqlDbType; return (type == SqlDbType.Image || type == SqlDbType.VarBinary); } @@ -1750,10 +1779,10 @@ public override string GetServerVersionStmt() } public override void SetTimeout(IGxConnectionManager connManager, IGxConnection connection, int handle) { - if (m_lockTimeout>0) + if (m_lockTimeout > 0) { - GXLogging.Debug(log, "Set Lock Timeout to " +m_lockTimeout/1000); - IDbCommand cmd = GetCommand(connection,SetTimeoutSentence(m_lockTimeout), new GxParameterCollection()); + GXLogging.Debug(log, "Set Lock Timeout to " + m_lockTimeout / 1000); + IDbCommand cmd = GetCommand(connection, SetTimeoutSentence(m_lockTimeout), new GxParameterCollection()); cmd.ExecuteNonQuery(); } } @@ -1762,40 +1791,40 @@ public override string SetTimeoutSentence(long milliseconds) { return "SET LOCK_TIMEOUT " + milliseconds; } - public override bool ProcessError( int dbmsErrorCode, string emsg, GxErrorMask errMask, IGxConnection con, ref int status, ref bool retry, int retryCount) - + public override bool ProcessError(int dbmsErrorCode, string emsg, GxErrorMask errMask, IGxConnection con, ref int status, ref bool retry, int retryCount) + { - GXLogging.Debug(log, "ProcessError: dbmsErrorCode=" + dbmsErrorCode +", emsg '"+ emsg + "'"); + GXLogging.Debug(log, "ProcessError: dbmsErrorCode=" + dbmsErrorCode + ", emsg '" + emsg + "'"); switch (dbmsErrorCode) { case 1801: //Database '%.*ls' already exists. case 15032: //The database '%s' already exists. break; - case 20: /*The instance of SQL Server you attempted to connect to does not support encryption. (PMcE: amazingly, this is transient)*/ - case 64: /*A connection was successfully established with the server, but then an error occurred during the login process.*/ - case 233: /*The client was unable to establish a connection because of an error during connection initialization process before login*/ - case 10053: /*A transport-level error has occurred when receiving results from the server.*/ - case 10060: /*A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible.*/ - case 40143: /*The service has encountered an error processing your request. Please try again.*/ - case 40197: /*The service has encountered an error processing your request. Please try again.*/ - case 40501: /*The service is currently busy. Retry the request after 10 seconds.*/ - case 40613: /*Database '%.*ls' on server '%.*ls' is not currently available. Please retry the connection later.*/ + case 20: /*The instance of SQL Server you attempted to connect to does not support encryption. (PMcE: amazingly, this is transient)*/ + case 64: /*A connection was successfully established with the server, but then an error occurred during the login process.*/ + case 233: /*The client was unable to establish a connection because of an error during connection initialization process before login*/ + case 10053: /*A transport-level error has occurred when receiving results from the server.*/ + case 10060: /*A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible.*/ + case 40143: /*The service has encountered an error processing your request. Please try again.*/ + case 40197: /*The service has encountered an error processing your request. Please try again.*/ + case 40501: /*The service is currently busy. Retry the request after 10 seconds.*/ + case 40613: /*Database '%.*ls' on server '%.*ls' is not currently available. Please retry the connection later.*/ case 53:/*A network-related or instance-specific error occurred while establishing a connection to SQL Server*/ - case 11: + case 11: case 121: /*A transport-level error has occurred when receiving results from the server. (provider: TCP Provider, error: 0 - The semaphore timeout period has expired.*/ case 10054://A transport-level error has occurred when sending the request to the server. (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.) case 6404: //The connection is broken and recovery is not possible. The connection is marked by the server as unrecoverable. No attempt was made to restore the connection. if (!GxContext.isReorganization && con != null && m_FailedConnections < MAX_TRIES)//Si es una operacion Open se reintenta. { - try - { - con.Close(); - } - catch { } - status=104; // General network error. Check your network documentation - Retry [Max Pool Size] times. + try + { + con.Close(); + } + catch { } + status = 104; // General network error. Check your network documentation - Retry [Max Pool Size] times. m_FailedConnections++; Thread.Sleep(MILLISECONDS_BETWEEN_RETRY_ATTEMPTS); - retry=true; + retry = true; GXLogging.Debug(log, "ProcessError: General network error, FailedConnections:" + m_FailedConnections); } else @@ -1811,7 +1840,7 @@ public override bool ProcessError( int dbmsErrorCode, string emsg, GxErrorMask e con.Close(); } catch { } - status = 104; + status = 104; m_FailedCreate++; Thread.Sleep(MILLISECONDS_BETWEEN_RETRY_ATTEMPTS); retry = true; @@ -1822,32 +1851,32 @@ public override bool ProcessError( int dbmsErrorCode, string emsg, GxErrorMask e return false; } break; - case 903: // Locked + case 903: // Locked case 1222: retry = Retry(errMask, retryCount); if (retry) - status=110;// Locked - Retry - else - status=103;//Locked + status = 110;// Locked - Retry + else + status = 103;//Locked return retry; - case 2601: // Duplicated record - case 2627: // Duplicated record - status = 1; + case 2601: // Duplicated record + case 2627: // Duplicated record + status = 1; break; - case 3701: // File not found - case 3703: // File not found - case 3704: // File not found - case 3731: // File not found - case 4902: // File not found - case 3727: // File not found - case 3728: // File not found - status = 105; + case 3701: // File not found + case 3703: // File not found + case 3704: // File not found + case 3731: // File not found + case 4902: // File not found + case 3727: // File not found + case 3728: // File not found + status = 105; break; - case 503: // Parent key not found - case 547: //conflicted with COLUMN FOREIGN KEY constraint + case 503: // Parent key not found + case 547: //conflicted with COLUMN FOREIGN KEY constraint if ((errMask & GxErrorMask.GX_MASKFOREIGNKEY) == 0) { - status = 500; // ForeignKeyError + status = 500; // ForeignKeyError return false; } break; @@ -1859,9 +1888,9 @@ public override bool ProcessError( int dbmsErrorCode, string emsg, GxErrorMask e } public override string ToDbmsConstant(DateTime Value) { - if (Value == System.DateTime.MinValue) + if (Value == System.DateTime.MinValue) Value = System.Data.SqlTypes.SqlDateTime.MinValue.Value; - return "'" + Value.ToString("yyyy-MM-dd HH\\:mm\\:ss").Replace("'","''") + "'"; + return "'" + Value.ToString("yyyy-MM-dd HH\\:mm\\:ss").Replace("'", "''") + "'"; } public override IGeographicNative GetGeospatial(IGxDbCommand cmd, IDataRecord DR, int i) @@ -1932,7 +1961,7 @@ public override void GetValues(IDataReader reader, ref object[] values) GXLogging.Error(log, "GetValues error", ex); } } - static internal decimal ReadSQLDecimal(SqlDataReader sqlReader, int idx){ + static internal decimal ReadSQLDecimal(SqlDataReader sqlReader, int idx) { //Reduce the precision //The SQlServer data type NUMBER can hold up to 38 precision, and the .NET Decimal type can hold up to 28 precision SqlDecimal sqldecimal = sqlReader.GetSqlDecimal(idx); @@ -1973,11 +2002,38 @@ static internal Int16 ReadSQLDecimalToShort(SqlDataReader sqlReader, int idx) return Convert.ToInt16(sqldecimal.Value); } } +#if NETCORE + private bool UserPasswordAllowed(SqlConnectionStringBuilder sqlConnectionString) + { + if (sqlConnectionString != null && (sqlConnectionString.Authentication == SqlAuthenticationMethod.ActiveDirectoryIntegrated || + sqlConnectionString.Authentication == SqlAuthenticationMethod.ActiveDirectoryInteractive || + sqlConnectionString.Authentication == SqlAuthenticationMethod.ActiveDirectoryManagedIdentity || + sqlConnectionString.Authentication == SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow)) + return false; + else + return true; + } + private bool UserIdAllowed(SqlConnectionStringBuilder sqlConnectionString) + { + if (sqlConnectionString != null && sqlConnectionString.Authentication == SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow) + return false; + else + return true; + } + private string ResolveConnectionStringAuthentication(string extra, SqlConnectionStringBuilder sqlConnectionString) + { + if (sqlConnectionString!=null && sqlConnectionString.Authentication != SqlAuthenticationMethod.NotSpecified && sqlConnectionString.IntegratedSecurity) + { + return ReplaceKeyValue(extra, INTEGRATED_SECURITY, INTEGRATED_SECURITY_NO); + } + return extra; + } +#endif protected override string BuildConnectionString(string datasourceName, string userId, string userPassword,string databaseName, string port, string schema, string extra) { StringBuilder connectionString = new StringBuilder(); - string port1 = port!=null ? port.Trim() : ""; + string port1 = port!=null ? port.Trim() : string.Empty; if (!string.IsNullOrEmpty(datasourceName) && port1.Length > 0 && !HasKey(extra, "Data Source")) { connectionString.AppendFormat("Data Source={0},{1};",datasourceName, port1); @@ -1986,10 +2042,27 @@ protected override string BuildConnectionString(string datasourceName, string us { connectionString.AppendFormat("Data Source={0};",datasourceName); } +#if NETCORE + SqlConnectionStringBuilder additionalConnectionString=null; + if (!string.IsNullOrEmpty(extra)) + { + additionalConnectionString = new SqlConnectionStringBuilder(extra); + } + if (userId != null && UserIdAllowed(additionalConnectionString)) + { + connectionString.AppendFormat(";User ID={0}", userId); + } + if (!string.IsNullOrEmpty(userPassword) && UserPasswordAllowed(additionalConnectionString)) + { + connectionString.AppendFormat(";Password={0}", userPassword); + } + extra = ResolveConnectionStringAuthentication(extra, additionalConnectionString); +#else if (userId!=null) { connectionString.AppendFormat(";User ID={0};Password={1}",userId,userPassword); } +#endif if (databaseName != null && databaseName.Trim().Length > 0 && !HasKey(extra, "Database")) { connectionString.AppendFormat(";Database={0}",databaseName); @@ -2015,6 +2088,7 @@ protected override string BuildConnectionString(string datasourceName, string us return connstr; } + #if !NETCORE public override Object Net2DbmsGeo(GXType type, IGeographicNative geo) { diff --git a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj b/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj index 94db46c2f..a2955f0e4 100644 --- a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj +++ b/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj @@ -65,7 +65,7 @@ - + diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj index b6e836963..e5a0c4679 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj @@ -33,12 +33,12 @@
- - - + + + - + diff --git a/dotnet/src/extensions/mocking/test/TestMockDBAccess/TestMockDBAccess.csproj b/dotnet/src/extensions/mocking/test/TestMockDBAccess/TestMockDBAccess.csproj index f0403360c..58c2e3d50 100644 --- a/dotnet/src/extensions/mocking/test/TestMockDBAccess/TestMockDBAccess.csproj +++ b/dotnet/src/extensions/mocking/test/TestMockDBAccess/TestMockDBAccess.csproj @@ -10,7 +10,7 @@ - + diff --git a/dotnet/test/DotNetCoreOpenTelemetryTest/DotNetCoreOpenTelemetryTest.csproj b/dotnet/test/DotNetCoreOpenTelemetryTest/DotNetCoreOpenTelemetryTest.csproj index df172d2e5..15d8fc2c6 100644 --- a/dotnet/test/DotNetCoreOpenTelemetryTest/DotNetCoreOpenTelemetryTest.csproj +++ b/dotnet/test/DotNetCoreOpenTelemetryTest/DotNetCoreOpenTelemetryTest.csproj @@ -1,4 +1,4 @@ - + net6.0 CS8032;1701;1702;NU1701 @@ -15,8 +15,8 @@ - - + + diff --git a/dotnet/test/DotNetCoreUnitTest/Domain/GxConnectionTest.cs b/dotnet/test/DotNetCoreUnitTest/Domain/GxConnectionTest.cs new file mode 100644 index 000000000..88b6fdb90 --- /dev/null +++ b/dotnet/test/DotNetCoreUnitTest/Domain/GxConnectionTest.cs @@ -0,0 +1,53 @@ +using System; +using GeneXus.Data; +using Xunit; + +namespace DotNetCoreUnitTest.Domain +{ + public class GxConnectionTest + { + [Fact] + public void AzureADAuthenticationConnectionString() + { + GxSqlServer sqlserver = new GxSqlServer(); + string server = "localhost"; + string port = "1433"; + string user = "testuser"; + string password = "testpassword"; + string database = "initaldb"; + string additionalConnectionString; + + additionalConnectionString = "Authentication=Active Directory Integrated;"; + string connStr = sqlserver.BuildConnectionStringImpl(server, user, password, database, port, string.Empty, additionalConnectionString); + Assert.DoesNotContain(password, connStr, StringComparison.OrdinalIgnoreCase); + Assert.Contains(user, connStr, StringComparison.OrdinalIgnoreCase); + + additionalConnectionString = "Authentication=Active Directory Interactive;"; + connStr = sqlserver.BuildConnectionStringImpl(server, user, password, database, port, string.Empty, additionalConnectionString); + Assert.DoesNotContain(password, connStr, StringComparison.OrdinalIgnoreCase); + Assert.Contains(user, connStr, StringComparison.OrdinalIgnoreCase); + + additionalConnectionString = "Authentication=Active Directory Service Principal; Encrypt=True;"; + connStr = sqlserver.BuildConnectionStringImpl(server, user, password, database, port, string.Empty, additionalConnectionString); + Assert.Contains(password, connStr, StringComparison.OrdinalIgnoreCase); + Assert.Contains(user, connStr, StringComparison.OrdinalIgnoreCase); + + additionalConnectionString= "Authentication=Active Directory Managed Identity;"; + connStr = sqlserver.BuildConnectionStringImpl(server, user, password, database, port, string.Empty, additionalConnectionString); + Assert.DoesNotContain(password, connStr, StringComparison.OrdinalIgnoreCase); + Assert.Contains(user, connStr, StringComparison.OrdinalIgnoreCase); + + + additionalConnectionString = "Authentication=Active Directory Device Code Flow;"; + connStr = sqlserver.BuildConnectionStringImpl(server, user, password, database, port, string.Empty, additionalConnectionString); + Assert.DoesNotContain(password, connStr, StringComparison.OrdinalIgnoreCase); + Assert.DoesNotContain(user, connStr, StringComparison.OrdinalIgnoreCase); + + additionalConnectionString = "Authentication=Active Directory Integrated;Integrated Security=yes"; + connStr = sqlserver.BuildConnectionStringImpl(server, user, password, database, port, string.Empty, additionalConnectionString); + Assert.Contains("Integrated Security=no", connStr, StringComparison.OrdinalIgnoreCase); + Assert.Contains("Authentication=Active Directory Integrated", connStr, StringComparison.OrdinalIgnoreCase); + + } + } +} diff --git a/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj b/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj index d11494d93..68de38b00 100644 --- a/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj +++ b/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj @@ -53,8 +53,8 @@ - - + + diff --git a/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj b/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj index bac7e207c..ee6046ce5 100644 --- a/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj +++ b/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj @@ -17,8 +17,8 @@ - - + + diff --git a/dotnet/test/ProjectHealthTest/PackageVersionsConsistency.cs b/dotnet/test/ProjectHealthTest/PackageVersionsConsistency.cs index 89848c54b..ad395603d 100644 --- a/dotnet/test/ProjectHealthTest/PackageVersionsConsistency.cs +++ b/dotnet/test/ProjectHealthTest/PackageVersionsConsistency.cs @@ -98,6 +98,17 @@ private void TestPackageVersionConsistencyAcrossProjects(string targetFramework, { foreach (XmlNode packageNode in packagesNodes) { + XmlAttribute condition = packageNode.ParentNode.Attributes["Condition"]; + if (condition != null) { + if (targetFramework == NET6 && condition.Value.Contains($"=='{NET_FRAMEWORK}'", StringComparison.OrdinalIgnoreCase)) + continue; + else if (targetFramework == NET_FRAMEWORK && condition.Value.Contains($"=='{NET6}'", StringComparison.OrdinalIgnoreCase)) + { + continue; + } + + } + if (packageNode.Attributes == null) { continue; From 5976e3ddb0896b0fbcf3e6c7ab5f9d89a58dbacd Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Mon, 28 Aug 2023 13:40:14 -0300 Subject: [PATCH 031/164] Support adding GX logs to telemetry. (#864) * Support adding GX logs to telemetry. --- .../GxNetCoreStartup/GxNetCoreStartup.csproj | 5 ++ .../dotnetcore/GxNetCoreStartup/Startup.cs | 57 ++++++++++++++++--- .../AzureAppInsights.cs | 53 +++++++++++++---- ...Xus.OpenTelemetry.Azure.AppInsights.csproj | 10 +++- .../TestOpenTelemetry.cs | 1 + 5 files changed, 106 insertions(+), 20 deletions(-) diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj b/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj index 525ff717a..3a21abc09 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj @@ -17,6 +17,11 @@ + + + + + diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs index 3495ef6c2..aeb2579df 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs @@ -4,7 +4,10 @@ using System.Collections.Generic; using System.IO; using System.Net; +using System.Runtime.InteropServices; using System.Threading.Tasks; +using Azure.Identity; +using Azure.Monitor.OpenTelemetry.Exporter; using GeneXus.Configuration; using GeneXus.Http; using GeneXus.HttpHandlerFactory; @@ -30,6 +33,8 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Logging; +using OpenTelemetry.Logs; +using OpenTelemetry.Resources; using StackExchange.Redis; @@ -39,6 +44,10 @@ public class Program { const string DEFAULT_PORT = "80"; static string DEFAULT_SCHEMA = Uri.UriSchemeHttp; + + private static string OPENTELEMETRY_SERVICE = "Observability"; + private static string OPENTELEMETRY_AZURE_DISTRO = "GeneXus.OpenTelemetry.Azure.AzureAppInsights"; + private static string APPLICATIONINSIGHTS_CONNECTION_STRING = "APPLICATIONINSIGHTS_CONNECTION_STRING"; public static void Main(string[] args) { try @@ -76,12 +85,12 @@ public static void Main(string[] args) } public static IWebHost BuildWebHost(string[] args) => - WebHost.CreateDefaultBuilder(args) - .ConfigureLogging(logging => logging.AddConsole()) - .UseStartup() - .UseContentRoot(Startup.LocalPath) - .Build(); - + WebHost.CreateDefaultBuilder(args) + .ConfigureLogging(WebHostConfigureLogging) + .UseStartup() + .UseContentRoot(Startup.LocalPath) + .Build(); + public static IWebHost BuildWebHostPort(string[] args, string port) { return BuildWebHostPort(args, port, DEFAULT_SCHEMA); @@ -89,12 +98,46 @@ public static IWebHost BuildWebHostPort(string[] args, string port) static IWebHost BuildWebHostPort(string[] args, string port, string schema) { return WebHost.CreateDefaultBuilder(args) - .ConfigureLogging(logging => logging.AddConsole()) + .ConfigureLogging(WebHostConfigureLogging) .UseUrls($"{schema}://*:{port}") .UseStartup() .UseContentRoot(Startup.LocalPath) .Build(); } + + private static void WebHostConfigureLogging(WebHostBuilderContext hostingContext, ILoggingBuilder loggingBuilder) + { + loggingBuilder.AddConsole(); + GXService providerService = GXServices.Instance?.Get(OPENTELEMETRY_SERVICE); + if (providerService != null && providerService.ClassName.StartsWith(OPENTELEMETRY_AZURE_DISTRO)) + { + ConfigureAzureOpentelemetry(loggingBuilder); + } + } + private static void ConfigureAzureOpentelemetry(ILoggingBuilder loggingBuilder) + { + string endpoint = Environment.GetEnvironmentVariable(APPLICATIONINSIGHTS_CONNECTION_STRING); + var resourceBuilder = ResourceBuilder.CreateDefault() + .AddTelemetrySdk(); + + loggingBuilder.AddOpenTelemetry(loggerOptions => + { + loggerOptions + .SetResourceBuilder(resourceBuilder) + .AddAzureMonitorLogExporter(options => + { + if (!string.IsNullOrEmpty(endpoint)) + options.ConnectionString = endpoint; + else + options.Credential = new DefaultAzureCredential(); + }) + .AddConsoleExporter(); + + loggerOptions.IncludeFormattedMessage = true; + loggerOptions.IncludeScopes = true; + loggerOptions.ParseStateValues = true; + }); + } private static void LocatePhysicalLocalPath() { string startup = FileUtil.GetStartupDirectory(); diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/AzureAppInsights.cs b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/AzureAppInsights.cs index 68e6152ae..5b9a30550 100644 --- a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/AzureAppInsights.cs +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/AzureAppInsights.cs @@ -1,10 +1,15 @@ using System; -using Azure.Monitor.OpenTelemetry.AspNetCore; +using Azure.Identity; +using Azure.Monitor.OpenTelemetry.Exporter; using GeneXus.Services; using GeneXus.Services.OpenTelemetry; using log4net; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; +using OpenTelemetry; +using OpenTelemetry.Logs; +using OpenTelemetry.Metrics; +using OpenTelemetry.Resources; +using OpenTelemetry.Trace; namespace GeneXus.OpenTelemetry.Azure { @@ -17,23 +22,47 @@ public AzureAppInsights(GXService s) { } - public bool InstrumentAspNetCoreApplication(IServiceCollection services) + public bool InstrumentAspNetCoreApplication(IServiceCollection _) { string oltpEndpoint = Environment.GetEnvironmentVariable(APPLICATIONINSIGHTS_CONNECTION_STRING); - - if (!string.IsNullOrEmpty(oltpEndpoint)) + try { - services.AddOpenTelemetry() - .UseAzureMonitor( o => - { + var resourceBuilder = ResourceBuilder.CreateDefault() + .AddTelemetrySdk(); + + Sdk.CreateTracerProviderBuilder() + .SetResourceBuilder(resourceBuilder) + .AddAzureMonitorTraceExporter(o => + { + if (!string.IsNullOrEmpty(oltpEndpoint)) o.ConnectionString = oltpEndpoint; - }); + else + { + o.Credential = new DefaultAzureCredential(); + log.Debug("Connect to Azure monitor Opentelemetry Trace exporter using Default Azure credential"); + } + }) + .AddGxAspNetInstrumentation() + .Build(); + Sdk.CreateMeterProviderBuilder() + .SetResourceBuilder(resourceBuilder) + .AddAzureMonitorMetricExporter(o => + { + if (!string.IsNullOrEmpty(oltpEndpoint)) + o.ConnectionString = oltpEndpoint; + else + { + o.Credential = new DefaultAzureCredential(); + log.Debug("Connect to Azure monitor Opentelemetry Metrics exporter using Default Azure credential"); + } + }) + .Build(); return true; } - else - { - log.Warn("OpenTelemetry Azure Monitor was not initialized due to missing 'APPLICATIONINSIGHTS_CONNECTION_STRING' Environment Variable"); + catch (Exception ex) + { + log.Warn("Azure Monitor Opentelemetry could not be initialized. " + ex.Message); return false; } } diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/GeneXus.OpenTelemetry.Azure.AppInsights.csproj b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/GeneXus.OpenTelemetry.Azure.AppInsights.csproj index f8d09b91f..26bbe19b1 100644 --- a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/GeneXus.OpenTelemetry.Azure.AppInsights.csproj +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/GeneXus.OpenTelemetry.Azure.AppInsights.csproj @@ -10,7 +10,15 @@ NU1605 - + + + + + + + + + diff --git a/dotnet/test/DotNetCoreOpenTelemetryTest/TestOpenTelemetry.cs b/dotnet/test/DotNetCoreOpenTelemetryTest/TestOpenTelemetry.cs index f78172a7a..11f71c618 100644 --- a/dotnet/test/DotNetCoreOpenTelemetryTest/TestOpenTelemetry.cs +++ b/dotnet/test/DotNetCoreOpenTelemetryTest/TestOpenTelemetry.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using GeneXus.Configuration; using GeneXus.Metadata; +using Microsoft.Extensions.Logging; using Xunit; using xUnitTesting; From 46408d68049eb0aa3ac8d93b5ea0201b894eaddd Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Mon, 28 Aug 2023 15:28:17 -0300 Subject: [PATCH 032/164] Specify SameSite mode for X-GXCSRF-TOKEN cookie. (#868) --- dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs index aeb2579df..4c91d228c 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs @@ -674,9 +674,15 @@ public async Task Invoke(HttpContext context) internal static void SetAntiForgeryTokens(IAntiforgery _antiforgery, HttpContext context) { AntiforgeryTokenSet tokenSet = _antiforgery.GetAndStoreTokens(context); - context.Response.Cookies.Append(HttpHeader.X_GXCSRF_TOKEN, tokenSet.RequestToken, - new CookieOptions { HttpOnly = false, Secure = GxContext.GetHttpSecure(context) == 1 }); - GXLogging.Debug(log, $"Setting cookie ", HttpHeader.X_GXCSRF_TOKEN, "=", tokenSet.RequestToken); + string sameSite; + CookieOptions cookieOptions = new CookieOptions { HttpOnly = false, Secure = GxContext.GetHttpSecure(context) == 1 }; + SameSiteMode sameSiteMode= SameSiteMode.Unspecified; + if (Config.GetValueOf("SAMESITE_COOKIE", out sameSite) && Enum.TryParse(sameSite, out sameSiteMode)) + { + cookieOptions.SameSite = sameSiteMode; + } + context.Response.Cookies.Append(HttpHeader.X_GXCSRF_TOKEN, tokenSet.RequestToken, cookieOptions); + GXLogging.Debug(log, $"Setting cookie ", HttpHeader.X_GXCSRF_TOKEN, "=", tokenSet.RequestToken, " samesite:" + sameSiteMode); } } From 246d469fa85ca835411afe33c0bf73834a8319b8 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 30 Aug 2023 07:15:42 -0300 Subject: [PATCH 033/164] Set domain for X-GXCSRF-TOKEN cookie to the referer domain. (#869) --- dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs index 4c91d228c..c1d0eebd6 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs @@ -681,8 +681,13 @@ internal static void SetAntiForgeryTokens(IAntiforgery _antiforgery, HttpContext { cookieOptions.SameSite = sameSiteMode; } + Uri referer = context.Request.GetUrlReferrer(); + if (referer != null) + { + cookieOptions.Domain = referer.Host; + } context.Response.Cookies.Append(HttpHeader.X_GXCSRF_TOKEN, tokenSet.RequestToken, cookieOptions); - GXLogging.Debug(log, $"Setting cookie ", HttpHeader.X_GXCSRF_TOKEN, "=", tokenSet.RequestToken, " samesite:" + sameSiteMode); + GXLogging.Debug(log, $"Setting cookie ", HttpHeader.X_GXCSRF_TOKEN, "=", tokenSet.RequestToken, " samesite:" + sameSiteMode, " domain:" + cookieOptions.Domain); } } From fb86dc59c88f6a1e732b4e5c6f222698ab416562 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 30 Aug 2023 12:20:08 -0300 Subject: [PATCH 034/164] Skip CLRF in the first post parameter of a multipart form data. (#867) --- .../GxClasses/Domain/GxHttpClient.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs index debd2d04b..0ba575f00 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs @@ -41,6 +41,7 @@ public class MultiPartTemplate { public string Boundary; public string FormdataTemplate; + public string FormdataSeparator; public byte[] Boundarybytes; public byte[] EndBoundaryBytes; public string HeaderTemplate; @@ -50,7 +51,8 @@ internal MultiPartTemplate() { Boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x"); ContentType = $"multipart/form-data; boundary={Boundary}"; - FormdataTemplate = "\r\n--" + Boundary + "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}"; + FormdataSeparator = "\r\n"; + FormdataTemplate = "--" + Boundary + "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}"; Boundarybytes = Encoding.ASCII.GetBytes($"\r\n--{Boundary}\r\n"); EndBoundaryBytes = Encoding.ASCII.GetBytes($"\r\n--{Boundary}--"); HeaderTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" + "Content-Type: {2}\r\n\r\n"; @@ -431,7 +433,7 @@ void SendVariables(Stream reqStream) for (int i = 0; i < _formVars.Count; i++) { if (_formVars.Keys[i] != null) - vars.Add(buildVariableToSend(_formVars.Keys[i], _formVars[i])); + vars.Add(buildVariableToSend(_formVars.Keys[i], _formVars[i], vars.Count)); } if (vars.Count > 0) { @@ -457,11 +459,15 @@ string variableSeparator() else return "&"; } - string buildVariableToSend(string key, string value) + string buildVariableToSend(string key, string value, int idx) { + bool needsCLRF = idx > 0; if (IsMultipart) { - return string.Format(MultiPart.FormdataTemplate, key, value); + if (needsCLRF) + return MultiPart.FormdataSeparator + string.Format(MultiPart.FormdataTemplate, key, value); + else + return string.Format(MultiPart.FormdataTemplate, key, value); } else { From 4959fe12f418a06b7d3671a252b306d052fcebed Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Thu, 31 Aug 2023 09:46:45 -0300 Subject: [PATCH 035/164] Restore default domain for X-GXCSRF-TOKEN cookie. (#870) --- dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs index c1d0eebd6..4c91d228c 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs @@ -681,13 +681,8 @@ internal static void SetAntiForgeryTokens(IAntiforgery _antiforgery, HttpContext { cookieOptions.SameSite = sameSiteMode; } - Uri referer = context.Request.GetUrlReferrer(); - if (referer != null) - { - cookieOptions.Domain = referer.Host; - } context.Response.Cookies.Append(HttpHeader.X_GXCSRF_TOKEN, tokenSet.RequestToken, cookieOptions); - GXLogging.Debug(log, $"Setting cookie ", HttpHeader.X_GXCSRF_TOKEN, "=", tokenSet.RequestToken, " samesite:" + sameSiteMode, " domain:" + cookieOptions.Domain); + GXLogging.Debug(log, $"Setting cookie ", HttpHeader.X_GXCSRF_TOKEN, "=", tokenSet.RequestToken, " samesite:" + sameSiteMode); } } From 60da3b399546733d9553e2285ff2f1d3caae5427 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Thu, 14 Sep 2023 17:43:52 -0300 Subject: [PATCH 036/164] Bind CSRF token to session id for .NET. (#872) * Bind CSRF token to session id for .NET. Move VerificationToken service to root path (rest/) * New sessions must not validate session data bound to CSRF token. * Remove session binding to the CSRF token, as it is unnecessary for serverless services on the backend. --- .../dotnetcore/GxNetCoreStartup/CsrfHelper.cs | 65 +++++++++++++++++ .../dotnetcore/GxNetCoreStartup/Startup.cs | 73 +------------------ .../GxClasses/Helpers/CsrfHelper.cs | 53 ++++++++++++++ .../GxClasses/Helpers/HttpHelper.cs | 3 +- .../GxClasses/Middleware/GXHttpModules.cs | 5 ++ .../GxClasses/Services/GXRestServices.cs | 40 +--------- .../Middleware/RestServiceTest.cs | 8 +- 7 files changed, 134 insertions(+), 113 deletions(-) create mode 100644 dotnet/src/dotnetcore/GxNetCoreStartup/CsrfHelper.cs create mode 100644 dotnet/src/dotnetframework/GxClasses/Helpers/CsrfHelper.cs diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/CsrfHelper.cs b/dotnet/src/dotnetcore/GxNetCoreStartup/CsrfHelper.cs new file mode 100644 index 000000000..4005ca78a --- /dev/null +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/CsrfHelper.cs @@ -0,0 +1,65 @@ + + +using System; +using System.Threading.Tasks; +using GeneXus.Configuration; +using GeneXus.Http; +using log4net; +using Microsoft.AspNetCore.Antiforgery; +using Microsoft.AspNetCore.Http; +namespace GeneXus.Application +{ + public class ValidateAntiForgeryTokenMiddleware + { + static readonly ILog log = log4net.LogManager.GetLogger(typeof(ValidateAntiForgeryTokenMiddleware)); + + private readonly RequestDelegate _next; + private readonly IAntiforgery _antiforgery; + private string _basePath; + + public ValidateAntiForgeryTokenMiddleware(RequestDelegate next, IAntiforgery antiforgery, String basePath) + { + _next = next; + _antiforgery = antiforgery; + _basePath = "/" + basePath; + } + + public async Task Invoke(HttpContext context) + { + if (context.Request.Path.HasValue && context.Request.Path.Value.StartsWith(_basePath)) + { + if (HttpMethods.IsPost(context.Request.Method) || + HttpMethods.IsDelete(context.Request.Method) || + HttpMethods.IsPut(context.Request.Method)) + { + string cookieToken = context.Request.Cookies[HttpHeader.X_CSRF_TOKEN_COOKIE]; + string headerToken = context.Request.Headers[HttpHeader.X_CSRF_TOKEN_HEADER]; + GXLogging.Debug(log, $"Antiforgery validation, cookieToken:{cookieToken}, headerToken:{headerToken}"); + + await _antiforgery.ValidateRequestAsync(context); + GXLogging.Debug(log, $"Antiforgery validation OK"); + } + else if (HttpMethods.IsGet(context.Request.Method)) + { + SetAntiForgeryTokens(_antiforgery, context); + } + } + if (!context.Request.Path.Value.EndsWith(_basePath)) //VerificationToken + await _next(context); + } + internal static void SetAntiForgeryTokens(IAntiforgery _antiforgery, HttpContext context) + { + AntiforgeryTokenSet tokenSet = _antiforgery.GetAndStoreTokens(context); + string sameSite; + CookieOptions cookieOptions = new CookieOptions { HttpOnly = false, Secure = GxContext.GetHttpSecure(context) == 1 }; + SameSiteMode sameSiteMode = SameSiteMode.Unspecified; + if (Config.GetValueOf("SAMESITE_COOKIE", out sameSite) && Enum.TryParse(sameSite, out sameSiteMode)) + { + cookieOptions.SameSite = sameSiteMode; + } + context.Response.Cookies.Append(HttpHeader.X_CSRF_TOKEN_COOKIE, tokenSet.RequestToken, cookieOptions); + GXLogging.Debug(log, $"Setting cookie ", HttpHeader.X_CSRF_TOKEN_COOKIE, "=", tokenSet.RequestToken, " samesite:" + sameSiteMode); + } + + } +} diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs index 4c91d228c..f9620a042 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs @@ -1,10 +1,7 @@ - - using System; using System.Collections.Generic; using System.IO; using System.Net; -using System.Runtime.InteropServices; using System.Threading.Tasks; using Azure.Identity; using Azure.Monitor.OpenTelemetry.Exporter; @@ -253,7 +250,7 @@ public void ConfigureServices(IServiceCollection services) { services.AddAntiforgery(options => { - options.HeaderName = HttpHeader.X_GXCSRF_TOKEN; + options.HeaderName = HttpHeader.X_CSRF_TOKEN_HEADER; options.SuppressXFrameOptionsHeader = false; }); } @@ -460,20 +457,10 @@ public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHos routes.MapRoute($"{s}", new RequestDelegate(gxRouting.ProcessRestRequest)); } } - routes.MapRoute($"{restBasePath}VerificationToken", (context) => - { - string requestPath = context.Request.Path.Value; - - if (string.Equals(requestPath, $"/{restBasePath}VerificationToken", StringComparison.OrdinalIgnoreCase) && antiforgery!=null) - { - ValidateAntiForgeryTokenMiddleware.SetAntiForgeryTokens(antiforgery, context); - } - return Task.CompletedTask; - }); routes.MapRoute($"{restBasePath}{{*{UrlTemplateControllerWithParms}}}", new RequestDelegate(gxRouting.ProcessRestRequest)); routes.MapRoute("Default", VirtualPath, new { controller = "Home", action = "Index" }); }); - + app.UseWebSockets(); string basePath = string.IsNullOrEmpty(VirtualPath) ? string.Empty : $"/{VirtualPath}"; Config.ScriptPath = basePath; @@ -630,60 +617,4 @@ public IActionResult Index() return Redirect(defaultFiles[0]); } } - public class ValidateAntiForgeryTokenMiddleware - { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(ValidateAntiForgeryTokenMiddleware)); - - private readonly RequestDelegate _next; - private readonly IAntiforgery _antiforgery; - private string _basePath; - - public ValidateAntiForgeryTokenMiddleware(RequestDelegate next, IAntiforgery antiforgery, String basePath) - { - _next = next; - _antiforgery = antiforgery; - _basePath = "/" + basePath; - } - - public async Task Invoke(HttpContext context) - { - if (context.Request.Path.HasValue && context.Request.Path.Value.StartsWith(_basePath)) - { - if (HttpMethods.IsPost(context.Request.Method) || - HttpMethods.IsDelete(context.Request.Method) || - HttpMethods.IsPut(context.Request.Method)) - { - string cookieToken = context.Request.Cookies[HttpHeader.X_GXCSRF_TOKEN]; - string headerToken = context.Request.Headers[HttpHeader.X_GXCSRF_TOKEN]; - GXLogging.Debug(log, $"Antiforgery validation, cookieToken:{cookieToken}, headerToken:{headerToken}"); - - await _antiforgery.ValidateRequestAsync(context); - GXLogging.Debug(log, $"Antiforgery validation OK"); - } - else if (HttpMethods.IsGet(context.Request.Method)) - { - string tokens = context.Request.Cookies[HttpHeader.X_GXCSRF_TOKEN]; - if (string.IsNullOrEmpty(tokens)) - { - SetAntiForgeryTokens(_antiforgery, context); - } - } - } - await _next(context); - } - internal static void SetAntiForgeryTokens(IAntiforgery _antiforgery, HttpContext context) - { - AntiforgeryTokenSet tokenSet = _antiforgery.GetAndStoreTokens(context); - string sameSite; - CookieOptions cookieOptions = new CookieOptions { HttpOnly = false, Secure = GxContext.GetHttpSecure(context) == 1 }; - SameSiteMode sameSiteMode= SameSiteMode.Unspecified; - if (Config.GetValueOf("SAMESITE_COOKIE", out sameSite) && Enum.TryParse(sameSite, out sameSiteMode)) - { - cookieOptions.SameSite = sameSiteMode; - } - context.Response.Cookies.Append(HttpHeader.X_GXCSRF_TOKEN, tokenSet.RequestToken, cookieOptions); - GXLogging.Debug(log, $"Setting cookie ", HttpHeader.X_GXCSRF_TOKEN, "=", tokenSet.RequestToken, " samesite:" + sameSiteMode); - } - - } } diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/CsrfHelper.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/CsrfHelper.cs new file mode 100644 index 000000000..f2b346659 --- /dev/null +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/CsrfHelper.cs @@ -0,0 +1,53 @@ +using System.Net.Http; +using System.Security; +using System.Web; +using System.Web.Helpers; +using GeneXus.Application; +using GeneXus.Utils; + +namespace GeneXus.Http +{ + internal class CSRFHelper + { + [SecuritySafeCritical] + internal static void ValidateAntiforgery(HttpContext context) + { + if (RestAPIHelpers.ValidateCsrfToken()) + { + ValidateAntiforgeryImpl(context); + } + } + [SecurityCritical] + static void ValidateAntiforgeryImpl(HttpContext context) + { + string cookieToken, formToken; + string httpMethod = context.Request.HttpMethod; + string tokens = context.Request.Cookies[HttpHeader.X_CSRF_TOKEN_COOKIE]?.Value; + string internalCookieToken = context.Request.Cookies[HttpHeader.X_CSRF_TOKEN_COOKIE]?.Value; + if (httpMethod == HttpMethod.Get.Method && (string.IsNullOrEmpty(tokens) || string.IsNullOrEmpty(internalCookieToken))) + { + AntiForgery.GetTokens(null, out cookieToken, out formToken); +#pragma warning disable SCS0009 // The cookie is missing security flag HttpOnly + HttpCookie cookie = new HttpCookie(HttpHeader.X_CSRF_TOKEN_COOKIE, formToken) + { + HttpOnly = false, + Secure = GxContext.GetHttpSecure(context) == 1, + }; +#pragma warning restore SCS0009 // The cookie is missing security flag HttpOnly + HttpCookie internalCookie = new HttpCookie(AntiForgeryConfig.CookieName, cookieToken) + { + HttpOnly = true, + Secure = GxContext.GetHttpSecure(context) == 1, + }; + context.Response.SetCookie(cookie); + context.Response.SetCookie(internalCookie); + } + if (httpMethod == HttpMethod.Delete.Method || httpMethod == HttpMethod.Post.Method || httpMethod == HttpMethod.Put.Method) + { + cookieToken = context.Request.Cookies[AntiForgeryConfig.CookieName]?.Value; + string headerToken = context.Request.Headers[HttpHeader.X_CSRF_TOKEN_HEADER]; + AntiForgery.Validate(cookieToken, headerToken); + } + } + } +} diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs index 4fd91c649..213448533 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs @@ -50,7 +50,8 @@ public class HttpHeader public static string XGXFILENAME = "x-gx-filename"; internal static string ACCEPT = "Accept"; internal static string TRANSFER_ENCODING = "Transfer-Encoding"; - internal static string X_GXCSRF_TOKEN = "X-GXCSRF-TOKEN"; + internal static string X_CSRF_TOKEN_HEADER = "X-XSRF-TOKEN"; + internal static string X_CSRF_TOKEN_COOKIE = "XSRF-TOKEN"; } internal class HttpHeaderValue { diff --git a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpModules.cs b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpModules.cs index 98ffd93e3..0398b09dd 100644 --- a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpModules.cs +++ b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpModules.cs @@ -86,6 +86,11 @@ private void onPostResolveRequestCache(object sender, EventArgs eventArgs) if (apiHandler != null) HttpContext.Current.RemapHandler(apiHandler); } + else if (string.Equals(HttpContext.Current.Request.HttpMethod, HttpMethod.Get.Method, StringComparison.OrdinalIgnoreCase) && + HttpContext.Current.Request.Path.EndsWith("/" + REST_BASE_URL, StringComparison.OrdinalIgnoreCase)) + { + CSRFHelper.ValidateAntiforgery(HttpContext.Current); + } } void IHttpModule.Dispose() { diff --git a/dotnet/src/dotnetframework/GxClasses/Services/GXRestServices.cs b/dotnet/src/dotnetframework/GxClasses/Services/GXRestServices.cs index e13ebb200..9eb75a4d3 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/GXRestServices.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/GXRestServices.cs @@ -558,11 +558,8 @@ void AddHeader(string header, string value) [SecuritySafeCritical] public bool ProcessHeaders(string queryId) { - if (RestAPIHelpers.ValidateCsrfToken()) - { - ValidateAntiforgery(); - } - + CSRFHelper.ValidateAntiforgery(context.HttpContext); + NameValueCollection headers = GetHeaders(); String language = null, theme = null, etag = null; if (headers != null) @@ -601,38 +598,7 @@ public bool ProcessHeaders(string queryId) return true; } - [SecurityCritical] - private void ValidateAntiforgery() - { - string cookieToken, formToken; - string httpMethod = context.HttpContext.Request.HttpMethod; - string tokens = context.HttpContext.Request.Cookies[HttpHeader.X_GXCSRF_TOKEN]?.Value; - string internalCookieToken = context.HttpContext.Request.Cookies[HttpHeader.X_GXCSRF_TOKEN]?.Value; - if (httpMethod == HttpMethod.Get.Method && (string.IsNullOrEmpty(tokens) || string.IsNullOrEmpty(internalCookieToken))) - { - AntiForgery.GetTokens(null, out cookieToken, out formToken); -#pragma warning disable SCS0009 // The cookie is missing security flag HttpOnly - HttpCookie cookie = new HttpCookie(HttpHeader.X_GXCSRF_TOKEN, formToken) - { - HttpOnly = false, - Secure = context.GetHttpSecure() == 1, - }; -#pragma warning restore SCS0009 // The cookie is missing security flag HttpOnly - HttpCookie internalCookie = new HttpCookie(AntiForgeryConfig.CookieName, cookieToken) - { - HttpOnly = true, - Secure = context.GetHttpSecure() == 1, - }; - context.HttpContext.Response.SetCookie(cookie); - context.HttpContext.Response.SetCookie(internalCookie); - } - if (httpMethod == HttpMethod.Delete.Method || httpMethod == HttpMethod.Post.Method || httpMethod == HttpMethod.Put.Method) - { - cookieToken = context.HttpContext.Request.Cookies[AntiForgeryConfig.CookieName]?.Value; - string headerToken = context.HttpContext.Request.Headers[HttpHeader.X_GXCSRF_TOKEN]; - AntiForgery.Validate(cookieToken, headerToken); - } - } + private void SendCacheHeaders() { diff --git a/dotnet/test/DotNetCoreAttackMitigationTest/Middleware/RestServiceTest.cs b/dotnet/test/DotNetCoreAttackMitigationTest/Middleware/RestServiceTest.cs index 7c74cb07e..3c292308a 100644 --- a/dotnet/test/DotNetCoreAttackMitigationTest/Middleware/RestServiceTest.cs +++ b/dotnet/test/DotNetCoreAttackMitigationTest/Middleware/RestServiceTest.cs @@ -53,14 +53,14 @@ public async Task RunController() foreach (var item in SetCookieHeaderValue.ParseList(values.ToList())) cookies.Add(requestUriObj, new Cookie(item.Name.Value, item.Value.Value, item.Path.Value)); - var setCookie = SetCookieHeaderValue.ParseList(values.ToList()).FirstOrDefault(t => t.Name.Equals(HttpHeader.X_GXCSRF_TOKEN, StringComparison.OrdinalIgnoreCase)); + var setCookie = SetCookieHeaderValue.ParseList(values.ToList()).FirstOrDefault(t => t.Name.Equals(HttpHeader.X_CSRF_TOKEN_COOKIE, StringComparison.OrdinalIgnoreCase)); csrfToken = setCookie.Value.Value; response.EnsureSuccessStatusCode(); Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); //When failed, turn on log.config to see server side error. StringContent body = new StringContent("{\"Image\":\"imageName\",\"ImageDescription\":\"imageDescription\"}"); - client.DefaultRequestHeaders.Add(HttpHeader.X_GXCSRF_TOKEN, csrfToken); + client.DefaultRequestHeaders.Add(HttpHeader.X_CSRF_TOKEN_HEADER, csrfToken); client.DefaultRequestHeaders.Add("Cookie", values);// //cookies.GetCookieHeader(requestUriObj)); response = await client.PostAsync("rest/apps/saveimage", body); @@ -74,7 +74,7 @@ public async Task HttpFirstPost() IEnumerable cookies = response.Headers.SingleOrDefault(header => header.Key == "Set-Cookie").Value; foreach (string cookie in cookies) { - Assert.False(cookie.StartsWith(HttpHeader.X_GXCSRF_TOKEN)); + Assert.False(cookie.StartsWith(HttpHeader.X_CSRF_TOKEN_COOKIE)); } response.EnsureSuccessStatusCode(); Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); @@ -87,7 +87,7 @@ public async Task HttpFirstGet() IEnumerable cookies = response.Headers.SingleOrDefault(header => header.Key == "Set-Cookie").Value; foreach (string cookie in cookies) { - Assert.False(cookie.StartsWith(HttpHeader.X_GXCSRF_TOKEN)); + Assert.False(cookie.StartsWith(HttpHeader.X_CSRF_TOKEN_COOKIE)); } response.EnsureSuccessStatusCode(); From c91f4c3208622a656a64c2164c1e2e7bae4b4f83 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Fri, 15 Sep 2023 11:07:47 -0300 Subject: [PATCH 037/164] Enable RecordCount retrieval in data provider for grid panel (#843) * Temporary implementation to enable RecordCount retrieval in data provider for grid panel. * Define the GXDataGridProcedure class as the base class for REST services handling panels with data grids. * Set the 'RecordCount' header when the 'RecordCount' routine is executed, regardless of whether 'RecordCount' is present in the request headers. * Set RecordCountSupported when RecorCount is not available. * RecordCount header must be set before opening cursor for loading data because it executes a stmt. Otherwise, it should be done after closing cursors. * Remove unused using. --- .../dotnetframework/GxClasses/Model/gxproc.cs | 79 +++++++++++++++++++ .../GxClasses/Services/GxRestWrapper.cs | 2 +- 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs b/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs index 7ec76f78e..e21304972 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs @@ -349,7 +349,86 @@ protected void initialize(int objClass, int objId, int dbgLines, long hash) protected void trkrng(int lineNro, int lineNro2) => dbgInfo?.TrkRng(lineNro, 0, lineNro2, 0); protected void trkrng(int lineNro, int colNro, int lineNro2, int colNro2) => dbgInfo?.TrkRng(lineNro, colNro, lineNro2, colNro2); } + public class GXDataGridProcedure : GXProcedure + { + static readonly ILog log = log4net.LogManager.GetLogger(typeof(GXDataGridProcedure)); + + const string HAS_NEXT_PAGE = "HasNextPage"; + const string RECORD_COUNT = "RecordCount"; + const string RECORD_COUNT_SUPPORTED = "RecordCountSupported"; + long totalRecordCount = -1; + protected virtual long RecordCount() + { + return -1; + } + protected virtual bool RecordCountSupported() + { + return true; + } + protected void SetPaginationHeaders(bool hasNextPage) + { + try + { + SetHasNextPageHeader(hasNextPage); + SetRecordCountSupportedHeader(); + } + catch (Exception ex) + { + GXLogging.Warn(log, $"A processing error occurred while setting pagination headers", ex); + } + } + private void SetRecordCountSupportedHeader() + { + if (!RecordCountSupported()) + { + GXLogging.Debug(log, $"Adding '{RECORD_COUNT_SUPPORTED}' header"); + context.SetHeader(RECORD_COUNT_SUPPORTED, false.ToString()); + } + } + private void SetHasNextPageHeader(bool hasNextPage) + { + context.SetHeader(HAS_NEXT_PAGE, StringUtil.BoolToStr(hasNextPage)); + } + + private void SetRecordCountHeader() + { + bool recordCountHeaderRequired = false; + bool setHeader = false; + if (context.HttpContext != null) + { + recordCountHeaderRequired = !string.IsNullOrEmpty(context.HttpContext.Request.Headers[RECORD_COUNT]); + } + if (totalRecordCount != -1) + { + setHeader = true; + } + else if (recordCountHeaderRequired) + { + totalRecordCount = RecordCount(); + setHeader = true; + } + if (setHeader) + { + GXLogging.Debug(log, $"Adding '{RECORD_COUNT}' header:", totalRecordCount.ToString()); + context.SetHeader(RECORD_COUNT, totalRecordCount.ToString()); + } + } + protected long GetPaginationStart(long start, long count) + { + if (start < 0) //last page + { + totalRecordCount = RecordCount(); + long lastPageRecords = totalRecordCount % count; + if (lastPageRecords == 0) + start = totalRecordCount - count; + else + start = totalRecordCount - lastPageRecords; + } + SetRecordCountHeader(); + return start; + } + } public class GxReportUtils { public static int OUTPUT_RVIEWER_NATIVE = 1; diff --git a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs index c0b1c6a74..ff903a67f 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs @@ -709,7 +709,7 @@ string dateTimeToHTMLDate(DateTime dt) } public Task WebException(Exception ex) { -#if NETCORE +#if NETCORE GxHttpActivitySourceHelper.SetException(Activity.Current, ex); #endif GXLogging.Error(log, "WebException", ex); From 2d21345cc191e0a9335189f71e519a7d29e0dd6f Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Fri, 15 Sep 2023 11:50:23 -0300 Subject: [PATCH 038/164] Fix syntax error when executing stored procedures in MySQL using mysqlconnector. (#873) --- .../GxClasses/Data/GXDataMysqlConnector.cs | 43 ++++++------------- .../GxClasses/Domain/GxCollections.cs | 6 ++- 2 files changed, 17 insertions(+), 32 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlConnector.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlConnector.cs index 14ed3a8be..1b4470a85 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlConnector.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlConnector.cs @@ -1,26 +1,25 @@ +using System; +using System.Data; +using System.Data.Common; +using System.Linq; +using System.Reflection; +using System.Security; +using System.Text; using GeneXus.Application; using GeneXus.Cache; using GeneXus.Utils; +using GxClasses.Helpers; using log4net; using MySQLCommand = MySqlConnector.MySqlCommand; -using MySQLParameter = MySqlConnector.MySqlParameter; using MySQLConnection = MySqlConnector.MySqlConnection; -using MySQLException = MySqlConnector.MySqlException; -using MySQLDbType = MySqlConnector.MySqlDbType; using MySQLDataAdapter = MySqlConnector.MySqlDataAdapter; -using System.IO; -using GxClasses.Helpers; -using System.Reflection; -using System; -using System.Data; -using System.Data.Common; -using System.Text; -using System.Collections.Generic; -using System.Security; +using MySQLDbType = MySqlConnector.MySqlDbType; +using MySQLException = MySqlConnector.MySqlException; +using MySQLParameter = MySqlConnector.MySqlParameter; namespace GeneXus.Data { - + public class GxMySqlConnector : GxDataRecord { static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Data.GxMySqlConnector)); @@ -49,27 +48,9 @@ public override GxAbstractConnectionWrapper GetConnection(bool showPrompt, strin return new MySqlConnectorConnectionWrapper(m_connectionString, connectionCache, isolationLevel); } - string convertToMySqlCall(string stmt, GxParameterCollection parameters) - { - if (parameters == null) - return ""; - string pname; - StringBuilder sBld = new StringBuilder(); - for (int i = 0; i < parameters.Count; i++) - { - if (i > 0) - sBld.Append(", "); - pname = "@" + parameters[i].ParameterName; - sBld.Append(pname); - parameters[i].ParameterName = pname; - } - return "CALL " + stmt + "(" + sBld.ToString() + ")"; - } [SecuritySafeCritical] public override IDbCommand GetCommand(IGxConnection con, string stmt, GxParameterCollection parameters, bool isCursor, bool forFirst, bool isRpc) { - if (isRpc) - stmt = convertToMySqlCall(stmt, parameters); MySQLCommand mysqlcmd = (MySQLCommand)base.GetCommand(con, stmt, parameters.Distinct()); if (isCursor && !isRpc) { diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs index 6da308291..e1484d23d 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs @@ -60,7 +60,10 @@ public int Add(IDataParameter value) { return parameters.Add(value); } - + internal void Reverse() + { + parameters.Reverse(); + } public void Clear() { parameters.Clear(); @@ -158,6 +161,7 @@ public GxParameterCollection Distinct() parms.Add(this[j].ParameterName); } } + uniqueParms.Reverse(); return uniqueParms; } else From 431076640e4f16471ed0d7efbc8c6cbc31fa05ff Mon Sep 17 00:00:00 2001 From: Alejandro Panizza Carve Date: Sat, 23 Sep 2023 20:45:56 -0300 Subject: [PATCH 039/164] - Fix dispatch of PUT Services in NET Core when the Restpath is duplicate and has path variables. Issue 104881 (#876) --- .../src/dotnetframework/GxClasses/Middleware/HandlerFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Middleware/HandlerFactory.cs b/dotnet/src/dotnetframework/GxClasses/Middleware/HandlerFactory.cs index b945d0df5..a16733d35 100644 --- a/dotnet/src/dotnetframework/GxClasses/Middleware/HandlerFactory.cs +++ b/dotnet/src/dotnetframework/GxClasses/Middleware/HandlerFactory.cs @@ -208,7 +208,7 @@ public bool GetSMap(string actualPath, string objectName, string objectNameUp, { foreach (SingleMap m in GXAPIModule.servicesMap[actualPath].Values) { - if (!m.Path.Equals(m.PathRegexp) && GxRegex.IsMatch(objectName, m.PathRegexp)) + if (!m.Path.Equals(m.PathRegexp) && GxRegex.IsMatch(objectName, m.PathRegexp) && m.Verb.Equals(requestType)) { mapName = m.Name; routeParms = new Dictionary(); From 692396a6bbd68f7aee7e099453008d4898376c45 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 4 Oct 2023 12:30:09 -0300 Subject: [PATCH 040/164] Add support for itext8 and .NET (#828) * Add support for itext8 and .NET * HTML and Image rendering fixes * Resolve merge with master and PDFA implementation. * Fixed text wrapping * Fixed justification error and code cleanup * Code cleanup * Register font provider for HTML elements. Rename PDFReportItext7 to PDFReportItext8 * Remove unused fontProvider parameter. * Set fontProvider for document. Reorder ProcessHTMLElement conditions. * Removed manual right alignment of list block element * Avoid unnecessary casts. * Some of the
elements generated by HtmlConverter.ConvertToElements do not contain any child elements; instead, they solely contain formatting properties (e.g.,

, horizontal rule
). Rendering these
elements results in a format closer to the original HTML. However, these changes mean that if a
extends beyond the available drawing area, it won't be displayed. This was the previous behavior. * Remove unused using. * Remove unused usings. * Improve HTML rendering. Break page for long HTMLs. * Add new test case for SAC# 47946 * The iText dependency needs to be added to DependencyContext.Default so that iText can locate resources like iText.IO.Font.Cmap.cjk_registry.properties when searching within DependencyContext.Default.GetRuntimeAssemblyNames(runtimeIdentifier). --------- Co-authored-by: tomas-sexenian --- dotnet/DotNetStandardClasses.sln | 7 + .../GxNetCoreStartup/GxNetCoreStartup.csproj | 5 + .../GxPdfReportsCS/GlobalSuppressions.cs | 2 + .../GxPdfReportsCS/GxPdfReportsCS.csproj | 10 +- .../GxPdfReportsCS/PDFReportItext8.cs | 1332 +++++++++++++ .../GxClasses/Core/gxconfig.cs | 23 + .../dotnetframework/GxClasses/Model/gxproc.cs | 6 +- .../{PDFReportItext.cs => PDFReportCommon.cs} | 1714 ++--------------- .../GxPdfReportsCS/PDFReportItext4.cs | 1539 +++++++++++++++ .../GxPdfReportsCS/PdfReportInterface.cs | 3 +- .../DotNetCoreUnitTest.csproj | 1 + .../DotNetPdfTest/DotNetPDFUnitTest.csproj | 53 + dotnet/test/DotNetPdfTest/PDFReport.ini | 30 + dotnet/test/DotNetPdfTest/PDFTests.cs | 35 + dotnet/test/DotNetPdfTest/adatos.cs | 191 ++ dotnet/test/DotNetPdfTest/apdfformat.cs | 232 +++ dotnet/test/DotNetPdfTest/apdfformats2.cs | 222 +++ dotnet/test/DotNetPdfTest/appsettings.json | 66 + dotnet/test/DotNetPdfTest/longHtml.cs | 248 +++ .../type_SdtFCKTstCollection_FCKTst.cs | 268 +++ .../test/DotNetUnitTest/PDF/apdfbasictest.cs | 131 +- 21 files changed, 4477 insertions(+), 1641 deletions(-) create mode 100644 dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportItext8.cs rename dotnet/src/dotnetframework/GxPdfReportsCS/{PDFReportItext.cs => PDFReportCommon.cs} (51%) create mode 100644 dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext4.cs create mode 100644 dotnet/test/DotNetPdfTest/DotNetPDFUnitTest.csproj create mode 100644 dotnet/test/DotNetPdfTest/PDFReport.ini create mode 100644 dotnet/test/DotNetPdfTest/PDFTests.cs create mode 100644 dotnet/test/DotNetPdfTest/adatos.cs create mode 100644 dotnet/test/DotNetPdfTest/apdfformat.cs create mode 100644 dotnet/test/DotNetPdfTest/apdfformats2.cs create mode 100644 dotnet/test/DotNetPdfTest/appsettings.json create mode 100644 dotnet/test/DotNetPdfTest/longHtml.cs create mode 100644 dotnet/test/DotNetPdfTest/type_SdtFCKTstCollection_FCKTst.cs diff --git a/dotnet/DotNetStandardClasses.sln b/dotnet/DotNetStandardClasses.sln index 00009ab39..cab5bac35 100644 --- a/dotnet/DotNetStandardClasses.sln +++ b/dotnet/DotNetStandardClasses.sln @@ -249,6 +249,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GXAzureEventGrid", "src\dot EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetCoreAttackMitigationTest", "test\DotNetCoreAttackMitigationTest\DotNetCoreAttackMitigationTest.csproj", "{2D615969-53E2-4B77-9A9A-75C33865CF76}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetPDFUnitTest", "test\DotNetPdfTest\DotNetPDFUnitTest.csproj", "{0FCFB078-5584-469F-92CC-61B0A6216D0D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -603,6 +605,10 @@ Global {2D615969-53E2-4B77-9A9A-75C33865CF76}.Debug|Any CPU.Build.0 = Debug|Any CPU {2D615969-53E2-4B77-9A9A-75C33865CF76}.Release|Any CPU.ActiveCfg = Release|Any CPU {2D615969-53E2-4B77-9A9A-75C33865CF76}.Release|Any CPU.Build.0 = Release|Any CPU + {0FCFB078-5584-469F-92CC-61B0A6216D0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0FCFB078-5584-469F-92CC-61B0A6216D0D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0FCFB078-5584-469F-92CC-61B0A6216D0D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0FCFB078-5584-469F-92CC-61B0A6216D0D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -722,6 +728,7 @@ Global {5BBC75F0-E51A-4EBD-A628-92498D319B1D} = {4C43F2DA-59E5-46F5-B691-195449498555} {7250CDB1-95C4-4822-B01B-3CBD73324CC9} = {30159B0F-BE61-4DB7-AC02-02851426BE4B} {2D615969-53E2-4B77-9A9A-75C33865CF76} = {1D6F1776-FF4B-46C2-9B3D-BC46CCF049DC} + {0FCFB078-5584-469F-92CC-61B0A6216D0D} = {1D6F1776-FF4B-46C2-9B3D-BC46CCF049DC} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E18684C9-7D76-45CD-BF24-E3944B7F174C} diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj b/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj index 3a21abc09..a2a836154 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj @@ -22,6 +22,11 @@ + + + + + diff --git a/dotnet/src/dotnetcore/GxPdfReportsCS/GlobalSuppressions.cs b/dotnet/src/dotnetcore/GxPdfReportsCS/GlobalSuppressions.cs index 37a5076e3..dc00e11aa 100644 --- a/dotnet/src/dotnetcore/GxPdfReportsCS/GlobalSuppressions.cs +++ b/dotnet/src/dotnetcore/GxPdfReportsCS/GlobalSuppressions.cs @@ -16,3 +16,5 @@ [assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:com.genexus.reports.NativeSharpFunctionsMS.getRegistrySubValues(System.String,System.String)~System.Collections.ArrayList")] [assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:com.genexus.reports.NativeSharpFunctionsMS.ReadRegKey(System.String)~System.String")] [assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:com.genexus.reports.MSPDFFontDescriptor.getTrueTypeFontLocation(System.String)~System.String")] +[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:com.genexus.reports.PDFReportItextBase.getAcrobatLocation~System.String")] +[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:com.genexus.reports.PDFReportItextBase.loadSubstituteTable")] diff --git a/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj b/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj index 3818d8a4f..c9d5311c5 100644 --- a/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj +++ b/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj @@ -9,15 +9,19 @@ - + + - - + + + + + all diff --git a/dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportItext8.cs b/dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportItext8.cs new file mode 100644 index 000000000..f5c2fb99f --- /dev/null +++ b/dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportItext8.cs @@ -0,0 +1,1332 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Text; +using GeneXus; +using iText.Barcodes; +using iText.Html2pdf; +using iText.Html2pdf.Resolver.Font; +using iText.IO.Font; +using iText.IO.Font.Otf; +using iText.IO.Image; +using iText.Kernel.Colors; +using iText.Kernel.Exceptions; +using iText.Kernel.Font; +using iText.Kernel.Geom; +using iText.Kernel.Pdf; +using iText.Kernel.Pdf.Action; +using iText.Kernel.Pdf.Canvas; +using iText.Layout; +using iText.Layout.Borders; +using iText.Layout.Element; +using iText.Layout.Font; +using iText.Layout.Layout; +using iText.Layout.Properties; +using iText.Layout.Renderer; +using iText.Layout.Splitting; +using log4net; +using Path = System.IO.Path; + +namespace GeneXus.Printer +{ + public class GxReportBuilderPdf8 : GxReportBuilderPdf + { + static ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + public GxReportBuilderPdf8() { } + public GxReportBuilderPdf8(string appPath, Stream outputStream) + { + + _pdfReport = new com.genexus.reports.PDFReportItext8(appPath); + if (outputStream != null) + { + _pdfReport.setOutputStream(outputStream); + GXLogging.Debug(log, "GxReportBuilderPdf outputStream: binaryWriter"); + } + } + } + +} +namespace com.genexus.reports +{ + + public class PDFReportItext8 : PDFReportItextBase + { + + static ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + //const int ASCENT_NORMALIZED_UNITS = 1000; + + private PageSize pageSize; + private PdfFont baseFont; + private Style fontStyle; + //Color for, BaseColor for => Itext5 + private Color backColor, foreColor, templateColorFill; + private Document document; + PdfDocument pdfDocument; + private PdfPage pdfPage; + private PdfWriter writer; + private Rectangle templateRectangle; + private float templatex, templatey; + private PdfFont templateFont; + private PdfFont defaultFont; + internal Dictionary documentImages; + Barcode128 barcode; + private Boolean fontBold; + private Boolean fontItalic; + + public PDFReportItext8(String appPath) : base(appPath) + { + documentImages = new Dictionary(); + } + + protected override void init(ref int gxYPage, ref int gxXPage, int pageWidth, int pageLength) + { + this.pageSize = ComputePageSize(leftMargin, topMargin, pageWidth, pageLength, props.getBooleanGeneralProperty(Const.MARGINS_INSIDE_BORDER, Const.DEFAULT_MARGINS_INSIDE_BORDER)); + gxXPage = (int)this.pageSize.GetRight(); + if (props.getBooleanGeneralProperty(Const.FIX_SAC24437, true)) + gxYPage = (int)(pageLength / GX_PAGE_SCALE_Y); + else + gxYPage = (int)(pageLength / GX_PAGE_SCALE_Y_OLD); + + writer = new PdfWriter(outputStream); + writer.SetCompressionLevel(CompressionConstants.BEST_COMPRESSION); + try + { + string level = props.getGeneralProperty(Const.COMPLIANCE_LEVEL); + if (Enum.TryParse(level, true, out complianceLevel)) + { + //if (SetComplainceLevel(complianceLevel)) + //writer.SetTagged(); + } + pdfDocument = new PdfDocument(writer); + pdfDocument.SetDefaultPageSize(this.pageSize); + document = new Document(pdfDocument); + document.SetFontProvider(new DefaultFontProvider()); + } + catch (PdfException de) + { + GXLogging.Debug(log, "GxDrawRect error", de); + } + } + + internal override bool SetComplainceLevel(PdfConformanceLevel level) + { + /*switch (level) + { + case PdfConformanceLevel.Pdf_A1A: + writer.PDFXConformance = PdfWriter.PDFA1A; + return true; + case PdfConformanceLevel.Pdf_A1B: + writer.PDFXConformance = PdfWriter.PDFA1B; + return true; + default: + return false; + }*/ + return false; + } + + /** + * @param hideCorners indicates whether corner triangles should be hidden when the side that joins them is hidden. + */ + + private void drawRectangle(PdfCanvas cb, float x, float y, float w, float h, int styleTop, int styleBottom, int styleRight, int styleLeft, + float radioTL, float radioTR, float radioBL, float radioBR, float penAux, bool hideCorners) + { + + float[] dashPatternTop = getDashedPattern(styleTop); + float[] dashPatternBottom = getDashedPattern(styleBottom); + float[] dashPatternLeft = getDashedPattern(styleLeft); + float[] dashPatternRight = getDashedPattern(styleRight); + + //-------------------bottom line--------------------- + if (styleBottom != STYLE_NONE_CONST) + { + cb.SetLineDash(dashPatternBottom, 0); + } + + float b = 0.4477f; + if (radioBL > 0) + { + cb.MoveTo(x + radioBL, y); + } + else + { + if (hideCorners && styleLeft == STYLE_NONE_CONST && radioBL == 0) + { + cb.MoveTo(x + penAux, y); + } + else + { + cb.MoveTo(x, y); + } + } + + //-------------------bottom right corner--------------------- + + if (styleBottom != STYLE_NONE_CONST) + { + if (hideCorners && styleRight == STYLE_NONE_CONST && radioBR == 0) + { + cb.LineTo(x + w - penAux, y); + } + else + { + cb.LineTo(x + w - radioBR, y); + } + if (radioBR > 0 && styleRight != STYLE_NONE_CONST) + { + cb.CurveTo(x + w - radioBR * b, y, x + w, y + radioBR * b, x + w, y + radioBR); + } + } + + //-------------------right line--------------------- + + if (styleRight != STYLE_NONE_CONST && dashPatternRight != dashPatternBottom) + { + cb.Stroke(); + cb.SetLineDash(dashPatternRight, 0); + if (hideCorners && styleBottom == STYLE_NONE_CONST && radioBR == 0) + { + cb.MoveTo(x + w, y + penAux); + } + else + { + cb.MoveTo(x + w, y + radioBR); + } + } + + //-------------------top right corner--------------------- + if (styleRight != STYLE_NONE_CONST) + { + if (hideCorners && styleTop == STYLE_NONE_CONST && radioTR == 0) + { + cb.LineTo(x + w, y + h - penAux); + } + else + { + cb.LineTo(x + w, y + h - radioTR); + } + if (radioTR > 0 && styleTop != STYLE_NONE_CONST) + { + cb.CurveTo(x + w, y + h - radioTR * b, x + w - radioTR * b, y + h, x + w - radioTR, y + h); + } + } + + //-------------------top line--------------------- + + if (styleTop != STYLE_NONE_CONST && dashPatternTop != dashPatternRight) + { + cb.Stroke(); + cb.SetLineDash(dashPatternTop, 0); + if (hideCorners && styleRight == STYLE_NONE_CONST && radioTR == 0) + { + cb.MoveTo(x + w - penAux, y + h); + } + else + { + cb.MoveTo(x + w - radioTR, y + h); + } + } + + //-------------------top left corner--------------------- + if (styleTop != STYLE_NONE_CONST) + { + if (hideCorners && styleLeft == STYLE_NONE_CONST && radioTL == 0) + { + cb.LineTo(x + penAux, y + h); + } + else + { + cb.LineTo(x + radioTL, y + h); + } + if (radioTL > 0 && styleLeft != STYLE_NONE_CONST) + { + cb.CurveTo(x + radioTL * b, y + h, x, y + h - radioTL * b, x, y + h - radioTL); + } + } + + //-------------------left line--------------------- + + if (styleLeft != STYLE_NONE_CONST && dashPatternLeft != dashPatternTop) + { + cb.Stroke(); + cb.SetLineDash(dashPatternLeft, 0); + if (hideCorners && styleTop == STYLE_NONE_CONST && radioTL == 0) + { + cb.MoveTo(x, y + h - penAux); + } + else + { + cb.MoveTo(x, y + h - radioTL); + } + } + + //-------------------bottom left corner--------------------- + if (styleLeft != STYLE_NONE_CONST) + { + if (hideCorners && styleBottom == STYLE_NONE_CONST && radioBL == 0) + { + cb.LineTo(x, y + penAux); + } + else + { + cb.LineTo(x, y + radioBL); + } + if (radioBL > 0 && styleBottom != STYLE_NONE_CONST) + { + cb.CurveTo(x, y + radioBL * b, x + radioBL * b, y, x + radioBL, y); + } + } + cb.Stroke(); + + } + + private void roundRectangle(PdfCanvas cb, float x, float y, float w, float h, float radioTL, float radioTR, float radioBL, float radioBR) + { + //-------------------bottom line--------------------- + + + float b = 0.4477f; + if (radioBL > 0) + { + cb.MoveTo(x + radioBL, y); + } + else + { + cb.MoveTo(x, y); + } + + //-------------------bottom right corner--------------------- + + cb.LineTo(x + w - radioBR, y); + if (radioBR > 0) + { + cb.CurveTo(x + w - radioBR * b, y, x + w, y + radioBR * b, x + w, y + radioBR); + } + + + cb.LineTo(x + w, y + h - radioTR); + if (radioTR > 0) + { + cb.CurveTo(x + w, y + h - radioTR * b, x + w - radioTR * b, y + h, x + w - radioTR, y + h); + } + + cb.LineTo(x + radioTL, y + h); + if (radioTL > 0) + { + cb.CurveTo(x + radioTL * b, y + h, x, y + h - radioTL * b, x, y + h - radioTL); + } + cb.LineTo(x, y + radioBL); + if (radioBL > 0) + { + cb.CurveTo(x, y + radioBL * b, x + radioBL * b, y, x + radioBL, y); + } + } + + public override void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue, + int styleTop, int styleBottom, int styleRight, int styleLeft, int cornerRadioTL, int cornerRadioTR, int cornerRadioBL, int cornerRadioBR) + { + Color rectBackColor = new DeviceRgb(backRed, backGreen, backBlue); + Color rectForeColor = new DeviceRgb(foreRed, foreGreen, foreBlue); + GxDrawRect(left, top, right, bottom, pen, rectForeColor, backMode, rectBackColor, styleTop, styleBottom, styleRight, styleLeft, cornerRadioTL, cornerRadioTR, cornerRadioBL, cornerRadioBR); + } + + void GxDrawRect(int left, int top, int right, int bottom, int pen, Color foreColor, int backMode, Color backColor, + int styleTop, int styleBottom, int styleRight, int styleLeft, int cornerRadioTL, int cornerRadioTR, int cornerRadioBL, int cornerRadioBR) + { + PdfCanvas cb = new PdfCanvas(pdfPage); + + float penAux = (float)convertScale(pen); + float rightAux = (float)convertScale(right); + float bottomAux = (float)convertScale(bottom); + float leftAux = (float)convertScale(left); + float topAux = (float)convertScale(top); + + GXLogging.Debug(log, "GxDrawRect -> (" + left + "," + top + ") - (" + right + "," + bottom + ") BackMode: " + backMode + " Pen:" + pen + ",leftMargin:" + leftMargin); + cb.SaveState(); + + float x1, y1, x2, y2; + x1 = leftAux + leftMargin; + y1 = pageSize.GetTop() - bottomAux - topMargin - bottomMargin; + x2 = rightAux + leftMargin; + y2 = pageSize.GetTop() - topAux - topMargin - bottomMargin; + + cb.SetLineWidth(penAux); + cb.SetLineCapStyle(PdfCanvasConstants.LineCapStyle.PROJECTING_SQUARE); + + if (cornerRadioBL == 0 && cornerRadioBR == 0 && cornerRadioTL == 0 && cornerRadioTR == 0 && styleBottom == 0 && styleLeft == 0 && styleRight == 0 && styleTop == 0) + { + //border color must be the same as the fill if border=0 since setLineWidth does not work. + if (pen > 0) + cb.SetStrokeColor(foreColor); + else + cb.SetStrokeColor(backColor); + cb.Rectangle(x1, y1, x2 - x1, y2 - y1); + + if (backMode != 0) + { + cb.SetFillColor(backColor); + cb.FillStroke(); + } + + cb.ClosePathStroke(); + } + else + { + float w = x2 - x1; + float h = y2 - y1; + if (w < 0) + { + x1 += w; + w = -w; + } + if (h < 0) + { + y1 += h; + h = -h; + } + + float cRadioTL = (float)convertScale(cornerRadioTL); + float cRadioTR = (float)convertScale(cornerRadioTR); + float cRadioBL = (float)convertScale(cornerRadioBL); + float cRadioBR = (float)convertScale(cornerRadioBR); + + // Scale the radius if it's too large or to small to fit. + int max = (int)Math.Min(w, h); + cRadioTL = Math.Max(0, Math.Min(cRadioTL, max / 2)); + cRadioTR = Math.Max(0, Math.Min(cRadioTR, max / 2)); + cRadioBL = Math.Max(0, Math.Min(cRadioBL, max / 2)); + cRadioBR = Math.Max(0, Math.Min(cRadioBR, max / 2)); + + if (backMode != 0) + { + cb.SetStrokeColor(backColor); + cb.SetLineWidth(0); + roundRectangle(cb, x1, y1, w, h, cRadioTL, cRadioTR, cRadioBL, cRadioBR); + cb.SetFillColor(backColor); + cb.FillStroke(); + cb.SetLineWidth(penAux); + } + if (pen > 0) + { + //Rectangle edge + cb.SetFillColor(backColor); + cb.SetStrokeColor(foreColor); + drawRectangle(cb, x1, y1, w, h, + styleTop, styleBottom, styleRight, styleLeft, + cRadioTL, cRadioTR, + cRadioBL, cRadioBR, penAux, false); + } + } + cb.RestoreState(); + } + public override void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue, int style) + { + PdfCanvas cb = new PdfCanvas(pdfPage); + + Color foreColor = new DeviceRgb(foreRed, foreGreen, foreBlue); + + float widthAux = (float)convertScale(width); + float rightAux = (float)convertScale(right); + float bottomAux = (float)convertScale(bottom); + float leftAux = (float)convertScale(left); + float topAux = (float)convertScale(top); + + GXLogging.Debug(log, "GxDrawLine leftAux: " + leftAux + ",leftMargin:" + leftMargin + ",pageSize.Top:" + pageSize.GetTop() + ",bottomAux:" + bottomAux + ",topMargin:" + topMargin + ",bottomMargin:" + bottomMargin); + + GXLogging.Debug(log, "GxDrawLine -> (" + left + "," + top + ") - (" + right + "," + bottom + ") Width: " + width); + float x1, y1, x2, y2; + x1 = leftAux + leftMargin; + y1 = pageSize.GetTop() - bottomAux - topMargin - bottomMargin; + x2 = rightAux + leftMargin; + y2 = pageSize.GetTop() - topAux - topMargin - bottomMargin; + + GXLogging.Debug(log, "Line-> (" + (x1) + "," + y1 + ") - (" + x2 + "," + y2 + ") "); + cb.SaveState(); + cb.SetStrokeColor(foreColor); + cb.SetLineWidth(widthAux); + + if (lineCapProjectingSquare) + { + cb.SetLineCapStyle(PdfCanvasConstants.LineCapStyle.PROJECTING_SQUARE); + } + if (style != 0) + { + float[] dashPattern = getDashedPattern(style); + cb.SetLineDash(dashPattern, 0); + } + + cb.MoveTo(x1, y1); + cb.LineTo(x2, y2); + cb.Stroke(); + + cb.RestoreState(); + } + + public override void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom, int aspectRatio) + { + try + { + Image image; + Image imageRef; + if (documentImages != null && documentImages.TryGetValue(bitmap, out imageRef)) + { + image = imageRef; + } + else + { + try + { + if (!Path.IsPathRooted(bitmap)) + { + + image = new Image(ImageDataFactory.Create(defaultRelativePrepend + bitmap)); + if (image == null) + { + bitmap = webAppDir + bitmap; + image = new Image(ImageDataFactory.Create(bitmap)); + } + else + { + bitmap = defaultRelativePrepend + bitmap; + } + } + else + { + image = new Image(ImageDataFactory.Create(bitmap)); + } + } + catch (Exception)//absolute url + { + Uri uri = new Uri(bitmap); + image = new Image(ImageDataFactory.Create(uri)); + } + if (documentImages == null) + { + documentImages = new Dictionary(); + } + documentImages[bitmap] = image; + } + GXLogging.Debug(log, "GxDrawBitMap -> '" + bitmap + "' [" + left + "," + top + "] - Size: (" + (right - left) + "," + (bottom - top) + ")"); + + if (image != null) + { + float rightAux = (float)convertScale(right); + float bottomAux = (float)convertScale(bottom); + float leftAux = (float)convertScale(left); + float topAux = (float)convertScale(top); + image.SetFixedPosition(this.getPage(),leftAux + leftMargin, this.pageSize.GetTop() - bottomAux - topMargin - bottomMargin); + if (aspectRatio == 0) + image.ScaleAbsolute(rightAux - leftAux, bottomAux - topAux); + else + image.ScaleToFit(rightAux - leftAux, bottomAux - topAux); + image.GetAccessibilityProperties().SetAlternateDescription(Path.GetFileName(bitmap)); + document.Add(image); + } + } + catch (PdfException de) + { + GXLogging.Error(log, "GxDrawBitMap document error", de); + } + catch (IOException ioe) + { + GXLogging.Error(log, "GxDrawBitMap io error", ioe); + } + catch (Exception e) + { + GXLogging.Error(log, "GxDrawBitMap error", e); + } + } + + public override void GxAttris(String fontName, int fontSize, bool fontBold, bool fontItalic, bool fontUnderline, bool fontStrikethru, int Pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue) + { + fontStyle = null; + bool _isCJK = false; + bool embeedFont = IsEmbeddedFont(fontName); + if (!embeedFont) + { + fontName = getSubstitute(fontName); + } + + GXLogging.Debug(log, "GxAttris: "); + GXLogging.Debug(log, "\\-> Font: " + fontName + " (" + fontSize + ")" + (fontBold ? " BOLD" : "") + (fontItalic ? " ITALIC" : "") + (fontStrikethru ? " Strike" : "")); + GXLogging.Debug(log, "\\-> Fore (" + foreRed + ", " + foreGreen + ", " + foreBlue + ")"); + GXLogging.Debug(log, "\\-> Back (" + backRed + ", " + backGreen + ", " + backBlue + ")"); + + if (barcode128AsImage && fontName.ToLower().IndexOf("barcode 128") >= 0 || fontName.ToLower().IndexOf("barcode128") >= 0) + { + barcode = new Barcode128(pdfDocument); + barcode.SetCodeType(Barcode128.CODE128); + } + else + { + barcode = null; + } + this.fontUnderline = fontUnderline; + this.fontStrikethru = fontStrikethru; + this.fontSize = fontSize; + this.fontBold = fontBold; + this.fontItalic = fontItalic; + foreColor = new DeviceRgb(foreRed, foreGreen, foreBlue); + backColor = new DeviceRgb(backRed, backGreen, backBlue); + + backFill = (backMode != 0); + try + { + //LoadAsianFontsDll(); + string f = fontName.ToLower(); + if (PDFFont.isType1(fontName)) + { + //Asian font + for (int i = 0; i < Type1FontMetrics.CJKNames.Length; i++) + { + if (Type1FontMetrics.CJKNames[i][0].ToLower().Equals(f) || + Type1FontMetrics.CJKNames[i][1].ToLower().Equals(f)) + { + fontStyle = new Style(); + if (fontItalic) fontStyle.SetItalic(); + if (fontBold) fontStyle.SetBold(); + + setAsianFont(fontName, string.Empty); + fontStyle.SetFont(baseFont); + + _isCJK = true; + break; + } + } + if (!_isCJK) + { + int style = 0; + if (fontBold && fontItalic) + style = style + 3; + else + { + if (fontItalic) + style = style + 2; + if (fontBold) + style = style + 1; + } + for (int i = 0; i < PDFFont.base14.Length; i++) + { + if (PDFFont.base14[i][0].ToLower().Equals(f)) + { + fontName = PDFFont.base14[i][1 + style].Substring(1); + break; + } + } + baseFont = PdfFontFactory.CreateFont(fontName, PdfEncodings.WINANSI, PdfFontFactory.EmbeddingStrategy.PREFER_NOT_EMBEDDED); + } + } + else + {//True type font + + if (IsEmbeddedFont(fontName)) + { + fontStyle = new Style(); + if (fontItalic) fontStyle.SetItalic(); + if (fontBold) fontStyle.SetBold(); + } + string fontPath = GetFontLocation(fontName); + bool foundFont = true; + if (string.IsNullOrEmpty(fontPath)) + { + MSPDFFontDescriptor fontDescriptor = new MSPDFFontDescriptor(); + fontPath = fontDescriptor.getTrueTypeFontLocation(fontName); + if (string.IsNullOrEmpty(fontPath)) + { + baseFont = CreateDefaultFont(); + foundFont = false; + } + else + { + props.setProperty(Const.MS_FONT_LOCATION, fontName, fontPath); + } + } + if (foundFont) + { + if (IsEmbeddedFont(fontName)) + { + try + { + baseFont = PdfFontFactory.CreateFont(fontPath, PdfEncodings.IDENTITY_H, PdfFontFactory.EmbeddingStrategy.PREFER_EMBEDDED); + GXLogging.Debug(log, "EMBEED_SECTION Font"); + } + catch (IOException ioEx) + { + Exception exDetailed = new Exception($"Error creating {fontPath}. Check font is installed for the current user", ioEx); + throw exDetailed; + } + } + else + { + + fontStyle = new Style(); + if (fontItalic) fontStyle.SetItalic(); + if (fontBold) fontStyle.SetBold(); + + GXLogging.Debug(log, "NOT EMBEED_SECTION Font"); + + baseFont = PdfFontFactory.CreateFont(fontPath, PdfEncodings.WINANSI, PdfFontFactory.EmbeddingStrategy.PREFER_NOT_EMBEDDED); + fontStyle.SetFont(baseFont); + } + } + else + { + GXLogging.Debug(log, "NOT foundFont fontName:" + fontName); + } + } + } + catch (PdfException de) + { + GXLogging.Debug(log, "GxAttris DocumentException", de); + throw de; + } + catch (Exception e) + { + GXLogging.Debug(log, "GxAttris error", e); + baseFont = CreateDefaultFont(); + } + } + + private PdfFont CreateDefaultFont() + { + if (defaultFont == null) + { + if (IsPdfA()) + defaultFont = PdfFontFactory.CreateFont("Helvetica", PdfEncodings.CP1252, PdfFontFactory.EmbeddingStrategy.PREFER_NOT_EMBEDDED); + else + defaultFont = PdfFontFactory.CreateFont("Helvetica", PdfEncodings.WINANSI, PdfFontFactory.EmbeddingStrategy.PREFER_NOT_EMBEDDED); + } + return PdfFontFactory.CreateFont("Helvetica", PdfEncodings.WINANSI, PdfFontFactory.EmbeddingStrategy.PREFER_NOT_EMBEDDED); + } + + public override void setAsianFont(String fontName, String style) + { + //LoadAsianFontsDll(); + try + { + if (fontName.Equals("Japanese")) + baseFont = PdfFontFactory.CreateFont("HeiseiMin-W3", "UniJIS-UCS2-H", PdfFontFactory.EmbeddingStrategy.PREFER_NOT_EMBEDDED); + if (fontName.Equals("Japanese2")) + baseFont = PdfFontFactory.CreateFont("HeiseiKakuGo-W5", "UniJIS-UCS2-H", PdfFontFactory.EmbeddingStrategy.PREFER_NOT_EMBEDDED); + if (fontName.Equals("SimplifiedChinese")) + baseFont = PdfFontFactory.CreateFont("STSong-Light", "UniGB-UCS2-H", PdfFontFactory.EmbeddingStrategy.PREFER_NOT_EMBEDDED); + if (fontName.Equals("TraditionalChinese")) + baseFont = PdfFontFactory.CreateFont("MHei-Medium", "UniCNS-UCS2-H", PdfFontFactory.EmbeddingStrategy.PREFER_NOT_EMBEDDED); + if (fontName.Equals("Korean")) + baseFont = PdfFontFactory.CreateFont("HYSMyeongJo-Medium", "UniKS-UCS2-H", PdfFontFactory.EmbeddingStrategy.PREFER_NOT_EMBEDDED); + } + catch (PdfException de) + { + GXLogging.Debug(log, "setAsianFont error", de); + } + catch (IOException ioe) + { + GXLogging.Debug(log, "setAsianFont io error", ioe); + } + } + + public override void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align, int htmlformat, int border, int valign) + { + GXLogging.Debug(log, "GxDrawText, text:" + sTxt); + + bool printRectangle = false; + if (props.getBooleanGeneralProperty(Const.BACK_FILL_IN_CONTROLS, true)) + printRectangle = true; + + if (printRectangle && (border == 1 || backFill)) + GxDrawRect(left, top, right, bottom, border, foreColor, backFill ? 1 : 0, backColor, 0, 0, 0, 0, 0, 0, 0, 0); + + PdfCanvas canvas = new PdfCanvas(pdfPage); + sTxt = sTxt.TrimEnd(TRIM_CHARS); + + PdfFont font = baseFont; + canvas.SetFontAndSize(this.baseFont, fontSize); + canvas.SetFillColor(foreColor); + float captionHeight = baseFont.GetAscent(sTxt, fontSize) / 1000; + float rectangleWidth = baseFont.GetWidth(sTxt, fontSize); + float lineHeight = (1 / 1000) * (baseFont.GetAscent(sTxt, fontSize) - baseFont.GetDescent(sTxt, fontSize)) + (fontSize * 1.2f); + float textBlockHeight = (float)convertScale(bottom - top); + int linesCount = (int)(textBlockHeight / lineHeight); + int bottomOri = bottom; + int topOri = top; + + if (linesCount >= 2 && !((align & 16) == 16) && htmlformat != 1) + if (valign == (int)VerticalAlign.TOP) + bottom = top + (int)reconvertScale(lineHeight); + else if (valign == (int)VerticalAlign.BOTTOM) + top = bottom - (int)reconvertScale(lineHeight); + + float bottomAux = (float)convertScale(bottom) - ((float)convertScale(bottom - top) - captionHeight) / 2; + float topAux = (float)convertScale(top) + ((float)convertScale(bottom - top) - captionHeight) / 2; ; + + float leftAux = (float)convertScale(left); + float rightAux = (float)convertScale(right); + int alignment = align & 3; + bool autoResize = (align & 256) == 256; + + GXLogging.Debug(log, "GxDrawText left: " + left + ",top:" + top + ",right:" + right + ",bottom:" + bottom + ",captionHeight:" + captionHeight + ",fontSize:" + fontSize); + GXLogging.Debug(log, "GxDrawText leftAux: " + leftAux + ",leftMargin:" + leftMargin + ",pageSize.Top:" + pageSize.GetTop() + ",bottomAux:" + bottomAux + ",topMargin:" + topMargin + ",bottomMargin:" + bottomMargin); + if (htmlformat == 1) + { + try + { + ConverterProperties converterProperties = new ConverterProperties(); + FontProvider fontProvider = document.GetFontProvider(); + if (IsTrueType(baseFont)) + { + Hashtable locations = GetFontLocations(); + foreach (string fontName in locations.Keys) + { + string fontPath = (string)locations[fontName]; + if (string.IsNullOrEmpty(fontPath)) + { + MSPDFFontDescriptor fontDescriptor = new MSPDFFontDescriptor(); + fontPath = fontDescriptor.getTrueTypeFontLocation(fontName); + } + if (!string.IsNullOrEmpty(fontPath)) + { + + fontProvider.AddFont(fontPath); + } + } + } + converterProperties.SetFontProvider(fontProvider); + bottomAux = (float)convertScale(bottom); + topAux = (float)convertScale(top); + float drawingPageHeight = this.pageSize.GetTop() - topMargin - bottomMargin; + + float llx = leftAux + leftMargin; + float lly = drawingPageHeight - bottomAux; + float urx = rightAux + leftMargin; + float ury = drawingPageHeight - topAux; + + Rectangle htmlRectangle = new Rectangle(llx, lly, urx - llx, ury - lly); + YPosition yPosition = new YPosition(htmlRectangle.GetTop()); + + Canvas htmlCanvas = new Canvas(canvas, htmlRectangle); + htmlCanvas.SetFontProvider(fontProvider); + + //Iterate over the elements (a.k.a the parsed HTML string) and handle each case accordingly + IList elements = HtmlConverter.ConvertToElements(sTxt, converterProperties); + foreach (IElement element in elements) + { + float blockElementHeight = GetBlockElementHeight((IBlockElement)element, htmlRectangle); + + if (PageHeightExceeded(bottomMargin, yPosition.CurrentYPosition)) + { + llx = leftAux + leftMargin; + lly = drawingPageHeight - bottomAux; + urx = rightAux + leftMargin; + ury = drawingPageHeight - topAux; + htmlRectangle = new Rectangle(llx, lly, urx - llx, ury - lly); + yPosition = new YPosition(htmlRectangle.GetTop()); + bottomAux -= drawingPageHeight; + GxEndPage(); + GxStartPage(); + + canvas = new PdfCanvas(pdfPage); + sTxt = sTxt.TrimEnd(TRIM_CHARS); + canvas.SetFontAndSize(this.baseFont, fontSize); + canvas.SetFillColor(foreColor); + + htmlCanvas = new Canvas(canvas, htmlRectangle); + htmlCanvas.SetFontProvider(fontProvider); + } + ProcessHTMLElement((IBlockElement)element, alignment, htmlCanvas); + yPosition.CurrentYPosition -= blockElementHeight; + } + + } + catch (Exception ex1) + { + GXLogging.Debug(log, "Error adding html: ", ex1); + } + + } + else if (barcode != null) + { + GXLogging.Debug(log, "Barcode" + barcode.GetType().ToString()); + try + { + barcode.SetCode(sTxt); + barcode.SetTextAlignment(alignment); + Rectangle rectangle = new Rectangle(0, 0); + + switch (alignment) + { + case 1: // Center Alignment + rectangle = rectangle.SetBbox((leftAux + rightAux) / 2 + leftMargin - rectangleWidth / 2, + (float)this.pageSize.GetTop() - (float)convertScale(bottom) - topMargin - bottomMargin, + (leftAux + rightAux) / 2 + leftMargin + rectangleWidth / 2, + (float)this.pageSize.GetTop() - (float)convertScale(top) - topMargin - bottomMargin); + break; + case 2: // Right Alignment + rectangle = rectangle.SetBbox(rightAux + leftMargin - rectangleWidth, + (float)this.pageSize.GetTop() - (float)convertScale(bottom) - topMargin - bottomMargin, + rightAux + leftMargin, + (float)this.pageSize.GetTop() - (float)convertScale(top) - topMargin - bottomMargin); + break; + case 0: // Left Alignment + rectangle = rectangle.SetBbox(leftAux + leftMargin, + (float)this.pageSize.GetTop() - (float)convertScale(bottom) - topMargin - bottomMargin, + leftAux + leftMargin + rectangleWidth, + (float)this.pageSize.GetTop() - (float)convertScale(top) - topMargin - bottomMargin); + break; + } + barcode.SetAltText(string.Empty); + barcode.SetBaseline(0); + + if (fontSize < Const.LARGE_FONT_SIZE) + barcode.SetX(Const.OPTIMAL_MINIMU_BAR_WIDTH_SMALL_FONT); + else + barcode.SetX(Const.OPTIMAL_MINIMU_BAR_WIDTH_LARGE_FONT); + + + Image imageCode = new Image(barcode.CreateFormXObject(backFill ? backColor : null, foreColor, pdfDocument)); + imageCode.SetFixedPosition(leftAux + leftMargin, rectangle.GetBottom()); + barcode.SetBarHeight(rectangle.GetHeight()); + imageCode.ScaleToFit(rectangle.GetWidth(), rectangle.GetHeight()); + document.Add(imageCode); + } + catch (Exception ex) + { + GXLogging.Error(log, "Error generating Barcode " + barcode.GetType().ToString(), ex); + } + } + else + { + + if (sTxt.Trim().ToLower().Equals("{{pages}}")) + { + GXLogging.Debug(log, "GxDrawText addTemplate-> (" + (leftAux + leftMargin) + "," + (this.pageSize.GetTop() - bottomAux - topMargin - bottomMargin) + ") "); + templateRectangle = new Rectangle(leftAux + leftMargin, (float)this.pageSize.GetTop() - bottomAux - topMargin - bottomMargin, rightAux + leftMargin, (float)this.pageSize.GetTop() - topAux - topMargin - bottomMargin); + + templatex = leftAux + leftMargin; + templatey = this.pageSize.GetTop() - bottomAux - topMargin - bottomMargin; + templateFont = this.baseFont; + templateFontSize = fontSize; + templateColorFill = foreColor; + templateAlignment = alignment; + templateCreated = true; + } + + float textBlockWidth = rightAux - leftAux; + float TxtWidth = baseFont.GetWidth(sTxt, fontSize); + Boolean justified = (alignment == 3) && textBlockWidth < TxtWidth; + Boolean wrap = ((align & 16) == 16); + + float leading = (float)Convert.ToDouble(props.getGeneralProperty(Const.LEADING), CultureInfo.InvariantCulture.NumberFormat); + Style style = new Style(); + if (fontBold) style.SetBold(); + if (fontItalic) style.SetItalic(); + if (fontStrikethru) style.SetUnderline(fontSize / 6, fontSize / 2); + if (fontUnderline) style.SetUnderline(fontSize / 6, 0); + style.SetFont(font); + style.SetFontSize(fontSize); + style.SetFontColor(foreColor); + + if (wrap || justified) + { + bottomAux = (float)convertScale(bottomOri); + topAux = (float)convertScale(topOri); + + float llx = leftAux + leftMargin; + float lly = this.pageSize.GetTop() - bottomAux - topMargin - bottomMargin; + float urx = rightAux + leftMargin; + float ury = this.pageSize.GetTop() - topAux - topMargin - bottomMargin; + + DrawTextColumn(llx, lly, urx, ury, leading, sTxt, valign, alignment, style, wrap); + } + else + { + try + { + if (!autoResize) + { + String newsTxt = sTxt; + while (TxtWidth > textBlockWidth && (newsTxt.Length - 1 >= 0)) + { + sTxt = newsTxt; + newsTxt = newsTxt.Substring(0, newsTxt.Length - 1); + TxtWidth = this.baseFont.GetWidth(newsTxt, fontSize); + } + } + + Paragraph p = new Paragraph(sTxt); + p.AddStyle(style); + + switch (alignment) + { + case 1: // Center Alignment + document.ShowTextAligned(p, ((leftAux + rightAux) / 2) + leftMargin, this.pageSize.GetTop() - bottomAux - topMargin - bottomMargin, this.getPage(), TextAlignment.CENTER, VerticalAlignment.MIDDLE, 0); + break; + case 2: // Right Alignment + document.ShowTextAligned(p, rightAux + leftMargin, this.pageSize.GetTop() - bottomAux - topMargin - bottomMargin, this.getPage(), TextAlignment.RIGHT, VerticalAlignment.MIDDLE, 0); + break; + case 0: // Left Alignment + case 3: // Justified, only one text line + document.ShowTextAligned(p, leftAux + leftMargin, this.pageSize.GetTop() - bottomAux - topMargin - bottomMargin, this.getPage(), TextAlignment.LEFT, VerticalAlignment.MIDDLE, 0); + break; + } + } + catch (Exception e) + { + GXLogging.Error(log, "GxDrawText failed to draw simple text: ", e); + } + } + } + } + + private void ProcessHTMLElement(IBlockElement blockElement, int alignment, Canvas htmlCanvas) + { + if (blockElement is Paragraph p) + { + if (alignment != 0) + p.SetTextAlignment(GetTextAlignment(alignment)); + } + htmlCanvas.Add(blockElement); + } + bool PageHeightExceeded(float bottomAux, float drawingPageHeight) + { + return bottomAux > drawingPageHeight; + } + private float GetBlockElementHeight(IBlockElement blockElement, Rectangle htmlRectangle) + { + return blockElement.CreateRendererSubTree().SetParent(document.GetRenderer()).Layout(new LayoutContext(new LayoutArea(this.getPage(), htmlRectangle))).GetOccupiedArea().GetBBox().GetHeight(); + } + + //Utility class used to know where the cursor is left after each block element (HTML tag) is rendered + private class YPosition + { + public YPosition(float initialYPosition) + { + CurrentYPosition = initialYPosition; + } + + public float CurrentYPosition { get; set; } + } + + private BaseDirection? GetBaseDirection(int runDirection) + { + switch (runDirection) + { + case 2: return BaseDirection.LEFT_TO_RIGHT; + default: return null; + } + } + + private VerticalAlignment GetVerticalAlignment(float valign) + { + if (valign == (int)VerticalAlign.TOP) + return VerticalAlignment.TOP; + else if (valign == (int)VerticalAlign.BOTTOM) + return VerticalAlignment.BOTTOM; + else + return VerticalAlignment.MIDDLE; + } + + private TextAlignment? GetTextAlignment(int alignment) + { + switch (alignment) + { + case 1: return TextAlignment.CENTER; + case 2: return TextAlignment.RIGHT; + case 0: return TextAlignment.LEFT; + case 3: return TextAlignment.JUSTIFIED; + } + return null; + } + + void DrawTextColumn(float llx, float lly, float urx, float ury, float leading, String text, int valign, int alignment, Style style, Boolean wrap) + { + Paragraph p = new Paragraph(text); + + if (valign == (int)VerticalAlign.MIDDLE) + { + ury = ury + leading; + p.SetVerticalAlignment(VerticalAlignment.MIDDLE); + } + else if (valign == (int)VerticalAlign.BOTTOM) + { + ury = ury + leading; + p.SetVerticalAlignment(VerticalAlignment.BOTTOM); + } + else if (valign == (int)VerticalAlign.TOP) + { + ury = ury + leading / 2; + p.SetVerticalAlignment(VerticalAlignment.TOP); + } + Rectangle rect = new Rectangle(llx, lly, urx - llx, ury - lly); + p.SetTextAlignment(GetTextAlignment(alignment)); + p.AddStyle(style); + + if (wrap) + { + p.SetProperty(Property.SPLIT_CHARACTERS, new CustomSplitCharacters()); + Table table = new Table(1); + table.SetFixedPosition(this.getPage(), rect.GetX(), rect.GetY(), rect.GetWidth()); + Cell cell = new Cell(); + cell.SetWidth(rect.GetWidth()); + cell.SetHeight(rect.GetHeight()); + cell.SetBorder(Border.NO_BORDER); + cell.SetVerticalAlignment(VerticalAlignment.MIDDLE); + cell.Add(p); + table.AddCell(cell); + document.Add(table); + } + else + { + try + { + PdfCanvas pdfCanvas = new PdfCanvas(pdfPage); + Canvas canvas = new Canvas(pdfCanvas, rect); + canvas.Add(p); + canvas.Close(); + } + catch (Exception e) { GXLogging.Error(log, "GxDrawText failed to justify text column: ", e); } + } + } + + public class CustomSplitCharacters : DefaultSplitCharacters + { + public override bool IsSplitCharacter(GlyphLine text, int glyphPos) + { + if (!text.Get(glyphPos).HasValidUnicode()) + { + return false; + } + + bool baseResult = base.IsSplitCharacter(text, glyphPos); + bool myResult = false; + Glyph glyph = text.Get(glyphPos); + + if (glyph.GetUnicode() == '_') + { + myResult = true; + } + return myResult || baseResult; + } + } + +#pragma warning restore CS0612 // Type or member is obsolete + + private PageSize ComputePageSize(float leftMargin, float topMargin, int width, int length, bool marginsInsideBorder) + { + if ((leftMargin == 0 && topMargin == 0) || marginsInsideBorder) + { + if (length == 23818 && width == 16834) + return PageSize.A3; + else if (length == 16834 && width == 11909) + return PageSize.A4; + else if (length == 11909 && width == 8395) + return PageSize.A5; + else if (length == 20016 && width == 5731) + return PageSize.B4; + else if (length == 14170 && width == 9979) + return PageSize.B5; + else if (length == 15120 && width == 10440) + return PageSize.EXECUTIVE; + else if (length == 20160 && width == 12240) + return PageSize.LEGAL; + else if (length == 15840 && width == 12240) + return PageSize.LETTER; + else + return new PageSize(new Rectangle((int)(width / PAGE_SCALE_X), (int)(length / PAGE_SCALE_Y))); + } + return new PageSize(new Rectangle((int)(width / PAGE_SCALE_X) + leftMargin, (int)(length / PAGE_SCALE_Y) + topMargin)); + } + public override void GxEndDocument() + { + //{{Pages}} + if (templateCreated) + { + int totalPages = pdfDocument.GetNumberOfPages(); + for (int i = 0; i < totalPages; i++) + { + PdfPage page = pdfDocument.GetPage(i); + Canvas canvas = new Canvas(page, templateRectangle); + canvas.ShowTextAligned(i.ToString(CultureInfo.InvariantCulture), templatex, templatey, TextAlignment.CENTER).SetBackgroundColor(templateColorFill).SetFont(templateFont).SetFontSize(templateFontSize); + } + } + + int copies = 1; + try + { + copies = Convert.ToInt32(printerSettings.getProperty(form, Const.COPIES)); + GXLogging.Debug(log, "Setting number of copies to " + copies); + PdfViewerPreferences preferences = new PdfViewerPreferences(); + preferences.SetNumCopies(copies); + + int duplex = Convert.ToInt32(printerSettings.getProperty(form, Const.DUPLEX)); + PdfViewerPreferences.PdfViewerPreferencesConstants duplexValue; + if (duplex == 1) + duplexValue = PdfViewerPreferences.PdfViewerPreferencesConstants.SIMPLEX; + else if (duplex == 2) + duplexValue = PdfViewerPreferences.PdfViewerPreferencesConstants.DUPLEX_FLIP_LONG_EDGE; + else if (duplex == 3) + duplexValue = PdfViewerPreferences.PdfViewerPreferencesConstants.DUPLEX_FLIP_SHORT_EDGE; + else if (duplex == 4) + duplexValue = PdfViewerPreferences.PdfViewerPreferencesConstants.DUPLEX_FLIP_LONG_EDGE; + else + duplexValue = PdfViewerPreferences.PdfViewerPreferencesConstants.NONE; + GXLogging.Debug(log, "Setting duplex to " + duplexValue.ToString()); + preferences.SetDuplex(duplexValue); + } + catch (Exception ex) + { + GXLogging.Error(log, "Setting viewer preference error", ex); + } + + bool printingScript = false; + String serverPrinting = props.getGeneralProperty(Const.SERVER_PRINTING); + bool fit = props.getGeneralProperty(Const.ADJUST_TO_PAPER).Equals("true"); + if ((outputType == Const.OUTPUT_PRINTER || outputType == Const.OUTPUT_STREAM_PRINTER) && serverPrinting.Equals("false")) + { + + printingScript = true; + StringBuilder javascript = new StringBuilder(); ; + + javascript.Append("var pp = this.getPrintParams();"); + String printer = printerSettings.getProperty(form, Const.PRINTER).Replace("\\", "\\\\"); + if (!string.IsNullOrEmpty(printer)) + javascript.Append("pp.printerName = \"" + printer + "\";\n"); + + if (fit) + { + javascript.Append("pp.pageHandling = pp.constants.handling.fit;\n"); + } + else + { + javascript.Append("pp.pageHandling = pp.constants.handling.none;\n"); + } + + GXLogging.Debug(log, "MODE:" + printerSettings.getProperty(form, Const.MODE) + ",form:" + form); + + if (printerSettings.getProperty(form, Const.MODE, "3").StartsWith("0"))//Show printer dialog Never + { + javascript.Append("pp.interactive = pp.constants.interactionLevel.automatic;\n"); + + for (int i = 0; i < copies; i++) + { + javascript.Append("this.print(pp);\n"); + } + + //writer.addJavaScript("this.print({bUI: false, bSilent: true, bShrinkToFit: true});"); + //No print dialog is displayed. During printing a progress monitor and cancel + //dialog is displayed and removed automatically when printing is complete. + } + else //Show printer dialog is sent directly to printer | always + { + javascript.Append("pp.interactive = pp.constants.interactionLevel.full;\n"); + //Displays the print dialog allowing the user to change print settings and requiring + //the user to press OK to continue. During printing a progress monitor and cancel + //dialog is displayed and removed automatically when printing is complete. + + javascript.Append("this.print(pp);\n"); + + } + pdfDocument.GetCatalog().SetOpenAction(PdfAction.CreateJavaScript(javascript.ToString())); + } + + if (IsPdfA()) + { + /*using (Stream iccProfile = ReadResource("sRGB Color Space Profile.icm")) + { + ICC_Profile icc = ICC_Profile.GetInstance(iccProfile); + writer.SetOutputIntents("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1", icc); + } + + writer.ExtraCatalog.Put(PdfName.LANG, new PdfString(Config.GetCultureForLang(language).Name)); + PdfDictionary markInfo = new PdfDictionary(PdfName.MARKINFO); + markInfo.Put(PdfName.MARKED, new PdfBoolean(PdfBoolean.TRUE)); + writer.ExtraCatalog.Put(PdfName.MARKINFO, markInfo); + + writer.CreateXmpMetadata();*/ + + } + document.Close(); + GXLogging.Debug(log, "GxEndDocument!"); + try + { + props.save(); + GXLogging.Debug(log, "props.save()"); + } + catch (IOException e) + { + GXLogging.Error(log, "props.save() error", e); + + } + GXLogging.Debug(log, "outputType: " + outputType + ",docName:" + docName); + + switch (outputType) + { + case Const.OUTPUT_SCREEN: + try + { + outputStream.Close(); + GXLogging.Debug(log, "GxEndDocument OUTPUT_SCREEN outputstream length" + outputStream.ToString().Length); + } + catch (IOException e) + { + GXLogging.Error(log, "GxEndDocument OUTPUT_SCREEN error", e); + } + try { showReport(docName, modal); } + catch (Exception){} + break; + + case Const.OUTPUT_PRINTER: + try { outputStream.Close(); } + catch (IOException) {; } // Cierro el archivo + try + { + if (!serverPrinting.Equals("false") && !printingScript) + { + printReport(docName, this.printerOutputMode == 0, printerSettings.getProperty(form, Const.PRINTER)); + } + } + catch (Exception){} + break; + + case Const.OUTPUT_FILE: + try + { + outputStream.Close(); + GXLogging.Debug(log, "GxEndDocument OUTPUT_FILE outputstream length" + outputStream.ToString().Length); + } + catch (IOException e) + { + GXLogging.Error(log, "GxEndDocument OUTPUT_FILE error", e); + } + break; + + case Const.OUTPUT_STREAM: + case Const.OUTPUT_STREAM_PRINTER: + default: break; + } + outputStream = null; + + GXLogging.Debug(log, "GxEndDocument End"); + } + public override void GxStartPage() + { + try + { + pdfPage = pdfDocument.AddNewPage(); + GXLogging.Debug(log, "GxStartPage pages:" + pages + ",new page:" + pages + 1); + pages = pages + 1; + } + catch (PdfException de) + { + GXLogging.Error(log, "GxStartPage error", de); + } + } + + private bool IsTrueType(PdfFont font) + { + return font.GetFontProgram() is TrueTypeFont; + } + } +} + diff --git a/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs b/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs index 7254ff5e8..80b273938 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs @@ -778,6 +778,7 @@ public class Preferences static int oldSTR = -1; static int instrumented = -1; static string mediaPath; + static string pdfLib; static string blobPath; static string blobPathFolderName; static int blankEmptyDates = -1; @@ -1192,6 +1193,28 @@ public static string getPRINT_LAYOUT_METADATA_DIR() } return mediaPath; } + internal static string PdfReportLibrary() + { + if (pdfLib == null) + { + lock (syncRoot) + { + if (pdfLib == null) + { + if (Config.GetValueOf("PDF_RPT_LIBRARY", out pdfLib)) + { + pdfLib = pdfLib.Trim(); + } + else + { + pdfLib = string.Empty; + } + GXLogging.Debug(log, "PDF_RPT_LIBRARY:", pdfLib); + } + } + } + return pdfLib; + } public enum StorageTimeZonePty { Undefined = 0, Utc = 1, Local = 2 }; public static Boolean useTimezoneFix() diff --git a/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs b/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs index e21304972..967201629 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs @@ -434,6 +434,9 @@ public class GxReportUtils public static int OUTPUT_RVIEWER_NATIVE = 1; public static int OUTPUT_RVIEWER_DLL = 2; public static int OUTPUT_PDF = 3; +#if NETCORE + const string PDF_LIBRARY_ITEXT8 = "ITEXT8"; +#endif static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); static public IReportHandler GetPrinter( int outputType, string path, Stream reportOutputStream) @@ -468,7 +471,8 @@ static public IReportHandler GetPrinter( int outputType, string path, Stream rep Type classType = assem.GetType( "GeneXus.Printer.GxReportBuilderPdf", false, true); reportHandler = (IReportHandler) Activator.CreateInstance(classType,new Object[]{path, reportOutputStream}); #else - reportHandler = (IReportHandler)(ClassLoader.FindInstance("GxPdfReportsCS", "GeneXus.Printer", "GxReportBuilderPdf", new Object[] { path, reportOutputStream }, null)); + string reportBuidler = Preferences.PdfReportLibrary().Equals(PDF_LIBRARY_ITEXT8, StringComparison.OrdinalIgnoreCase) ? "GxReportBuilderPdf8" : "GxReportBuilderPdf"; + reportHandler = (IReportHandler)(ClassLoader.FindInstance("GxPdfReportsCS", "GeneXus.Printer", reportBuidler, new Object[] { path, reportOutputStream }, null)); #endif } catch (TargetInvocationException ex) diff --git a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext.cs b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs similarity index 51% rename from dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext.cs rename to dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs index 61b8d0b30..a656d7d07 100644 --- a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext.cs +++ b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs @@ -1,3 +1,4 @@ + using System; using System.IO; @@ -11,18 +12,14 @@ using System.util; using System.Diagnostics; using log4net; -using iTextSharp.text.pdf; -using iTextSharp.text; using GeneXus.Printer; -using iTextSharp.text.html.simpleparser; using System.Collections.Generic; using System.Security; using GeneXus; using GeneXus.Utils; using System.Reflection; using GeneXus.Metadata; -using GeneXus.Configuration; namespace com.genexus.reports { @@ -34,75 +31,63 @@ internal enum VerticalAlign BOTTOM = 2, } - public class PDFReportItextSharp : IReportHandler + public abstract class PDFReportItextBase : IReportHandler { - private int lineHeight, pageLines; + protected int lineHeight, pageLines; static ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - private iTextSharp.text.Rectangle pageSize; - private BaseFont baseFont; - Barcode barcode = null; - private bool fontUnderline; - private bool fontStrikethru; - private int fontSize; - private string language; - - //Color for, BaseColor for => Itext5 - private object backColor, foreColor, templateColorFill; - private Stream outputStream = null; - - private static object syncRoot = new Object(); - private static ParseINI props; - private ParseINI printerSettings; - private String form; - private ArrayList stringTotalPages; - private int outputType = -1; - private int printerOutputMode = -1; - private bool modal = false; - private String docName = "PDFReport.pdf"; - private static NativeSharpFunctionsMS nativeCode = new NativeSharpFunctionsMS(); - private static Hashtable fontSubstitutes = new Hashtable(); - private static String configurationFile = null; - private static String configurationTemplateFile = null; - private static String defaultRelativePrepend = null; - private static String webAppDir = null; + protected bool fontUnderline; + protected bool fontStrikethru; + protected int fontSize; + protected string language; + + protected Stream outputStream = null; + + protected static object syncRoot = new Object(); + protected static ParseINI props; + protected ParseINI printerSettings; + protected String form; + protected ArrayList stringTotalPages; + protected int outputType = -1; + protected int printerOutputMode = -1; + protected bool modal = false; + protected String docName = "PDFReport.pdf"; + protected static NativeSharpFunctionsMS nativeCode = new NativeSharpFunctionsMS(); + protected Hashtable fontSubstitutes = new Hashtable(); + protected static String configurationFile = null; + protected static String configurationTemplateFile = null; + protected static String defaultRelativePrepend = null; + protected static String webAppDir = null; public static bool DEBUG = false; - private Document document; - private PdfWriter writer; - private static String predefinedSearchPath = ""; - private float leftMargin; - private float topMargin; - private float bottomMargin; - private PdfTemplate template; - private BaseFont templateFont; - private int templateFontSize; - private bool backFill = true; - private int templateAlignment; - private int pages = 0; - private bool templateCreated = false; - private bool asianFontsDllLoaded = false; - private static char[] TRIM_CHARS = { ' ' }; - private int M_top, M_bot; + protected static String predefinedSearchPath = ""; + protected float leftMargin; + protected float topMargin; + protected float bottomMargin; + protected int templateFontSize; + protected bool backFill = true; + protected int templateAlignment; + protected int pages = 0; + protected bool templateCreated = false; + protected static char[] TRIM_CHARS = { ' ' }; + protected int M_top, M_bot; public static float DASHES_UNITS_ON = 10; public static float DASHES_UNITS_OFF = 10; public static float DOTS_UNITS_OFF = 3; public static float DOTS_UNITS_ON = 1; public bool lineCapProjectingSquare = true; public bool barcode128AsImage = true; - private PdfConformanceLevel complianceLevel = PdfConformanceLevel.None; - internal Dictionary documentImages; - float[] STYLE_SOLID = new float[] { 1, 0 };//0 - float[] STYLE_NONE = null;//1 - float[] STYLE_DOTTED, //2 + protected PdfConformanceLevel complianceLevel = PdfConformanceLevel.None; + protected float[] STYLE_SOLID = new float[] { 1, 0 };//0 + protected float[] STYLE_NONE = null;//1 + protected float[] STYLE_DOTTED, //2 STYLE_DASHED, //3 STYLE_LONG_DASHED, //4 STYLE_LONG_DOT_DASHED; //5 - int STYLE_NONE_CONST = 1; - int runDirection; - int justifiedType; - static Assembly iTextAssembly = typeof(Document).Assembly; + protected int STYLE_NONE_CONST = 1; + protected int runDirection; + protected int MULTIPLIED_LEADING = 1; public bool GxOpenDoc(string fileName) { @@ -247,14 +232,11 @@ public static void showReport(String filename1, bool modal) } private static char alternateSeparator = Path.DirectorySeparatorChar == '/' ? '\\' : '/'; - public PDFReportItextSharp(String appPath) + public PDFReportItextBase(String appPath) { try { - document = null; - pageSize = null; stringTotalPages = new ArrayList(); - documentImages = new Dictionary(); defaultRelativePrepend = appPath; webAppDir = defaultRelativePrepend; if (appPath.Length > 0) @@ -417,27 +399,31 @@ public static String getPredefinedSearchPaths() return predefinedSearchPath; } - private void init() + protected virtual void init(ref int gxYPage, ref int gxXPage, int pageWidth, int pageLength) { - Document.Compress = true; - try + + } + private float[] parsePattern(String patternStr) + { + if (patternStr!=null) { - writer = PdfWriter.GetInstance(document, outputStream); - string level = props.getGeneralProperty(Const.COMPLIANCE_LEVEL); - if (Enum.TryParse(level, true, out complianceLevel)) + patternStr = patternStr.Trim(); + String[] values = patternStr.Split(new char[]{';'}); + if (values.Length>0) { - if (SetComplainceLevel(complianceLevel)) - writer.SetTagged(); + float[] pattern = new float[values.Length]; + for (int i=0; i diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj b/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj index a2a836154..4f74f4428 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj @@ -18,14 +18,14 @@ - - - - + + + + - + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj index e50e530ad..d17db6c17 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj @@ -7,7 +7,7 @@ - + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj index f66d540c0..644efe5e0 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj @@ -7,7 +7,7 @@ - + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj index c58643257..18dd71d4e 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj @@ -7,7 +7,7 @@ - + diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/GeneXus.OpenTelemetry.Azure.AppInsights.csproj b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/GeneXus.OpenTelemetry.Azure.AppInsights.csproj index 26bbe19b1..0f89f3098 100644 --- a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/GeneXus.OpenTelemetry.Azure.AppInsights.csproj +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/GeneXus.OpenTelemetry.Azure.AppInsights.csproj @@ -11,7 +11,7 @@ - + From e31cc8a2084402f21413ce326dbd6670b29b5c2c Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 31 Oct 2023 09:36:36 -0300 Subject: [PATCH 054/164] Sanitize user input before logging it. (#892) * Sanitize user input before logging it. * Sanitize user input before logging it. --- .../Azure/Handlers/QueueHandler/QueueTriggerHandler.cs | 8 ++++---- .../ServiceBusHandler/ServiceBusTriggerHandler.cs | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/dotnet/src/extensions/Azure/Handlers/QueueHandler/QueueTriggerHandler.cs b/dotnet/src/extensions/Azure/Handlers/QueueHandler/QueueTriggerHandler.cs index 13ecbbcda..35f7c93bf 100644 --- a/dotnet/src/extensions/Azure/Handlers/QueueHandler/QueueTriggerHandler.cs +++ b/dotnet/src/extensions/Azure/Handlers/QueueHandler/QueueTriggerHandler.cs @@ -30,7 +30,7 @@ public void Run(string myQueueItem, FunctionContext context) string functionName = context.FunctionDefinition.Name; QueueMessage queueMessage = SetupMessage(context, myQueueItem); - log.LogInformation($"GeneXus Queue trigger handler. Function processed: {functionName} Invocation Id: {context.InvocationId}. Queue item : {queueMessage.Id}"); + log.LogInformation($"GeneXus Queue trigger handler. Function processed: {functionName} Invocation Id: {context.InvocationId}. Queue item : {StringUtil.Sanitize(queueMessage.Id, StringUtil.LogUserEntryWhiteList)}"); try { @@ -197,20 +197,20 @@ private void ProcessMessage(FunctionContext context, ILogger log, QueueMessage q } catch (Exception) { - log.LogError("{0} Error invoking the GX procedure for Message Id {1}.", FunctionExceptionType.SysRuntimeError, queueMessage.Id); + log.LogError("{0} Error invoking the GX procedure for Message Id {1}.", FunctionExceptionType.SysRuntimeError, StringUtil.Sanitize(queueMessage.Id, StringUtil.LogUserEntryWhiteList)); throw; //Throw the exception so the runtime can Retry the operation. } } } else { - exMessage = string.Format("{0} GeneXus procedure could not be executed for Message Id {1}.", FunctionExceptionType.SysRuntimeError, queueMessage.Id); + exMessage = string.Format("{0} GeneXus procedure could not be executed for Message Id {1}.", FunctionExceptionType.SysRuntimeError, StringUtil.Sanitize(queueMessage.Id, StringUtil.LogUserEntryWhiteList)); throw new Exception(exMessage); } } catch (Exception) { - log.LogError("{0} Error processing Message Id {1}.", FunctionExceptionType.SysRuntimeError, queueMessage.Id); + log.LogError("{0} Error processing Message Id {1}.", FunctionExceptionType.SysRuntimeError, StringUtil.Sanitize(queueMessage.Id, StringUtil.LogUserEntryWhiteList)); throw; //Throw the exception so the runtime can Retry the operation. } } diff --git a/dotnet/src/extensions/Azure/Handlers/ServiceBusHandler/ServiceBusTriggerHandler.cs b/dotnet/src/extensions/Azure/Handlers/ServiceBusHandler/ServiceBusTriggerHandler.cs index 98d10130e..331728efb 100644 --- a/dotnet/src/extensions/Azure/Handlers/ServiceBusHandler/ServiceBusTriggerHandler.cs +++ b/dotnet/src/extensions/Azure/Handlers/ServiceBusHandler/ServiceBusTriggerHandler.cs @@ -31,7 +31,7 @@ public void Run(string myQueueItem, FunctionContext context) string functionName = context.FunctionDefinition.Name; Message message = SetupMessage(context, myQueueItem); - log.LogInformation($"GeneXus Service Bus trigger handler. Function processed: {functionName}. Queue item Id: {message.MessageId}"); + log.LogInformation($"GeneXus Service Bus trigger handler. Function processed: {functionName}. Queue item Id: {StringUtil.Sanitize(message.MessageId, StringUtil.LogUserEntryWhiteList)}"); try { @@ -236,7 +236,7 @@ private void ProcessMessage(FunctionContext context, ILogger log, Message messag } catch (Exception) { - exMessage = string.Format("{0} Error invoking the GX procedure for Message Id {1}.", FunctionExceptionType.SysRuntimeError, message.MessageId); + exMessage = string.Format("{0} Error invoking the GX procedure for Message Id {1}.", FunctionExceptionType.SysRuntimeError, StringUtil.Sanitize(message.MessageId, StringUtil.LogUserEntryWhiteList)); log.LogError(exMessage); throw; //Throw the exception so the runtime can Retry the operation. } @@ -250,7 +250,7 @@ private void ProcessMessage(FunctionContext context, ILogger log, Message messag } catch (Exception) { - log.LogError("{0} Error processing Message Id {1}.", FunctionExceptionType.SysRuntimeError, message.MessageId); + log.LogError("{0} Error processing Message Id {1}.", FunctionExceptionType.SysRuntimeError, StringUtil.Sanitize(message.MessageId, StringUtil.LogUserEntryWhiteList)); throw; //Throw the exception so the runtime can Retry the operation. } } From a868e1cecbd7c5f8531ec16ef701304d7a8e50b8 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 31 Oct 2023 09:37:12 -0300 Subject: [PATCH 055/164] Add a configuration key to disable the flattening of API object output (#891) * Add a configuration key to disable the flattening of API object output when it's a single SDT. * wrapped must be initialized in true at MethodUrlExecute. * For non api objects, wrapped is false by default. * Fix wron condition on FlattenSingleApiOutput. * Rename FlattenSingleApiOutput to WrapSingleApiOutput --- .../GxClasses/Core/gxconfig.cs | 12 +++++- .../GxClasses/Services/GxRestWrapper.cs | 42 ++++++++++++------- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs b/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs index 80b273938..deab7b67d 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs @@ -1377,7 +1377,17 @@ public static int SessionTimeout { return sessionTimeout; } } - + const bool DefaultWrapSingleApiOutput = false; + internal static bool WrapSingleApiOutput + { + get + { + if (Config.GetValueOf("WRAP_SINGLE_API_OUTPUT", out string flatten)) + return (int.TryParse(flatten, out int value) && value == 1); + else + return DefaultWrapSingleApiOutput; + } + } internal static string CorsAllowedOrigins() { if (Config.GetValueOf("CORS_ALLOW_ORIGIN", out string corsOrigin)) diff --git a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs index 7de521c68..ad837f6d6 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs @@ -142,8 +142,9 @@ public virtual Task MethodBodyExecute(object key) Dictionary formatParameters = ReflectionHelper.ParametersFormat(_procWorker, innerMethod); setWorkerStatus(_procWorker); _procWorker.cleanup(); + int originalParameterCount = outputParameters.Count; RestProcess(_procWorker, outputParameters); - wrapped = GetWrappedStatus(_procWorker, wrapped, outputParameters, outputParameters.Count); + wrapped = GetWrappedStatus(_procWorker, wrapped, outputParameters, outputParameters.Count, originalParameterCount); return Serialize(outputParameters, formatParameters, wrapped); } catch (Exception e) @@ -330,9 +331,10 @@ public virtual Task MethodUrlExecute(object key) int parCount = outputParameters.Count; setWorkerStatus(_procWorker); _procWorker.cleanup(); + int originalParameterCount = outputParameters.Count; RestProcess(_procWorker, outputParameters); bool wrapped = false; - wrapped = GetWrappedStatus(_procWorker, wrapped, outputParameters, parCount); + wrapped = GetWrappedStatus(_procWorker, wrapped, outputParameters, parCount, originalParameterCount); return Serialize(outputParameters, formatParameters, wrapped); } catch (Exception e) @@ -344,29 +346,37 @@ public virtual Task MethodUrlExecute(object key) Cleanup(); } } - bool GetWrappedStatus(GXBaseObject worker, bool wrapped, Dictionary outputParameters, int parCount) + bool GetWrappedStatus(GXBaseObject worker, bool defaultWrapped, Dictionary outputParameters, int parCount, int originalParCount) { + bool wrapped = defaultWrapped; if (worker.IsApiObject) { if (outputParameters.Count == 1) { - wrapped = false; - Object v = outputParameters.First().Value; - - if (v.GetType().GetInterfaces().Contains(typeof(IGxGenericCollectionWrapped))) + if ((originalParCount == 1) || (originalParCount > 1 && !Preferences.WrapSingleApiOutput)) { - IGxGenericCollectionWrapped icollwrapped = v as IGxGenericCollectionWrapped; - if (icollwrapped != null) - wrapped = icollwrapped.GetIsWrapped(); - } - if (v is IGxGenericCollectionItem item) - { - if (item.Sdt is GxSilentTrnSdt) + wrapped = false; + Object v = outputParameters.First().Value; + + if (v.GetType().GetInterfaces().Contains(typeof(IGxGenericCollectionWrapped))) { - wrapped = (parCount>1)?true:false; + IGxGenericCollectionWrapped icollwrapped = v as IGxGenericCollectionWrapped; + if (icollwrapped != null) + wrapped = icollwrapped.GetIsWrapped(); + } + if (v is IGxGenericCollectionItem item) + { + if (item.Sdt is GxSilentTrnSdt) + { + wrapped = (parCount > 1) ? true : false; + } } } - } + if (originalParCount > 1 && Preferences.WrapSingleApiOutput) + { + wrapped = true; //Ignore defaultWrapped parameter. + } + } } return wrapped; } From a849d02f765eca913af2ac963aadc2e6a6d3ed9c Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Wed, 1 Nov 2023 14:50:35 -0300 Subject: [PATCH 056/164] Logging implementation update (#871) --- .../DynService/Cosmos/CosmosDBConnection.cs | 3 +- .../DynService/Cosmos/CosmosDBDataReader.cs | 3 +- .../Cosmos/CosmosDBRequestWrapper.cs | 3 +- .../Cosmos/DynService.CosmosDB.csproj | 3 +- .../DynService/OData/DynServiceOData.csproj | 1 - .../GxClasses.Web/GxClasses.Web.csproj | 3 +- .../GxClasses.Web/Middleware/GXRouting.cs | 2 +- .../Middleware/HandlerFactory.cs | 2 +- .../Notifications/WebSocket/WSHandler.cs | 2 +- .../GxClasses/Domain/GXXmlReadWrite.cs | 14 +- .../src/dotnetcore/GxClasses/GxClasses.csproj | 8 +- .../GxClasses/Helpers/GXGeographyCore.cs | 2 +- .../AzureAppInsightsLogProvider.cs | 99 +++ .../Services/LogService/GXLogService.cs | 23 + .../OpenTelemetry/OpenTelemetryService.cs | 5 +- .../GxClasses/Services/ServiceSettings.cs | 8 +- .../Services/Session/GXSessionFactory.cs | 7 +- dotnet/src/dotnetcore/GxExcel/GxExcel.csproj | 1 - dotnet/src/dotnetcore/GxMail/GxMail.csproj | 1 - .../dotnetcore/GxNetCoreStartup/CsrfHelper.cs | 3 +- .../GxNetCoreStartup/GxNetCoreStartup.csproj | 9 +- .../Properties/AssemblyInfo.cs | 7 + .../dotnetcore/GxNetCoreStartup/Startup.cs | 62 +- .../src/dotnetcore/GxOffice/GxOffice.csproj | 1 - .../GxPdfReportsCS/GxPdfReportsCS.csproj | 5 +- .../GxPdfReportsCS/PDFReportItext8.cs | 4 +- .../src/dotnetcore/GxSearch/GxSearch.csproj | 1 - .../Cache/GxMemcached/GxMemcached.csproj | 3 +- .../Providers/Cache/GxRedis/GxRedis.csproj | 1 - .../Messaging/GXAmazonSQS/AWSQueue.cs | 2 +- .../GXAzureEventGrid/AzureEventGrid.cs | 2 +- .../GXAzureEventGrid/GXAzureEventGrid.csproj | 4 +- .../Messaging/GXAzureQueue/AzureQueue.cs | 4 +- .../GXAzureQueue/GXAzureQueue.csproj | 4 +- .../GXAzureServiceBus/AzureServiceBus.cs | 2 +- .../GXAzureServiceBus.csproj | 4 +- .../GXEventRouter/EventRouterBase.cs | 2 +- .../GXEventRouter/EventRouterProvider.cs | 2 +- .../GXEventRouter/EventRouterProviderBase.cs | 4 +- .../GXMessageBroker/MessageBrokerBase.cs | 2 +- .../GXMessageBroker/MessageBrokerProvider.cs | 2 +- .../Messaging/GXMessageBroker/MessageQueue.cs | 4 +- .../GXMessageBroker/ServiceSettings.cs | 2 +- .../Messaging/GXQueue/MessageQueueProvider.cs | 2 +- .../Providers/Messaging/GXQueue/QueueBase.cs | 2 +- .../Messaging/GXQueue/SimpleMessageQueue.cs | 4 +- .../AzureAppInsights.cs | 9 +- .../LightstepProvider.cs | 4 +- .../DynServiceOData/DynServiceOData.csproj | 1 - .../GxClasses.Win/GxClasses.Win.csproj | 3 +- .../GxClasses.Win/Process/CommandLine.cs | 3 +- .../Configuration/ExternalStorage.cs | 7 +- .../Configuration/LogConfiguration.cs | 10 +- .../GxClasses/Core/GXApplication.cs | 121 ++-- .../dotnetframework/GxClasses/Core/GXUtils.cs | 2 +- .../GxClasses/Core/GXUtilsCommon.cs | 18 +- .../GxClasses/Core/Web/HttpAjaxContext.cs | 2 +- .../GxClasses/Core/gxconfig.cs | 225 +++--- .../Cryptography/GXAsymmetricEncryption.cs | 16 +- .../GxClasses/Cryptography/GXCertificate.cs | 7 +- .../Cryptography/GXSymmetricEncryption.cs | 18 +- .../GxClasses/Data/GXDataADO.cs | 10 +- .../GxClasses/Data/GXDataCommon.cs | 31 +- .../GxClasses/Data/GXDataDb2.cs | 5 +- .../GxClasses/Data/GXDataDb2400.cs | 8 +- .../GxClasses/Data/GXDataHana.cs | 6 +- .../GxClasses/Data/GXDataInformix.cs | 6 +- .../GxClasses/Data/GXDataMysqlConnector.cs | 11 +- .../GxClasses/Data/GXDataMysqlDriverCS.cs | 7 +- .../GxClasses/Data/GXDataNTier.cs | 5 +- .../GxClasses/Data/GXDataNTierADO.cs | 6 +- .../GxClasses/Data/GXDataNTierService.cs | 7 +- .../GxClasses/Data/GXDataOracle.cs | 21 +- .../GxClasses/Data/GXDataPostgreSQL.cs | 4 +- .../GxClasses/Data/GXDataSqlite.cs | 5 +- .../GxClasses/Diagnostics/GXDebugManager.cs | 2 +- .../GxClasses/Diagnostics/Log.cs | 69 +- .../GxClasses/Dialog/IProcess.cs | 3 +- .../GxClasses/Domain/ExpressionEvaluator.cs | 2 +- .../GxClasses/Domain/GXFileIO.cs | 9 +- .../GxClasses/Domain/GXGeolocation.cs | 2 +- .../GxClasses/Domain/GXLDAP.cs | 2 +- .../GxClasses/Domain/GXXmlReadWrite.cs | 2 +- .../GxClasses/Domain/GxCollections.cs | 6 +- .../GxClasses/Domain/GxGenericCollections.cs | 4 +- .../GxClasses/Domain/GxHttpClient.cs | 2 +- .../GxClasses/Domain/GxMessaging.cs | 5 +- .../GxClasses/Domain/GxSession.cs | 2 +- .../GxClasses/Domain/SD/SDApis.cs | 4 +- .../GxClasses/GxClasses.csproj | 2 +- .../GxClasses/Helpers/GXFileWatcher.cs | 2 +- .../GxClasses/Helpers/GXLogging.cs | 677 +++++++++++++++++- .../GxClasses/Helpers/GXMetadata.cs | 2 +- .../GxClasses/Helpers/GXRes.cs | 2 +- .../GxClasses/Helpers/GXRestUtils.cs | 2 +- .../GxClasses/Helpers/GXUtilsGeospatial.cs | 4 +- .../GxClasses/Helpers/HttpHelper.cs | 2 +- .../GxClasses/Helpers/JSONHelper.cs | 2 +- .../GxClasses/Helpers/ThemeHelper.cs | 2 +- .../GxClasses/Management/GXManagement.cs | 13 +- .../GxClasses/Management/GXPerformance.cs | 4 +- .../GxClasses/Middleware/GXHttp.cs | 5 +- .../GxClasses/Middleware/GXHttpModules.cs | 4 +- .../GxClasses/Middleware/GXHttpServices.cs | 7 +- .../GxClasses/Middleware/HandlerFactory.cs | 2 +- .../GxClasses/Model/GXBaseObject.cs | 3 +- .../GxClasses/Model/GXSilentTrn.cs | 2 +- .../GxClasses/Model/GxMockProvider.cs | 2 +- .../dotnetframework/GxClasses/Model/gxproc.cs | 8 +- .../WebSocket/GXWebSocketFactory.cs | 5 +- .../GxClasses/Printer/GxPrinter.cs | 2 +- .../GxClasses/Reorg/GXReorg.cs | 2 +- .../GxClasses/Security/GxSecurityProvider.cs | 2 +- .../GxClasses/Security/WebSecurity.cs | 18 +- .../GxClasses/Services/Caching/GxCache.cs | 14 +- .../GxClasses/Services/GXRestServices.cs | 5 +- .../GxClasses/Services/GxRestWrapper.cs | 2 +- .../Services/Storage/ExternalProviderBase.cs | 10 +- .../GxClasses/Services/Storage/GXServices.cs | 21 +- .../GxClasses/View/GXWebControls.cs | 2 +- .../GXDataInitialization.cs | 2 +- .../GXDataInitialization.csproj | 5 - .../dotnetframework/GxExcel/GxExcel.csproj | 1 - .../dotnetframework/GxExcel/GxExcelEPPlus.cs | 8 +- .../src/dotnetframework/GxExcel/GxExcelI.cs | 12 +- .../dotnetframework/GxExcel/GxExcelLite.cs | 4 +- .../GxMail/Exchange/ExchangeSession.cs | 5 +- .../GxMail/Exchange/Service.cs | 6 +- .../GxMail/Exchange/TraceListener.cs | 12 +- .../dotnetframework/GxMail/GXMailSession.cs | 2 +- .../dotnetframework/GxMail/GXPOP3Session.cs | 3 +- .../dotnetframework/GxMail/GXSMTPSession.cs | 5 +- .../src/dotnetframework/GxMail/GxMail.csproj | 1 - .../src/dotnetframework/GxMail/MAPISession.cs | 3 +- .../src/dotnetframework/GxMail/MailMessage.cs | 2 +- .../GxMail/Mentalis/RFC822EndReader.cs | 2 +- .../dotnetframework/GxMail/OutlookSession.cs | 2 +- .../src/dotnetframework/GxMail/POP3Session.cs | 3 +- .../GxMail/POP3SessionOpenPop.cs | 4 +- .../src/dotnetframework/GxMail/Pop3MailKit.cs | 3 +- .../dotnetframework/GxMail/Pop3SessionBase.cs | 14 +- .../dotnetframework/GxMail/SMTP/SmtpHelper.cs | 2 +- .../dotnetframework/GxMail/SMTPMailClient.cs | 2 +- .../src/dotnetframework/GxMail/SMTPMailKit.cs | 2 +- .../src/dotnetframework/GxMail/SMTPSession.cs | 2 +- .../GxOffice/ExcelSpreadsheetGXWrapper.cs | 10 +- .../dotnetframework/GxOffice/GxOffice.csproj | 1 - .../GxOffice/poi/xssf/ExcelCells.cs | 5 +- .../GxOffice/poi/xssf/ExcelSpreadsheet.cs | 7 +- .../GxPdfReportsCS/GxPdfReportsCS.csproj | 5 - .../GxPdfReportsCS/PDFReportCommon.cs | 10 +- .../GxPdfReportsCS/PDFReportItext4.cs | 3 +- .../GxPdfReportsCS/PdfReportInterface.cs | 3 +- .../GxSearch/DocumentHandler.cs | 6 +- .../dotnetframework/GxSearch/GxSearch.csproj | 1 - .../src/dotnetframework/GxSearch/Indexer.cs | 2 +- .../src/dotnetframework/GxSearch/Searcher.cs | 2 +- .../src/dotnetframework/GxSearch/Settings.cs | 2 +- .../dotnetframework/GxSearch/SpellChecker.cs | 2 +- .../GxWebSocket/GXWebSocket.csproj | 1 - .../dotnetframework/GxWebSocket/WSHandler.cs | 6 +- .../StoreManager/Store/StoreManager.cs | 3 +- .../Projects/StoreManager/StoreManager.csproj | 3 +- .../Cache/GxMemcached/GxMemcached.cs | 2 +- .../Providers/Cache/GxRedis/GxRedis.cs | 3 +- .../Providers/Cache/GxRedis/GxRedis.csproj | 1 - .../Storage/GXAmazonS3/ExternalProviderS3.cs | 5 +- .../Storage/GXAmazonS3/GXAmazonS3.csproj | 1 - ...eXus.Deploy.AzureFunctions.Handlers.csproj | 6 +- .../HttpHandler/GXHttpAzureContextAccessor.cs | 2 +- .../AzureFunctionsTest.csproj | 1 + .../Middleware/RestServiceTest.cs | 4 - .../TestOpenTelemetry.cs | 10 +- .../DotNetCoreUnitTest.csproj | 11 +- .../{log.config => log.console.config} | 2 +- .../Middleware/MiddlewareTest.cs | 7 +- .../test/DotNetUnitTest/DotNetUnitTest.csproj | 5 + dotnet/test/DotNetUnitTest/Log/LogTest.cs | 19 + dotnet/test/DotNetUnitTest/log.console.config | 39 + 179 files changed, 1484 insertions(+), 669 deletions(-) create mode 100644 dotnet/src/dotnetcore/GxClasses/Services/LogService/AzureAppInsights/AzureAppInsightsLogProvider.cs create mode 100644 dotnet/src/dotnetcore/GxClasses/Services/LogService/GXLogService.cs create mode 100644 dotnet/src/dotnetcore/GxNetCoreStartup/Properties/AssemblyInfo.cs rename dotnet/test/DotNetCoreUnitTest/{log.config => log.console.config} (97%) create mode 100644 dotnet/test/DotNetUnitTest/Log/LogTest.cs create mode 100644 dotnet/test/DotNetUnitTest/log.console.config diff --git a/dotnet/src/dotnetcore/DynService/Cosmos/CosmosDBConnection.cs b/dotnet/src/dotnetcore/DynService/Cosmos/CosmosDBConnection.cs index 756d8c365..2d64302a9 100644 --- a/dotnet/src/dotnetcore/DynService/Cosmos/CosmosDBConnection.cs +++ b/dotnet/src/dotnetcore/DynService/Cosmos/CosmosDBConnection.cs @@ -12,7 +12,6 @@ using GeneXus.Cache; using GeneXus.Data.Cosmos; using GeneXus.Data.NTier.CosmosDB; -using log4net; using Microsoft.Azure.Cosmos; namespace GeneXus.Data.NTier @@ -65,7 +64,7 @@ public class CosmosDBConnection : ServiceConnection //Options not supported by the spec yet //private const string DISTINCT = "DISTINCT"; - static readonly ILog logger = log4net.LogManager.GetLogger(typeof(CosmosDBConnection)); + static readonly IGXLogger logger = GXLoggerFactory.GetLogger(); public override string ConnectionString { get diff --git a/dotnet/src/dotnetcore/DynService/Cosmos/CosmosDBDataReader.cs b/dotnet/src/dotnetcore/DynService/Cosmos/CosmosDBDataReader.cs index f74528139..45ee1b70a 100644 --- a/dotnet/src/dotnetcore/DynService/Cosmos/CosmosDBDataReader.cs +++ b/dotnet/src/dotnetcore/DynService/Cosmos/CosmosDBDataReader.cs @@ -9,7 +9,6 @@ using GeneXus.Cache; using GeneXus.Data.NTier; using GeneXus.Data.NTier.CosmosDB; -using log4net; using Microsoft.Azure.Cosmos; using Newtonsoft.Json; @@ -27,7 +26,7 @@ public class CosmosDBDataReader : IDataReader private int ItemCount; private List> Items = null; - static readonly ILog logger = log4net.LogManager.GetLogger(typeof(CosmosDBDataReader)); + static readonly IGXLogger logger = GXLoggerFactory.GetLogger(); private void CheckCurrentPosition() { if (m_currentEntry == null) diff --git a/dotnet/src/dotnetcore/DynService/Cosmos/CosmosDBRequestWrapper.cs b/dotnet/src/dotnetcore/DynService/Cosmos/CosmosDBRequestWrapper.cs index aaa3a62c2..faf6b9f97 100644 --- a/dotnet/src/dotnetcore/DynService/Cosmos/CosmosDBRequestWrapper.cs +++ b/dotnet/src/dotnetcore/DynService/Cosmos/CosmosDBRequestWrapper.cs @@ -3,7 +3,6 @@ using System.IO; using System.Threading.Tasks; using GeneXus.Data.Cosmos; -using log4net; using Microsoft.Azure.Cosmos; using Newtonsoft.Json; @@ -14,7 +13,7 @@ public class RequestWrapper private readonly Container m_container; private readonly CosmosClient m_cosmosClient; private readonly QueryDefinition m_queryDefinition; - static readonly ILog logger = log4net.LogManager.GetLogger(typeof(RequestWrapper)); + static readonly IGXLogger logger = GXLoggerFactory.GetLogger(); public string idValue { get; set; } public object partitionKeyValue { get; set; } public bool queryByPK { get; set; } diff --git a/dotnet/src/dotnetcore/DynService/Cosmos/DynService.CosmosDB.csproj b/dotnet/src/dotnetcore/DynService/Cosmos/DynService.CosmosDB.csproj index 120fad8f9..253f9f40c 100644 --- a/dotnet/src/dotnetcore/DynService/Cosmos/DynService.CosmosDB.csproj +++ b/dotnet/src/dotnetcore/DynService/Cosmos/DynService.CosmosDB.csproj @@ -13,7 +13,8 @@ - + + diff --git a/dotnet/src/dotnetcore/DynService/OData/DynServiceOData.csproj b/dotnet/src/dotnetcore/DynService/OData/DynServiceOData.csproj index 6626d65c7..ae4beeb73 100644 --- a/dotnet/src/dotnetcore/DynService/OData/DynServiceOData.csproj +++ b/dotnet/src/dotnetcore/DynService/OData/DynServiceOData.csproj @@ -13,7 +13,6 @@ - diff --git a/dotnet/src/dotnetcore/GxClasses.Web/GxClasses.Web.csproj b/dotnet/src/dotnetcore/GxClasses.Web/GxClasses.Web.csproj index 5d7ca697c..dc3708d0b 100644 --- a/dotnet/src/dotnetcore/GxClasses.Web/GxClasses.Web.csproj +++ b/dotnet/src/dotnetcore/GxClasses.Web/GxClasses.Web.csproj @@ -29,7 +29,8 @@ - + + diff --git a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs index 25573f464..f6d88c57c 100644 --- a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs +++ b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs @@ -28,7 +28,7 @@ namespace GxClasses.Web.Middleware internal class GXRouting : IGXRouting { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(IGXRouting)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public static string VirtualPath = string.Empty; public static string LocalPath = Directory.GetCurrentDirectory(); diff --git a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/HandlerFactory.cs b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/HandlerFactory.cs index 549b6ba9e..5296ca8dd 100644 --- a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/HandlerFactory.cs +++ b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/HandlerFactory.cs @@ -32,7 +32,7 @@ public class BaseUrls public class HandlerFactory { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.HttpHandlerFactory.HandlerFactory)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private string _basePath; static Dictionary _aspxObjects = new Dictionary(){ {"gxoauthlogout",typeof(GXOAuthLogout)}, diff --git a/dotnet/src/dotnetcore/GxClasses.Web/Notifications/WebSocket/WSHandler.cs b/dotnet/src/dotnetcore/GxClasses.Web/Notifications/WebSocket/WSHandler.cs index ae0051f63..92f15fc43 100644 --- a/dotnet/src/dotnetcore/GxClasses.Web/Notifications/WebSocket/WSHandler.cs +++ b/dotnet/src/dotnetcore/GxClasses.Web/Notifications/WebSocket/WSHandler.cs @@ -18,7 +18,7 @@ namespace GeneXus.Http.WebSocket { public class WSHandler: WebSocketHandler, IGXWebSocketAsync { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(WSHandler)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private const string GX_NOTIFICATIONINFO_NAME = "GeneXus.Core.genexus.server.SdtNotificationInfo"; protected static WebSocketConnectionManager WebSocketConnectionManager = new WebSocketConnectionManager(); diff --git a/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs b/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs index 71b13de71..aa04926c8 100644 --- a/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs +++ b/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs @@ -1,19 +1,17 @@ using System; -using System.Xml; using System.Collections; using System.Collections.Specialized; -using System.Text; -using System.Net; using System.IO; +using System.Net; +using System.Text; +using System.Xml; using System.Xml.Schema; +using System.Xml.XPath; +using System.Xml.Xsl; using GeneXus.Application; using GeneXus.Http.Client; using GeneXus.Http.Server; using GeneXus.Utils; -using log4net; - -using System.Xml.Xsl; -using System.Xml.XPath; namespace GeneXus.XML { @@ -1887,7 +1885,7 @@ public void Dispose() public class GXXMLWriter: IDisposable { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GXXMLWriter)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private XmlTextWriter writer; private short errorCode; diff --git a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj index b42acd3bc..2e8ab31ff 100644 --- a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj +++ b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj @@ -1,4 +1,4 @@ - + net6.0 @@ -157,6 +157,12 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + diff --git a/dotnet/src/dotnetcore/GxClasses/Helpers/GXGeographyCore.cs b/dotnet/src/dotnetcore/GxClasses/Helpers/GXGeographyCore.cs index f4b03d19a..e33b0802d 100644 --- a/dotnet/src/dotnetcore/GxClasses/Helpers/GXGeographyCore.cs +++ b/dotnet/src/dotnetcore/GxClasses/Helpers/GXGeographyCore.cs @@ -204,7 +204,7 @@ internal static object STRingN(object instance, int i) [DataContract] public class Geospatial : IGeographicNative { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Utils.Geospatial)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); internal const string EMPTY_GEOMETRY = "GEOMETRYCOLLECTION EMPTY"; const string EMPTY_GEOGRAPHY = "GEOGRAPHY EMPTY"; diff --git a/dotnet/src/dotnetcore/GxClasses/Services/LogService/AzureAppInsights/AzureAppInsightsLogProvider.cs b/dotnet/src/dotnetcore/GxClasses/Services/LogService/AzureAppInsights/AzureAppInsightsLogProvider.cs new file mode 100644 index 000000000..a5b7fbf2a --- /dev/null +++ b/dotnet/src/dotnetcore/GxClasses/Services/LogService/AzureAppInsights/AzureAppInsightsLogProvider.cs @@ -0,0 +1,99 @@ +using System; +using Azure.Monitor.OpenTelemetry.Exporter; +using Microsoft.Extensions.Logging; +using OpenTelemetry.Logs; + +namespace GeneXus.Services.Log +{ + public class AzureAppInsightsLogProvider : ILoggerFactory + { + private static string APPLICATIONINSIGHTS_CONNECTION_STRING = "APPLICATIONINSIGHTS_CONNECTION_STRING"; + private const string LOG_LEVEL_ENVVAR = "GX_LOG_LEVEL"; + public static ILoggerFactory loggerFactory; + + public static ILoggerFactory GetAzureMonitorLoggerFactory() + { + string appInsightsConnection = Environment.GetEnvironmentVariable(APPLICATIONINSIGHTS_CONNECTION_STRING); + try + { + + if (appInsightsConnection != null) + { + string loglevelvalue = Environment.GetEnvironmentVariable(LOG_LEVEL_ENVVAR); + LogLevel loglevel = LogLevel.Information; + if (!string.IsNullOrEmpty(loglevelvalue)) + { + Enum.TryParse(loglevelvalue, out loglevel); + } + loggerFactory = LoggerFactory.Create(builder => + { + builder.AddOpenTelemetry(options => + { + options.AddAzureMonitorLogExporter(o => o.ConnectionString = appInsightsConnection); + options.AddConsoleExporter(); + }).SetMinimumLevel(loglevel); + }); + } + else + { + throw new ArgumentNullException(APPLICATIONINSIGHTS_CONNECTION_STRING, "Opentelemetry Provider is Azure Monitor. Application Insight Log could not be initialized due to missing APPLICATIONINSIGHTS_CONNECTION_STRING environment variable."); + } + } + catch (Exception ex) + { + throw ex; + } + + return loggerFactory; + } + + public static ILoggerFactory GetLoggerFactory() + { + string appInsightsConnection = Environment.GetEnvironmentVariable(APPLICATIONINSIGHTS_CONNECTION_STRING); + try + { + + if (appInsightsConnection != null) + { + string loglevelvalue = Environment.GetEnvironmentVariable(LOG_LEVEL_ENVVAR); + LogLevel loglevel = LogLevel.Information; + if (!string.IsNullOrEmpty(loglevelvalue)) + { + Enum.TryParse(loglevelvalue, out loglevel); + } + loggerFactory = LoggerFactory.Create(builder => builder.AddApplicationInsights( + + configureTelemetryConfiguration: (config) => + config.ConnectionString = appInsightsConnection, + configureApplicationInsightsLoggerOptions: (options) => { } + ).SetMinimumLevel(loglevel) + ); + } + else + { + throw new ArgumentNullException(APPLICATIONINSIGHTS_CONNECTION_STRING, "LogOutput is Application Insights. Application Insight Log could not be initialized due to missing APPLICATIONINSIGHTS_CONNECTION_STRING environment variable."); + } + } + catch (Exception ex) + { + throw ex; + } + + return loggerFactory; + } + + public void AddProvider(ILoggerProvider provider) + { + loggerFactory.AddProvider(provider); + } + public void Dispose() + { + loggerFactory.Dispose(); + } + public ILogger CreateLogger(string name) + { + return loggerFactory.CreateLogger(name); + } + + } +} \ No newline at end of file diff --git a/dotnet/src/dotnetcore/GxClasses/Services/LogService/GXLogService.cs b/dotnet/src/dotnetcore/GxClasses/Services/LogService/GXLogService.cs new file mode 100644 index 000000000..cc455dbdc --- /dev/null +++ b/dotnet/src/dotnetcore/GxClasses/Services/LogService/GXLogService.cs @@ -0,0 +1,23 @@ +using GeneXus.Configuration; +using Microsoft.Extensions.Logging; + +namespace GeneXus.Services.Log +{ + public static class GXLogService + { + private static string AZURE_APPLICATION_INSIGHTS_LOG = "AZUREAPPLICATIONINSIGHTS"; + const string OTEL_AZUREMONITOR_EXPORTER = "OTEL_AZUREMONITOR_EXPORTER"; + const string LOG_OUTPUT = "LOG_OUTPUT"; + public static ILoggerFactory GetLogFactory() + { + if (Config.GetValueOf(LOG_OUTPUT, out string logProvider)) + { + if (logProvider == OTEL_AZUREMONITOR_EXPORTER) + return AzureAppInsightsLogProvider.GetAzureMonitorLoggerFactory(); + else if (logProvider == AZURE_APPLICATION_INSIGHTS_LOG) + return AzureAppInsightsLogProvider.GetLoggerFactory(); + } + return null; + } + } +} diff --git a/dotnet/src/dotnetcore/GxClasses/Services/OpenTelemetry/OpenTelemetryService.cs b/dotnet/src/dotnetcore/GxClasses/Services/OpenTelemetry/OpenTelemetryService.cs index 125f05ff5..9e17ad7ce 100644 --- a/dotnet/src/dotnetcore/GxClasses/Services/OpenTelemetry/OpenTelemetryService.cs +++ b/dotnet/src/dotnetcore/GxClasses/Services/OpenTelemetry/OpenTelemetryService.cs @@ -11,7 +11,8 @@ public interface IOpenTelemetryProvider public static class OpenTelemetryService { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(OpenTelemetryService)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + private static string OPENTELEMETRY_SERVICE = "Observability"; public static string GX_ACTIVITY_SOURCE_NAME = "GeneXus.Tracing"; @@ -49,7 +50,7 @@ internal static void Setup(Microsoft.Extensions.DependencyInjection.IServiceColl bool started = provider.InstrumentAspNetCoreApplication(services); if (started) { - log.Info("OpenTelemetry instrumentation started"); + GXLogging.Info(log, "OpenTelemetry instrumentation started"); } } } diff --git a/dotnet/src/dotnetcore/GxClasses/Services/ServiceSettings.cs b/dotnet/src/dotnetcore/GxClasses/Services/ServiceSettings.cs index 2249548f0..05c398a7e 100644 --- a/dotnet/src/dotnetcore/GxClasses/Services/ServiceSettings.cs +++ b/dotnet/src/dotnetcore/GxClasses/Services/ServiceSettings.cs @@ -6,7 +6,7 @@ namespace GeneXus.Services.Common { public class ServiceSettingsReader { - static readonly ILog logger = log4net.LogManager.GetLogger(typeof(ServiceSettingsReader)); + static readonly IGXLogger logger = GXLoggerFactory.GetLogger(); internal GXService service; public string serviceNameResolver { get; } @@ -25,7 +25,7 @@ public string GetEncryptedPropertyValue(string propertyName) if (value == null) { String errorMessage = String.Format($"Service configuration error - Property name {ResolvePropertyName(propertyName)} must be defined"); - logger.Fatal(errorMessage); + GXLogging.Critical(logger, errorMessage); throw new Exception(errorMessage); } return value; @@ -45,7 +45,7 @@ public string GetEncryptedPropertyValue(string propertyName, string defaultValue } catch (Exception) { - logger.Warn($"Could not decrypt property name: {ResolvePropertyName(propertyName)}"); + GXLogging.Warn(logger, $"Could not decrypt property name: {ResolvePropertyName(propertyName)}"); } } return value; @@ -57,7 +57,7 @@ public string GetPropertyValue(string propertyName) if (value == null) { String errorMessage = String.Format($"Service configuration error - Property name {ResolvePropertyName(propertyName)} must be defined"); - logger.Fatal(errorMessage); + GXLogging.Critical(logger, errorMessage); throw new Exception(errorMessage); } return value; diff --git a/dotnet/src/dotnetcore/GxClasses/Services/Session/GXSessionFactory.cs b/dotnet/src/dotnetcore/GxClasses/Services/Session/GXSessionFactory.cs index 51e578ce0..022d21373 100644 --- a/dotnet/src/dotnetcore/GxClasses/Services/Session/GXSessionFactory.cs +++ b/dotnet/src/dotnetcore/GxClasses/Services/Session/GXSessionFactory.cs @@ -11,7 +11,8 @@ namespace GeneXus.Services { public class GXSessionServiceFactory { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GXSessionServiceFactory)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + static string REDIS = "REDIS"; static string DATABASE = "DATABASE"; public static ISessionService GetProvider() @@ -58,7 +59,7 @@ public static ISessionService GetProvider() } public class GxRedisSession : ISessionService { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GxRedisSession)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); internal static string SESSION_ADDRESS = "SESSION_PROVIDER_ADDRESS"; internal static string SESSION_INSTANCE = "SESSION_PROVIDER_INSTANCE_NAME"; internal static string SESSION_PASSWORD = "SESSION_PROVIDER_PASSWORD"; @@ -108,7 +109,7 @@ public GxRedisSession(string host, string password, string instanceName, int ses } public class GxDatabaseSession : ISessionService { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GxDatabaseSession)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); internal static string SESSION_ADDRESS = "SESSION_PROVIDER_ADDRESS"; internal static string SESSION_PASSWORD = "SESSION_PROVIDER_PASSWORD"; internal static string SESSION_SCHEMA = "SESSION_PROVIDER_SCHEMA"; diff --git a/dotnet/src/dotnetcore/GxExcel/GxExcel.csproj b/dotnet/src/dotnetcore/GxExcel/GxExcel.csproj index 365ebaf33..95f6df2d8 100644 --- a/dotnet/src/dotnetcore/GxExcel/GxExcel.csproj +++ b/dotnet/src/dotnetcore/GxExcel/GxExcel.csproj @@ -17,7 +17,6 @@ - diff --git a/dotnet/src/dotnetcore/GxMail/GxMail.csproj b/dotnet/src/dotnetcore/GxMail/GxMail.csproj index aa513282b..50db5ccbf 100644 --- a/dotnet/src/dotnetcore/GxMail/GxMail.csproj +++ b/dotnet/src/dotnetcore/GxMail/GxMail.csproj @@ -66,7 +66,6 @@ - diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/CsrfHelper.cs b/dotnet/src/dotnetcore/GxNetCoreStartup/CsrfHelper.cs index 4005ca78a..4f6c15b71 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/CsrfHelper.cs +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/CsrfHelper.cs @@ -11,8 +11,7 @@ namespace GeneXus.Application { public class ValidateAntiForgeryTokenMiddleware { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(ValidateAntiForgeryTokenMiddleware)); - + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private readonly RequestDelegate _next; private readonly IAntiforgery _antiforgery; private string _basePath; diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj b/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj index 4f74f4428..6028dd9b1 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj @@ -18,10 +18,11 @@ - - - - + + + + + diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/Properties/AssemblyInfo.cs b/dotnet/src/dotnetcore/GxNetCoreStartup/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..e3c540157 --- /dev/null +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/Properties/AssemblyInfo.cs @@ -0,0 +1,7 @@ +using System.Runtime.CompilerServices; + + +[assembly: InternalsVisibleTo("DotNetCoreOpenTelemetryTest")] +[assembly: InternalsVisibleTo("DotNetCoreWebUnitTest")] + + diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs index f9620a042..3c9dc0804 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs @@ -12,7 +12,6 @@ using GeneXus.Services.OpenTelemetry; using GeneXus.Utils; using GxClasses.Web.Middleware; -using log4net; using Microsoft.AspNetCore; using Microsoft.AspNetCore.Antiforgery; using Microsoft.AspNetCore.Builder; @@ -34,7 +33,6 @@ using OpenTelemetry.Resources; using StackExchange.Redis; - namespace GeneXus.Application { public class Program @@ -42,9 +40,6 @@ public class Program const string DEFAULT_PORT = "80"; static string DEFAULT_SCHEMA = Uri.UriSchemeHttp; - private static string OPENTELEMETRY_SERVICE = "Observability"; - private static string OPENTELEMETRY_AZURE_DISTRO = "GeneXus.OpenTelemetry.Azure.AzureAppInsights"; - private static string APPLICATIONINSIGHTS_CONNECTION_STRING = "APPLICATIONINSIGHTS_CONNECTION_STRING"; public static void Main(string[] args) { try @@ -82,12 +77,11 @@ public static void Main(string[] args) } public static IWebHost BuildWebHost(string[] args) => - WebHost.CreateDefaultBuilder(args) - .ConfigureLogging(WebHostConfigureLogging) + WebHost.CreateDefaultBuilder(args) .UseStartup() .UseContentRoot(Startup.LocalPath) .Build(); - + public static IWebHost BuildWebHostPort(string[] args, string port) { return BuildWebHostPort(args, port, DEFAULT_SCHEMA); @@ -95,46 +89,12 @@ public static IWebHost BuildWebHostPort(string[] args, string port) static IWebHost BuildWebHostPort(string[] args, string port, string schema) { return WebHost.CreateDefaultBuilder(args) - .ConfigureLogging(WebHostConfigureLogging) .UseUrls($"{schema}://*:{port}") .UseStartup() .UseContentRoot(Startup.LocalPath) .Build(); } - private static void WebHostConfigureLogging(WebHostBuilderContext hostingContext, ILoggingBuilder loggingBuilder) - { - loggingBuilder.AddConsole(); - GXService providerService = GXServices.Instance?.Get(OPENTELEMETRY_SERVICE); - if (providerService != null && providerService.ClassName.StartsWith(OPENTELEMETRY_AZURE_DISTRO)) - { - ConfigureAzureOpentelemetry(loggingBuilder); - } - } - private static void ConfigureAzureOpentelemetry(ILoggingBuilder loggingBuilder) - { - string endpoint = Environment.GetEnvironmentVariable(APPLICATIONINSIGHTS_CONNECTION_STRING); - var resourceBuilder = ResourceBuilder.CreateDefault() - .AddTelemetrySdk(); - - loggingBuilder.AddOpenTelemetry(loggerOptions => - { - loggerOptions - .SetResourceBuilder(resourceBuilder) - .AddAzureMonitorLogExporter(options => - { - if (!string.IsNullOrEmpty(endpoint)) - options.ConnectionString = endpoint; - else - options.Credential = new DefaultAzureCredential(); - }) - .AddConsoleExporter(); - - loggerOptions.IncludeFormattedMessage = true; - loggerOptions.IncludeScopes = true; - loggerOptions.ParseStateValues = true; - }); - } private static void LocatePhysicalLocalPath() { string startup = FileUtil.GetStartupDirectory(); @@ -142,7 +102,6 @@ private static void LocatePhysicalLocalPath() if (startup == Startup.LocalPath && !File.Exists(Path.Combine(startup, Startup.APP_SETTINGS)) && File.Exists(Path.Combine(startupParent, Startup.APP_SETTINGS))) Startup.LocalPath = startupParent; } - } public static class GXHandlerExtensions @@ -164,9 +123,10 @@ public static IApplicationBuilder MapWebSocketManager(this IApplicationBuilder a } public class Startup - { + { + static IGXLogger log; + internal static string APPLICATIONINSIGHTS_CONNECTION_STRING = "APPLICATIONINSIGHTS_CONNECTION_STRING"; - static readonly ILog log = log4net.LogManager.GetLogger(typeof(Startup)); const long DEFAULT_MAX_FILE_UPLOAD_SIZE_BYTES = 528000000; public static string VirtualPath = string.Empty; public static string LocalPath = Directory.GetCurrentDirectory(); @@ -189,14 +149,15 @@ public class Startup public List servicesBase = new List(); private GXRouting gxRouting; - public Startup(IConfiguration configuration, IHostingEnvironment env) { Config.ConfigRoot = configuration; + GxContext.IsHttpContext = true; + Config.LoadConfiguration(); GXRouting.ContentRootPath = env.ContentRootPath; GXRouting.UrlTemplateControllerWithParms = "controllerWithParms"; - GxContext.IsHttpContext = true; gxRouting = new GXRouting(REST_BASE_URL); + log = GXLoggerFactory.GetLogger(); } public void ConfigureServices(IServiceCollection services) { @@ -213,7 +174,7 @@ public void ConfigureServices(IServiceCollection services) options.AllowSynchronousIO = true; }); services.AddDistributedMemoryCache(); - + services.AddLogging(builder => builder.AddConsole()); services.Configure(options => { if (Config.GetValueOf("MaxFileUploadSize", out string MaxFileUploadSizeStr) && long.TryParse(MaxFileUploadSizeStr, out long MaxFileUploadSize)) @@ -339,7 +300,8 @@ private void ConfigureSessionService(IServiceCollection services, ISessionServic public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHostingEnvironment env, ILoggerFactory loggerFactory) { string baseVirtualPath = string.IsNullOrEmpty(VirtualPath) ? VirtualPath : $"/{VirtualPath}"; - LogConfiguration.SetupLog4Net(); + LogConfiguration.SetupLog4Net(); + var provider = new FileExtensionContentTypeProvider(); //mappings provider.Mappings[".json"] = "application/json"; @@ -535,7 +497,7 @@ bool IsAspx(HttpContext context, string basePath) public class CustomExceptionHandlerMiddleware { const string InvalidCSRFToken = "InvalidCSRFToken"; - static readonly ILog log = log4net.LogManager.GetLogger(typeof(CustomExceptionHandlerMiddleware)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public async Task Invoke(HttpContext httpContext) { string httpReasonPhrase=string.Empty; diff --git a/dotnet/src/dotnetcore/GxOffice/GxOffice.csproj b/dotnet/src/dotnetcore/GxOffice/GxOffice.csproj index 4a31a7b68..58b337cfa 100644 --- a/dotnet/src/dotnetcore/GxOffice/GxOffice.csproj +++ b/dotnet/src/dotnetcore/GxOffice/GxOffice.csproj @@ -35,7 +35,6 @@ - diff --git a/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj b/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj index c9d5311c5..2d941fcda 100644 --- a/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj +++ b/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj @@ -19,10 +19,9 @@ - + - - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportItext8.cs b/dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportItext8.cs index 6c2918fce..04cda142a 100644 --- a/dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportItext8.cs +++ b/dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportItext8.cs @@ -33,7 +33,7 @@ namespace GeneXus.Printer { public class GxReportBuilderPdf8 : GxReportBuilderPdf { - static ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static IGXLogger log = GXLoggerFactory.GetLogger(); public GxReportBuilderPdf8() { } public GxReportBuilderPdf8(string appPath, Stream outputStream) { @@ -53,8 +53,8 @@ namespace com.genexus.reports public class PDFReportItext8 : PDFReportItextBase { + static IGXLogger log = GXLoggerFactory.GetLogger(); - static ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); //const int ASCENT_NORMALIZED_UNITS = 1000; private PageSize pageSize; diff --git a/dotnet/src/dotnetcore/GxSearch/GxSearch.csproj b/dotnet/src/dotnetcore/GxSearch/GxSearch.csproj index 826d61a8b..a56b1af66 100644 --- a/dotnet/src/dotnetcore/GxSearch/GxSearch.csproj +++ b/dotnet/src/dotnetcore/GxSearch/GxSearch.csproj @@ -20,7 +20,6 @@ - diff --git a/dotnet/src/dotnetcore/Providers/Cache/GxMemcached/GxMemcached.csproj b/dotnet/src/dotnetcore/Providers/Cache/GxMemcached/GxMemcached.csproj index 46337bb8a..7b96da27f 100644 --- a/dotnet/src/dotnetcore/Providers/Cache/GxMemcached/GxMemcached.csproj +++ b/dotnet/src/dotnetcore/Providers/Cache/GxMemcached/GxMemcached.csproj @@ -15,8 +15,7 @@ - - + diff --git a/dotnet/src/dotnetcore/Providers/Cache/GxRedis/GxRedis.csproj b/dotnet/src/dotnetcore/Providers/Cache/GxRedis/GxRedis.csproj index d83ab1b7f..ef7f8104e 100644 --- a/dotnet/src/dotnetcore/Providers/Cache/GxRedis/GxRedis.csproj +++ b/dotnet/src/dotnetcore/Providers/Cache/GxRedis/GxRedis.csproj @@ -18,7 +18,6 @@ - diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs index 1e76f3b24..071ea69fc 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs @@ -31,7 +31,7 @@ public class AWSQueue : QueueBase, IQueue public const string MESSSAGE_GROUP_ID = "MessageGroupId"; public const string MESSSAGE_DEDUPLICATION_ID = "MessageDeduplicationId"; - static readonly ILog logger = log4net.LogManager.GetLogger(typeof(AWSQueue)); + static readonly IGXLogger logger = GXLoggerFactory.GetLogger(); public AWSQueue() : this(null) { diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/AzureEventGrid.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/AzureEventGrid.cs index 921497aac..f69a69466 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/AzureEventGrid.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/AzureEventGrid.cs @@ -20,7 +20,7 @@ public class AzureEventGrid : EventRouterBase, IEventRouter private EventGridPublisherClient _client; private string _endpoint; private string _accessKey; - static readonly ILog logger = LogManager.GetLogger(typeof(AzureEventGrid)); + static readonly IGXLogger logger = GXLoggerFactory.GetLogger(); public AzureEventGrid() : this(null) { } diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj index d17db6c17..2f000f396 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj @@ -7,8 +7,10 @@ + - + + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs index 0435a7a55..519dce15a 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs @@ -8,6 +8,7 @@ using GeneXus.Services; using GeneXus.Utils; using log4net; +using Microsoft.Extensions.Logging; namespace GeneXus.Messaging.Queue { @@ -15,7 +16,8 @@ public class AzureQueue : QueueBase, IQueue { public static string Name = "AZUREQUEUE"; - static readonly ILog logger = LogManager.GetLogger(typeof(AzureQueue)); + static readonly IGXLogger logger = GXLoggerFactory.GetLogger(); + QueueClient _queueClient { get; set; } private string _queueName { get; set; } private string _connectionString { get; set; } diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj index 644efe5e0..3f5265ff9 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj @@ -7,8 +7,10 @@ + - + + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/AzureServiceBus.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/AzureServiceBus.cs index c44390a41..92e06e744 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/AzureServiceBus.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/AzureServiceBus.cs @@ -18,7 +18,7 @@ public class AzureServiceBus : MessageBrokerBase, IMessageBroker private const int MAX_MESSAGES_DEFAULT = 10; private const short LOCK_DURATION = 5; public static string Name = "AZURESB"; - static readonly ILog logger = LogManager.GetLogger(typeof(AzureServiceBus)); + static readonly IGXLogger logger = GXLoggerFactory.GetLogger(); private ConcurrentDictionary> m_messages = new ConcurrentDictionary>(); ServiceBusClient _serviceBusClient { get; set; } diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj index 18dd71d4e..121e87165 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj @@ -7,8 +7,10 @@ + - + + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterBase.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterBase.cs index d8db3aeb0..5b9e802fa 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterBase.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterBase.cs @@ -6,7 +6,7 @@ namespace GeneXus.Messaging.Common { public abstract class EventRouterBase { - static readonly ILog logger = LogManager.GetLogger(typeof(EventRouterBase)); + static readonly IGXLogger logger = GXLoggerFactory.GetLogger(); internal GXService service; public EventRouterBase() { diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterProvider.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterProvider.cs index 410543865..f635107ec 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterProvider.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterProvider.cs @@ -11,7 +11,7 @@ namespace GeneXus.Messaging.Common [GXApi] public class EventRouterProvider : EventRouterProviderBase { - static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static readonly IGXLogger logger = GXLoggerFactory.GetLogger(); private static GXService providerService; public EventRouterProvider() { } diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterProviderBase.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterProviderBase.cs index 2ab0a67c8..7514c6b04 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterProviderBase.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterProviderBase.cs @@ -14,7 +14,7 @@ public class EventRouterProviderBase { internal IEventRouter eventRouter = null; public static Assembly assembly; - static readonly ILog logger = LogManager.GetLogger(typeof(EventRouterProviderBase)); + static readonly IGXLogger logger = GXLoggerFactory.GetLogger(); private const string MODULE_DLL = @"GeneXusEventMessaging"; public EventRouterProviderBase() @@ -179,7 +179,7 @@ private GXCloudEvent ToGXCloudEvent(GxUserType evt) internal class ServiceFactory { private static IEventRouter eventRouter; - private static readonly ILog log = LogManager.GetLogger(typeof(Services.ServiceFactory)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public static GXServices GetGXServices() { diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageBrokerBase.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageBrokerBase.cs index 9f1e2ac80..7fbd6a18d 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageBrokerBase.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageBrokerBase.cs @@ -6,7 +6,7 @@ namespace GeneXus.Messaging.Common { public abstract class MessageBrokerBase { - static readonly ILog logger = log4net.LogManager.GetLogger(typeof(MessageBrokerBase)); + static readonly IGXLogger logger = GXLoggerFactory.GetLogger(); internal GXService service; public MessageBrokerBase() { diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageBrokerProvider.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageBrokerProvider.cs index c4bc73447..433a9a211 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageBrokerProvider.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageBrokerProvider.cs @@ -11,7 +11,7 @@ namespace GeneXus.Messaging.Common [GXApi] public class MessageBrokerProvider : MessageQueue { - static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static readonly IGXLogger logger = GXLoggerFactory.GetLogger(); private static GXService providerService; public MessageBrokerProvider() { diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageQueue.cs index 9f2a58649..2044de050 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageQueue.cs @@ -14,7 +14,7 @@ public class MessageQueue { internal IMessageBroker messageBroker = null; public static Assembly assembly; - static readonly ILog logger = log4net.LogManager.GetLogger(typeof(MessageQueue)); + static readonly IGXLogger logger = GXLoggerFactory.GetLogger(); private const string SDT_MESSAGE_CLASS_NAME = @"SdtMessage"; private const string SDT_MESSAGEPROPERTY_CLASS_NAME = @"SdtMessageProperty"; private const string NAMESPACE = @"GeneXus.Programs.genexusmessagingmessagebroker"; @@ -345,7 +345,7 @@ private BrokerMessage TransformGXUserTypeToBrokerMessage(GxUserType queueMessage internal class ServiceFactory { private static IMessageBroker messageBroker; - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Services.ServiceFactory)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public static GXServices GetGXServices() { diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/ServiceSettings.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/ServiceSettings.cs index c6cf8ce03..d29c55ab0 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/ServiceSettings.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/ServiceSettings.cs @@ -7,7 +7,7 @@ namespace GeneXus.Messaging.Common { public class ServiceSettings { - static readonly ILog logger = LogManager.GetLogger(typeof(ServiceSettings)); + static readonly IGXLogger logger = GXLoggerFactory.GetLogger(); internal GXService service; public string serviceNameResolver { get; } diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs index a3cbe8034..93a4ba066 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs @@ -11,7 +11,7 @@ namespace GeneXus.Messaging.Common [GXApi] public class MessageQueueProvider : SimpleMessageQueue { - static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static readonly IGXLogger logger = GXLoggerFactory.GetLogger(); private static GXService providerService; public MessageQueueProvider(){ } diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/QueueBase.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/QueueBase.cs index d8b80fdea..b43c47b1b 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/QueueBase.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/QueueBase.cs @@ -10,7 +10,7 @@ namespace GeneXus.Messaging.Common { public abstract class QueueBase { - static readonly ILog logger = log4net.LogManager.GetLogger(typeof(QueueBase)); + static readonly IGXLogger logger = GXLoggerFactory.GetLogger(); internal GXService service; public QueueBase() { diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs index e243ca161..dd5d35031 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs @@ -16,7 +16,7 @@ public class SimpleMessageQueue { internal IQueue queue = null; public static Assembly assembly; - static readonly ILog logger = log4net.LogManager.GetLogger(typeof(SimpleMessageQueue)); + static readonly IGXLogger logger = GXLoggerFactory.GetLogger(); private const string SDT_MESSAGE_CLASS_NAME = @"SdtMessage"; private const string SDT_MESSAGEPROPERTY_CLASS_NAME = @"SdtMessageProperty"; private const string SDT_MESSAGERESULT_CLASS_NAME = @"SdtMessageResult"; @@ -434,7 +434,7 @@ protected void QueueErrorMessagesSetup(Exception ex, out GXBaseCollection(); public static GXServices GetGXServices() { diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/AzureAppInsights.cs b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/AzureAppInsights.cs index 5b9a30550..98d6c7d1c 100644 --- a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/AzureAppInsights.cs +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/AzureAppInsights.cs @@ -3,7 +3,6 @@ using Azure.Monitor.OpenTelemetry.Exporter; using GeneXus.Services; using GeneXus.Services.OpenTelemetry; -using log4net; using Microsoft.Extensions.DependencyInjection; using OpenTelemetry; using OpenTelemetry.Logs; @@ -15,7 +14,7 @@ namespace GeneXus.OpenTelemetry.Azure { public class AzureAppInsights : IOpenTelemetryProvider { - private static readonly ILog log = LogManager.GetLogger(typeof(AzureAppInsights)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private const string APPLICATIONINSIGHTS_CONNECTION_STRING = "APPLICATIONINSIGHTS_CONNECTION_STRING"; public AzureAppInsights(GXService s) @@ -39,7 +38,7 @@ public bool InstrumentAspNetCoreApplication(IServiceCollection _) else { o.Credential = new DefaultAzureCredential(); - log.Debug("Connect to Azure monitor Opentelemetry Trace exporter using Default Azure credential"); + GXLogging.Debug(log, "Connect to Azure monitor Opentelemetry Trace exporter using Default Azure credential"); } }) .AddGxAspNetInstrumentation() @@ -54,7 +53,7 @@ public bool InstrumentAspNetCoreApplication(IServiceCollection _) else { o.Credential = new DefaultAzureCredential(); - log.Debug("Connect to Azure monitor Opentelemetry Metrics exporter using Default Azure credential"); + GXLogging.Debug(log, "Connect to Azure monitor Opentelemetry Metrics exporter using Default Azure credential"); } }) .Build(); @@ -62,7 +61,7 @@ public bool InstrumentAspNetCoreApplication(IServiceCollection _) } catch (Exception ex) { - log.Warn("Azure Monitor Opentelemetry could not be initialized. " + ex.Message); + GXLogging.Warn(log, "Azure Monitor Opentelemetry could not be initialized. " + ex.Message); return false; } } diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryLightStep/LightstepProvider.cs b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryLightStep/LightstepProvider.cs index 228b579ff..8b4f5195a 100644 --- a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryLightStep/LightstepProvider.cs +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryLightStep/LightstepProvider.cs @@ -13,7 +13,7 @@ namespace GeneXus.OpenTelemetry.Lightstep public class LightStepOpenTelemetry : IOpenTelemetryProvider { - private static readonly ILog log = LogManager.GetLogger(typeof(LightStepOpenTelemetry)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private const string LIGHTSTEP_INGREST_URL = "ingest.lightstep.com:443"; private const string LIGHTSTEP_ACCESS_TOKEN = "LS_ACCESS_TOKEN"; @@ -27,7 +27,7 @@ public bool InstrumentAspNetCoreApplication(IServiceCollection services) if (string.IsNullOrEmpty(lightstepToken)) { - log.Warn("OpenTelemetry Lightstep was not initialized due to missing 'LS_ACCESS_TOKEN' Environment Variable"); + GXLogging.Warn(log, "OpenTelemetry Lightstep was not initialized due to missing 'LS_ACCESS_TOKEN' Environment Variable"); return false; } diff --git a/dotnet/src/dotnetframework/DynServiceOData/DynServiceOData.csproj b/dotnet/src/dotnetframework/DynServiceOData/DynServiceOData.csproj index 7ef6d238e..2cf30c8fd 100644 --- a/dotnet/src/dotnetframework/DynServiceOData/DynServiceOData.csproj +++ b/dotnet/src/dotnetframework/DynServiceOData/DynServiceOData.csproj @@ -11,7 +11,6 @@ - diff --git a/dotnet/src/dotnetframework/GxClasses.Win/GxClasses.Win.csproj b/dotnet/src/dotnetframework/GxClasses.Win/GxClasses.Win.csproj index 1d113bc5d..bdff5e121 100644 --- a/dotnet/src/dotnetframework/GxClasses.Win/GxClasses.Win.csproj +++ b/dotnet/src/dotnetframework/GxClasses.Win/GxClasses.Win.csproj @@ -8,11 +8,10 @@ GeneXus.Classes.Win - - + \ No newline at end of file diff --git a/dotnet/src/dotnetframework/GxClasses.Win/Process/CommandLine.cs b/dotnet/src/dotnetframework/GxClasses.Win/Process/CommandLine.cs index ad02258b6..fa2a5a55a 100644 --- a/dotnet/src/dotnetframework/GxClasses.Win/Process/CommandLine.cs +++ b/dotnet/src/dotnetframework/GxClasses.Win/Process/CommandLine.cs @@ -19,8 +19,7 @@ public IProcessHelper GetProcessHelper() } public class GxProcess : IProcessHelper { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Utils.GxProcess)); - + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public short OpenPrintDocument(string commandString) { Process p = new Process(); diff --git a/dotnet/src/dotnetframework/GxClasses/Configuration/ExternalStorage.cs b/dotnet/src/dotnetframework/GxClasses/Configuration/ExternalStorage.cs index f7433d04c..41112ccd6 100644 --- a/dotnet/src/dotnetframework/GxClasses/Configuration/ExternalStorage.cs +++ b/dotnet/src/dotnetframework/GxClasses/Configuration/ExternalStorage.cs @@ -16,8 +16,7 @@ public class ExternalStorage : GxStorageProvider private GXService providerService; - static readonly ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - + static readonly IGXLogger logger = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); public ExternalStorage() { @@ -59,7 +58,7 @@ public bool Create(string name, GXProperties properties, ref GxStorageProvider s } string typeFullName = providerService.ClassName; - logger.Debug("Loading storage provider: "+ typeFullName); + GXLogging.Debug(logger, "Loading storage provider: " + typeFullName); #if !NETCORE Type type = Type.GetType(typeFullName, true, true); #else @@ -70,7 +69,7 @@ public bool Create(string name, GXProperties properties, ref GxStorageProvider s } catch (Exception ex) { - logger.Error("Couldn't connect to external storage provider. ", ex); + GXLogging.Error(logger, "Couldn't connect to external storage provider. ", ex); StorageMessages(ex, messages); return false; } diff --git a/dotnet/src/dotnetframework/GxClasses/Configuration/LogConfiguration.cs b/dotnet/src/dotnetframework/GxClasses/Configuration/LogConfiguration.cs index 38102430c..6a047d681 100644 --- a/dotnet/src/dotnetframework/GxClasses/Configuration/LogConfiguration.cs +++ b/dotnet/src/dotnetframework/GxClasses/Configuration/LogConfiguration.cs @@ -11,7 +11,7 @@ namespace GeneXus.Configuration { internal class LogConfiguration { - private static readonly ILog logger = log4net.LogManager.GetLogger(typeof(LogConfiguration)); + //private static readonly IGXLogger logger = GXLoggerFactory.GetLogger(); public const string USER_LOG_TOPIC = "GeneXusUserLog"; private const string LOG_LEVEL_ENVVAR = "GX_LOG_LEVEL"; @@ -20,7 +20,11 @@ internal class LogConfiguration public static void SetupLog4Net() { - SetupLog4NetFromEnvironmentVariables(); + Config.GetValueOf("LOG_OUTPUT", out string logProvider); + if (logProvider == "ASPNetTraceAppender" || logProvider == "ConsoleAppender" || logProvider == "EventLogAppender" || logProvider == "RollingFile") + { + SetupLog4NetFromEnvironmentVariables(); + } } private static void SetupLog4NetFromEnvironmentVariables() @@ -56,7 +60,7 @@ private static void SetupLog4NetFromEnvironmentVariables() IAppender appenderToAdd = h.GetAppenders().FirstOrDefault(a => a.Name == appenderName); if (appenderToAdd == null) { - LogConfiguration.logger.Warn($"Appender '{appenderName}' was not found on Log4Net Config file"); + //LogConfiguration.logger.Warn($"Appender '{appenderName}' was not found on Log4Net Config file"); return; } diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs index c835ae5d9..06c6000b2 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs @@ -293,18 +293,18 @@ public GxHttpContextAccesor(IHttpContextAccessor ctxAccessor) public override IFeatureCollection Features => ctxAccessor.HttpContext.Features; - public override IDictionary Items { get => ctxAccessor.HttpContext.Items; set => ctxAccessor.HttpContext.Items=value; } + public override IDictionary Items { get => ctxAccessor.HttpContext.Items; set => ctxAccessor.HttpContext.Items = value; } public override HttpRequest Request => ctxAccessor.HttpContext.Request; - public override CancellationToken RequestAborted { get => ctxAccessor.HttpContext.RequestAborted; set => ctxAccessor.HttpContext.RequestAborted=value; } - public override IServiceProvider RequestServices { get => ctxAccessor.HttpContext.RequestServices; set => ctxAccessor.HttpContext.RequestServices=value; } + public override CancellationToken RequestAborted { get => ctxAccessor.HttpContext.RequestAborted; set => ctxAccessor.HttpContext.RequestAborted = value; } + public override IServiceProvider RequestServices { get => ctxAccessor.HttpContext.RequestServices; set => ctxAccessor.HttpContext.RequestServices = value; } public override HttpResponse Response => ctxAccessor.HttpContext.Response; - public override ISession Session { get => ctxAccessor.HttpContext.Session; set => ctxAccessor.HttpContext.Session=value; } - public override string TraceIdentifier { get => ctxAccessor.HttpContext.TraceIdentifier; set => ctxAccessor.HttpContext.TraceIdentifier=value; } - public override ClaimsPrincipal User { get => ctxAccessor.HttpContext.User; set => ctxAccessor.HttpContext.User=value; } + public override ISession Session { get => ctxAccessor.HttpContext.Session; set => ctxAccessor.HttpContext.Session = value; } + public override string TraceIdentifier { get => ctxAccessor.HttpContext.TraceIdentifier; set => ctxAccessor.HttpContext.TraceIdentifier = value; } + public override ClaimsPrincipal User { get => ctxAccessor.HttpContext.User; set => ctxAccessor.HttpContext.User = value; } public override WebSocketManager WebSockets => ctxAccessor.HttpContext.WebSockets; @@ -321,7 +321,8 @@ internal class GxApplication [Serializable] public class GxContext : IGxContext { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Application.GxContext)); + private static IGXLogger log = null; + internal static bool configurationLoaded = Config.configLoaded; internal static string GX_SPA_REQUEST_HEADER = "X-SPA-REQUEST"; internal static string GX_SPA_REDIRECT_URL = "X-SPA-REDIRECT-URL"; internal const string GXLanguage = "GXLanguage"; @@ -454,6 +455,26 @@ public static GxContext CreateDefaultInstance() context.SetDefaultTheme(theme); return context; } + + static IGXLogger Logger + { + get + { + if (Config.configLoaded) + { + if (log == null) + { + log = GXLoggerFactory.GetLogger(); + return log; + } + return log; + } + else + return null; + } + + } + public GxContext() { _DataStores = new ArrayList(2); @@ -461,7 +482,9 @@ public GxContext() _errorHandlerInfo = new GxErrorHandlerInfo(); setContext(this); httpContextVars = new GxHttpContextVars(); - GXLogging.Debug(log, "GxContext.Ctr Default handle:", () => _handle.ToString()); + + GXLogging.Debug(Logger, "GxContext.Ctr Default handle:", () => _handle.ToString()); + if (GxApplication.MainContext == null && !(IsHttpContext || GxContext.IsRestService)) GxApplication.MainContext = this; } @@ -476,12 +499,12 @@ public GxContext(int handle, string location) } public GxContext(String location) { - GXLogging.Debug(log, "GxContext.Ctr, parameters location=", location); + GXLogging.Debug(Logger, "GxContext.Ctr, parameters location=", location); _DataStores = new ArrayList(2); _errorHandlerInfo = new GxErrorHandlerInfo(); setContext(this); httpContextVars = new GxHttpContextVars(); - GXLogging.Debug(log, "Return GxContext.Ctr"); + GXLogging.Debug(Logger, "Return GxContext.Ctr"); } public GxContext(int handle, ArrayList dataStores, HttpContext httpContext) @@ -572,7 +595,7 @@ public CookieContainer GetCookieContainer(string url, bool includeCookies = true } catch (Exception ex) { - GXLogging.Debug(log, ex, "GetCookieContainer error url:", url); + GXLogging.Debug(Logger, ex, "GetCookieContainer error url:", url); } return new CookieContainer(); @@ -709,7 +732,7 @@ public static bool GetHttpRequestPostedFile(IGxContext gxContext, string varName if (ext != null) ext = ext.TrimStart('.'); string filePath = FileUtil.getTempFileName(tempDir); - GXLogging.Debug(log, "cgiGet(" + varName + "), fileName:" + filePath); + GXLogging.Debug(Logger, "cgiGet(" + varName + "), fileName:" + filePath); GxFile file = new GxFile(tempDir, filePath, GxFileType.PrivateAttribute); filePath = file.Create(pf.InputStream); string fileGuid = GxUploadHelper.GetUploadFileGuid(); @@ -980,12 +1003,12 @@ private bool CheckFileExists(string fileName) { string path = Path.Combine(this.GetPhysicalPath(), fileName); fileExists = File.Exists(path); - GXLogging.Debug(log, $"Searching if file exists ({fileName}). Found: {fileExists}"); + GXLogging.Debug(Logger, $"Searching if file exists ({fileName}). Found: {fileExists}"); } catch (Exception e) { fileExists = false; - GXLogging.Error(log, e, $"Failed searching for a file ({fileName})"); + GXLogging.Error(Logger, e, $"Failed searching for a file ({fileName})"); } return fileExists; } @@ -993,11 +1016,7 @@ private bool CheckFileExists(string fileName) public void StatusMessage(string message) { StackFrame frame = new StackFrame(1); -#if NETCORE - ILog statusLog = log4net.LogManager.GetLogger(frame.GetMethod().DeclaringType); -#else - ILog statusLog = log4net.LogManager.GetLogger(frame.GetMethod().DeclaringType.FullName); -#endif + IGXLogger statusLog = GXLoggerFactory.GetLogger(frame.GetMethod().DeclaringType.FullName); GXLogging.Info(statusLog, message); Console.WriteLine(message); } @@ -1405,7 +1424,7 @@ public void CloseConnections() } catch (Exception ex) { - GXLogging.Error(log, "Error closing report", ex); + GXLogging.Error(Logger, "Error closing report", ex); } } _reportHandlerToClose.Clear(); @@ -1470,7 +1489,7 @@ public void Disconnect() { foreach (IGxDataStore ds in _DataStores) ds.Disconnect(); - GXLogging.Debug(log, "Local Disconnect"); + GXLogging.Debug(Logger, "Local Disconnect"); } public void RollbackDataStores() @@ -1801,7 +1820,7 @@ internal string AbsoluteUri { absoluteUri = String.Format("{0}://{1}{2}", GetServerSchema(), _HttpContext.Request.Headers["Host"], _HttpContext.Request.GetRawUrl()); } - GXLogging.DebugSanitized(log, "AbsoluteUri dynamicport:", absoluteUri); + GXLogging.DebugSanitized(Logger, "AbsoluteUri dynamicport:", absoluteUri); return absoluteUri; } else @@ -2144,7 +2163,7 @@ static internal short GetHttpSecure(HttpContext httpContext) return 0; if (httpContext.Request.GetIsSecureFrontEnd()) { - GXLogging.Debug(log, "Front-End-Https header activated"); + GXLogging.Debug(Logger, "Front-End-Https header activated"); return 1; } else @@ -2473,7 +2492,7 @@ private byte SetCustomHttpHeader(string name, string value) Cache.AppendCacheExtension("no-store, must-revalidate"); break; default: - GXLogging.Warn(log, String.Format("Could not set Cache Control Http Header Value '{0}' to HttpResponse", value)); + GXLogging.Warn(Logger, String.Format("Could not set Cache Control Http Header Value '{0}' to HttpResponse", value)); break; } } @@ -2495,7 +2514,7 @@ private byte SetCustomHttpHeader(string name, string value) }catch (PlatformNotSupportedException ex) { _HttpContext.Response.AppendHeader(name, value); - GXLogging.Warn(log, ex, "SetHeader ", name, value); + GXLogging.Warn(Logger, ex, "SetHeader ", name, value); } } #else @@ -2516,7 +2535,7 @@ private byte SetCustomHttpHeader(string name, string value) _HttpContext.Response.AddHeader(HeaderNames.CacheControl, "private"); break; default: - GXLogging.Warn(log, String.Format("Could not set Cache Control Http Header Value '{0}' to HttpResponse", value)); + GXLogging.Warn(Logger, String.Format("Could not set Cache Control Http Header Value '{0}' to HttpResponse", value)); break; } } @@ -2529,7 +2548,7 @@ private byte SetCustomHttpHeader(string name, string value) } catch (Exception ex) { - GXLogging.Error(log, ex, "Error adding header ", name, value); + GXLogging.Error(Logger, ex, "Error adding header ", name, value); return 1; } } @@ -2883,7 +2902,7 @@ internal static int GetServerPort(HttpRequest request, bool isSecure) } catch (Exception ex) { - GXLogging.Error(log, "GetServerPort error", ex); + GXLogging.Error(Logger, "GetServerPort error", ex); return 0; } @@ -2925,7 +2944,7 @@ private bool FrontEndHttps() { if (CheckHeaderValue("Front-End-Https", "on") || CheckHeaderValue("X-Forwarded-Proto", "https")) { - GXLogging.Debug(log, "Front-End-Https header activated"); + GXLogging.Debug(Logger, "Front-End-Https header activated"); return true; } else @@ -2980,7 +2999,7 @@ public string GetPhysicalPath() } catch (Exception ex) { - GXLogging.Debug(log, "GetPhysicalPath error", ex); + GXLogging.Debug(Logger, "GetPhysicalPath error", ex); _physicalPath = String.Empty; } } @@ -3269,7 +3288,7 @@ public bool ExecuteBeforeConnect(IGxDataStore datastore) if (!configuredEventHandling) configEventHandling(); if (beforeConnectObj != null) { - GXLogging.Debug(log, "ExecuteBeforeConnect"); + GXLogging.Debug(Logger, "ExecuteBeforeConnect"); ClassLoader.ExecuteVoidRef(beforeConnectObj, "execute", new Object[] { datastore }); return true; } @@ -3283,7 +3302,7 @@ public bool ExecuteAfterConnect(String datastoreName) if (!configuredEventHandling) configEventHandling(); if (afterConnectObj != null) { - GXLogging.Debug(log, "ExecuteAfterConnect"); + GXLogging.Debug(Logger, "ExecuteAfterConnect"); ClassLoader.ExecuteVoidRef(afterConnectObj, "execute", new Object[] { datastoreName }); return true; } @@ -3301,7 +3320,7 @@ public void SetProperty(string key, string value) { if (HttpContext != null && HttpContext.Session != null) { - GXLogging.DebugSanitized(log, "HttpContext.Session.setProperty(", key, ")=", value); + GXLogging.DebugSanitized(Logger, "HttpContext.Session.setProperty(", key, ")=", value); WriteSessionKey(key, value); } else @@ -3310,7 +3329,7 @@ public void SetProperty(string key, string value) { _properties = new Hashtable(); } - GXLogging.DebugSanitized(log, "GxContext.Properties.getProperty(", key, ")=", value); + GXLogging.DebugSanitized(Logger, "GxContext.Properties.getProperty(", key, ")=", value); _properties[key] = value; } } @@ -3350,7 +3369,7 @@ public object GetContextProperty(string key) public string PathToUrl(string path) { - GXLogging.Debug(log, "PathToUrl:", () => GetContextPath() + " relativePath:" + PathToRelativeUrl(path)); + GXLogging.Debug(Logger, "PathToUrl:", () => GetContextPath() + " relativePath:" + PathToRelativeUrl(path)); #pragma warning disable SYSLIB0013 // EscapeUriString return Uri.EscapeUriString(GetContextPath()) + PathToRelativeUrl(path, false); #pragma warning disable SYSLIB0013 // EscapeUriString @@ -3570,11 +3589,11 @@ public OlsonTimeZone ClientTimeZone if (_currentTimeZone != null) return _currentTimeZone; string sTZ = _HttpContext == null ? "" : (string)_HttpContext.Request.Headers[GX_REQUEST_TIMEZONE]; - GXLogging.DebugSanitized(log, "ClientTimeZone GX_REQUEST_TIMEZONE header:", sTZ); + GXLogging.DebugSanitized(Logger, "ClientTimeZone GX_REQUEST_TIMEZONE header:", sTZ); if (String.IsNullOrEmpty(sTZ)) { sTZ = (string)GetCookie(GX_REQUEST_TIMEZONE); - GXLogging.Debug(log, "ClientTimeZone GX_REQUEST_TIMEZONE cookie:", sTZ); + GXLogging.Debug(Logger, "ClientTimeZone GX_REQUEST_TIMEZONE cookie:", sTZ); } try { @@ -3582,14 +3601,14 @@ public OlsonTimeZone ClientTimeZone } catch (Exception e1) { - GXLogging.Warn(log, "ClientTimeZone _currentTimeZone error", e1); + GXLogging.Warn(Logger, "ClientTimeZone _currentTimeZone error", e1); try { _currentTimeZone = TimeZoneUtil.GetInstanceFromWin32Id(TimeZoneInfo.Local.Id); } catch (Exception e2) { - GXLogging.Warn(log, "ClientTimeZone GetInstanceFromWin32Id error", e2); + GXLogging.Warn(Logger, "ClientTimeZone GetInstanceFromWin32Id error", e2); Preferences.StorageTimeZonePty storagePty = Preferences.getStorageTimezonePty(); if (storagePty == Preferences.StorageTimeZonePty.Undefined) _currentTimeZone = null; @@ -3607,16 +3626,16 @@ internal string ClientTimeZoneId if (_currentTimeZoneId != null) return _currentTimeZoneId; string sTZ = _HttpContext == null ? "" : (string)_HttpContext.Request.Headers[GX_REQUEST_TIMEZONE]; - GXLogging.DebugSanitized(log, "ClientTimeZone GX_REQUEST_TIMEZONE header:", sTZ); + GXLogging.DebugSanitized(Logger, "ClientTimeZone GX_REQUEST_TIMEZONE header:", sTZ); if (String.IsNullOrEmpty(sTZ)) { sTZ = (string)GetCookie(GX_REQUEST_TIMEZONE); - GXLogging.Debug(log, "ClientTimeZone GX_REQUEST_TIMEZONE cookie:", sTZ); + GXLogging.Debug(Logger, "ClientTimeZone GX_REQUEST_TIMEZONE cookie:", sTZ); } if (!DateTimeUtil.ValidTimeZone(sTZ)) { sTZ = (string)GetUndecodedCookie(GX_REQUEST_TIMEZONE); - GXLogging.Debug(log, "Try reading undecoded ClientTimeZone GX_REQUEST_TIMEZONE cookie:", sTZ); + GXLogging.Debug(Logger, "Try reading undecoded ClientTimeZone GX_REQUEST_TIMEZONE cookie:", sTZ); } try { @@ -3627,10 +3646,10 @@ internal string ClientTimeZoneId string invalidTimezone = DateTimeZoneProviders.Tzdb[sTZ].Id; }catch(Exception ex)//DateTimeZoneNotFound { - GXLogging.Warn(log, $"Client timezone not found: {sTZ}", ex); + GXLogging.Warn(Logger, $"Client timezone not found: {sTZ}", ex); } _currentTimeZoneId = DateTimeZoneProviders.Tzdb.GetSystemDefault().Id; - GXLogging.Warn(log, $"Setting Client timezone to System default: {_currentTimeZoneId}"); + GXLogging.Warn(Logger, $"Setting Client timezone to System default: {_currentTimeZoneId}"); } else { @@ -3639,7 +3658,7 @@ internal string ClientTimeZoneId } catch (Exception e1) { - GXLogging.Warn(log, "ClientTimeZone GetInstanceFromWin32Id error", e1); + GXLogging.Warn(Logger, "ClientTimeZone GetInstanceFromWin32Id error", e1); Preferences.StorageTimeZonePty storagePty = Preferences.getStorageTimezonePty(); if (storagePty == Preferences.StorageTimeZonePty.Undefined) _currentTimeZoneId = null; @@ -3744,7 +3763,7 @@ Hashtable Images string imgDir = ""; if (String.IsNullOrEmpty(dir) && _HttpContext == null) { - GXLogging.Debug(log, "Searching for txt files .."); + GXLogging.Debug(Logger, "Searching for txt files .."); int srchIx = 0; string[] paths = new string[] { ".\\", "..\\" }; bool found = false; @@ -3760,12 +3779,12 @@ Hashtable Images } } imgDir = dir; - GXLogging.Debug(log, $"{imgDir} txt file found"); + GXLogging.Debug(Logger, $"{imgDir} txt file found"); } else { imageFiles = Directory.GetFiles(dir, "*.txt"); - GXLogging.Debug(log, "imageFiles found"); + GXLogging.Debug(Logger, "imageFiles found"); } string KBPrefix = String.Empty; @@ -3829,7 +3848,7 @@ Hashtable Images } catch (FileNotFoundException) { - GXLogging.Debug(log, $"{filename} file not found"); + GXLogging.Debug(Logger, $"{filename} file not found"); } } } @@ -3848,7 +3867,7 @@ public string GetImagePath(string id, string KBId, string theme) return ret; else { - GXLogging.Debug(log, "Image not found at Images.txt. Image id:", () => KBId + id + " language:" + lang + " theme:" + theme); + GXLogging.Debug(Logger, "Image not found at Images.txt. Image id:", () => KBId + id + " language:" + lang + " theme:" + theme); return id; } } @@ -3972,7 +3991,7 @@ static public DateTime StartupDate public void SetSubmitInitialConfig(IGxContext context) { - GXLogging.Debug(log, "SetSubmitInitialConfig:", () => _handle.ToString() + " clientid:" + context.ClientID); + GXLogging.Debug(Logger, "SetSubmitInitialConfig:", () => _handle.ToString() + " clientid:" + context.ClientID); this._isSumbited = true; this.SetDefaultTheme(context.GetTheme(), context.GetThemeisDSO()); this.SetPhysicalPath(context.GetPhysicalPath()); diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXUtils.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXUtils.cs index 1f9e63a42..c5c616f58 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXUtils.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXUtils.cs @@ -267,7 +267,7 @@ static string NormalizeNewLine(string value) public class FileIO { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Utils.FileIO)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); const short GX_ASCDEL_BADFMTSTR = -10; const short GX_ASCDEL_WRITEERROR = -9; const short GX_ASCDEL_INVALIDDATE = -7; diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs index c3c1c176f..5164f74e9 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs @@ -90,7 +90,7 @@ public static void NextBytes(byte[] result) public class NumberUtil { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Utils.NumberUtil)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private NumberFormatInfo numberFormat; public NumberUtil(NumberFormatInfo numFmt) @@ -504,7 +504,7 @@ public string FormatValid(string oldText) public class StringUtil { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Utils.StringUtil)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private NumberFormatInfo numFmtInfo; private const int STR_LEN_DEFAULT = 10; @@ -1995,7 +1995,8 @@ public static string ToCamelCase(this string str) } public class DateTimeUtil { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Utils.DateTimeUtil)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + private CultureInfo cultureInfo; public static bool useConfigForDates; public static bool useConfigForTimes; @@ -3585,7 +3586,7 @@ static public DateTime FromTimeZone(DateTime dt, String sTZ, IGxContext context) public class FileUtil { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Utils.FileUtil)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public static byte DeleteFile(string fileName) { try @@ -4015,7 +4016,7 @@ internal static string SafeCombine(string basePath, string fileName) public class GXUtil { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Utils.GXUtil)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); #if !NETCORE static Hashtable domains; static string DOMAINS_FILE; @@ -5551,7 +5552,7 @@ public string IniReadValue(string Section, string Key) #endif public static class GXDbFile { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Utils.GXDbFile)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); private static Regex schemeRegex = new Regex("^" + Scheme + ":", RegexOptions.Compiled); @@ -5772,8 +5773,7 @@ public static string PathToUrl(string path, bool absUrl, IGxContext context = nu public static class GxImageUtil { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GxImageUtil)); - + static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); private static Bitmap BitmapCreateFromStream(string filePathOrUrl) { Uri uri; @@ -6200,7 +6200,7 @@ public static string EncodeNonAsciiCharacters(string value) } internal class ThreadUtil { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(ThreadUtil)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private static ConcurrentDictionary events = new ConcurrentDictionary(); const int MAX_WAIT_HANDLES = 64; internal static void Submit(WaitCallback callbak, object state) diff --git a/dotnet/src/dotnetframework/GxClasses/Core/Web/HttpAjaxContext.cs b/dotnet/src/dotnetframework/GxClasses/Core/Web/HttpAjaxContext.cs index 6f16bd50a..2180ad8a4 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/Web/HttpAjaxContext.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/Web/HttpAjaxContext.cs @@ -122,7 +122,7 @@ public bool isParmModified(string fieldName, object value) public class HttpAjaxContext : IHttpAjaxContext { private IGxContext _context; - static readonly ILog log = log4net.LogManager.GetLogger(typeof(HttpAjaxContext)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private Stack cmpContents = new Stack(); private GXAjaxCommandCollection commands = new GXAjaxCommandCollection(); private JArray _AttValues = new JArray(); diff --git a/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs b/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs index deab7b67d..6a3789eaf 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs @@ -29,7 +29,8 @@ namespace GeneXus.Configuration public class Config { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Configuration.Config)); + private static IGXLogger log = null; + public const string GX_LANG_SPA = "spa"; public const string GX_LANG_POR = "por"; public const string GX_LANG_ITA = "ita"; @@ -42,7 +43,7 @@ public class Config private static string configFileName; public static string loadedConfigFile; private static bool configLog = true; - private static bool configLoaded; + internal static bool configLoaded; static NameValueCollection _config; static ConcurrentDictionary s_confMapping; const string CONFMAPPING_FILE = "confmapping.json"; @@ -429,7 +430,7 @@ public static CultureInfo GetCultureForLang(string lang) } #if NETCORE - public static IConfiguration ConfigRoot { get; set; } + public static IConfiguration ConfigRoot { get ; set; } const string Log4NetShortName = "log4net"; static Version Log4NetVersion = new Version(2, 0, 15); @@ -439,13 +440,13 @@ public static CultureInfo GetCultureForLang(string lang) const string ITextSharpFileName = "iTextSharp.dll"; const string ITextSharpAssemblyName = "itextsharp"; private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) - { + { var requestedAssembly = new AssemblyName(args.Name); if (requestedAssembly.Name == Log4NetShortName){ requestedAssembly.Version = Log4NetVersion; return Assembly.Load(requestedAssembly); } - + if (args.Name.StartsWith(ConfigurationManagerBak)) { string fileName = Path.Combine(FileUtil.GetStartupDirectory(), ConfigurationManagerFileName); @@ -465,11 +466,12 @@ private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEven else { AssemblyName assName = new AssemblyName(args.Name); - bool strongNamedAssembly = assName.GetPublicKeyToken().Length > 0; string fileName = Path.Combine(FileUtil.GetStartupDirectory(), $"{assName.Name}.dll"); - if (!strongNamedAssembly && File.Exists(fileName)) + if (File.Exists(fileName)) { - return Assembly.LoadFrom(fileName); + Assembly assm = Assembly.LoadFrom(fileName); + if (assm!=null && assm.GetName().Version == assName.Version) + return assm; } } return null; @@ -509,115 +511,140 @@ static NameValueCollection config { if (!configLoaded || _config == null) { + bool isNetTrustException = false; + Exception netTrustedException = null; + string configuredFilename = null; lock (syncRoot) { if (_config == null) { + try { AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; } catch (Exception ex) { - GXLogging.Info(log, ".NET trust level is lower than full", ex.Message); + isNetTrustException = true; + netTrustedException = ex; } string logConfigSource; - configLoaded = true; if (configFileName != null) { - if (log.IsDebugEnabled) loadedConfigFile = configFileName; + loadedConfigFile = configFileName; _config = loadConfig(configFileName, out logConfigSource); if (!string.IsNullOrEmpty(logConfigSource)) - logConfig(logConfigSource); + logConfig(logConfigSource, out configuredFilename); else - logConfig(configFileName); - return _config; + logConfig(configFileName, out configuredFilename); } + else + { #if !NETCORE - if (GxContext.IsHttpContext && - File.Exists(Path.Combine(GxContext.StaticPhysicalPath(), "web.config"))) - { - logConfig(null); - if (log.IsDebugEnabled) loadedConfigFile = Path.Combine(GxContext.StaticPhysicalPath(), "web.config"); - _config = ConfigurationSettings.AppSettings; - foreach (string key in _config.Keys) - { - string value = MappedValue(key, _config[key]); - if (value!=_config[key]) - _config[key] = value; - } - languages = null; - return _config; - } - if (GxContext.IsHttpContext && - File.Exists(Path.Combine(GxContext.StaticPhysicalPath(), "bin", "client.exe.config"))) - - { + if (GxContext.IsHttpContext && + File.Exists(Path.Combine(GxContext.StaticPhysicalPath(), "web.config"))) + { + logConfig(null, out configuredFilename); + loadedConfigFile = Path.Combine(GxContext.StaticPhysicalPath(), "web.config"); + _config = ConfigurationSettings.AppSettings; + foreach (string key in _config.Keys) + { + string value = MappedValue(key, _config[key]); + if (value != _config[key]) + _config[key] = value; + } + languages = null; + } + else if (GxContext.IsHttpContext && + File.Exists(Path.Combine(GxContext.StaticPhysicalPath(), "bin", "client.exe.config"))) + { - logConfig("bin/log.config"); - if (log.IsDebugEnabled) - loadedConfigFile = Path.Combine(GxContext.StaticPhysicalPath(), "bin", "client.exe.config"); - _config = loadConfig("bin/client.exe.config"); - return _config; - } - if (File.Exists("client.exe.config")) - { - logConfig("log.console.config"); - if (log.IsDebugEnabled) loadedConfigFile = Path.GetFullPath("client.exe.config"); - _config = loadConfig("client.exe.config"); - } - else - { - string file = FileUtil.GetStartupDirectory() + "/client.exe.config"; - string logFile = FileUtil.GetStartupDirectory() + "/log.console.config"; - logConfig(logFile); - if (log.IsDebugEnabled) loadedConfigFile = Path.GetFullPath(file); - _config = loadConfig(file); + logConfig("bin/log.config", out configuredFilename); + loadedConfigFile = Path.Combine(GxContext.StaticPhysicalPath(), "bin", "client.exe.config"); + _config = loadConfig("bin/client.exe.config"); + } + else if (File.Exists("client.exe.config")) + { + logConfig("log.console.config", out configuredFilename); + loadedConfigFile = Path.GetFullPath("client.exe.config"); + _config = loadConfig("client.exe.config"); + } + else + { + string file = FileUtil.GetStartupDirectory() + "/client.exe.config"; + string logFile = FileUtil.GetStartupDirectory() + "/log.console.config"; + logConfig(logFile, out configuredFilename); + loadedConfigFile = Path.GetFullPath(file); + _config = loadConfig(file); - } + } #else - string basePath = FileUtil.GetBasePath(); - string currentDir = Directory.GetCurrentDirectory(); - string startupDir = FileUtil.GetStartupDirectory(); - string appSettings = "appsettings.json"; - string clientConfig = "client.exe.config"; - string logConfigFile = GxContext.IsHttpContext ? "log.config" : "log.console.config"; - - if (File.Exists(Path.Combine(basePath, appSettings))) - { - _config = loadConfigJson(basePath, appSettings); - logConfig(Path.Combine(basePath, logConfigFile)); - } - else if (File.Exists(appSettings)) - { - _config = loadConfigJson(currentDir, appSettings); - logConfig(logConfigFile); - } - else if (File.Exists(Path.Combine(startupDir, appSettings))) - { - _config = loadConfigJson(startupDir, appSettings); - logConfig(Path.Combine(startupDir, logConfigFile)); - } - else if (File.Exists(clientConfig)) - { - _config = loadConfig(clientConfig, out logConfigSource); - if (!string.IsNullOrEmpty(logConfigSource)) - logConfig(logConfigSource); - else - logConfig(logConfigFile); - } - try - { - Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); - } - catch (Exception ex) - { - GXLogging.Info(log, "Could not register encoding provider", ex.Message); - } + string basePath = FileUtil.GetBasePath(); + string currentDir = Directory.GetCurrentDirectory(); + string startupDir = FileUtil.GetStartupDirectory(); + string appSettings = "appsettings.json"; + string clientConfig = "client.exe.config"; + + string logConfigurationSource = string.Empty; + + if (File.Exists(Path.Combine(basePath, appSettings))) + { + _config = loadConfigJson(basePath, appSettings); + + } + else if (File.Exists(appSettings)) + { + _config = loadConfigJson(currentDir, appSettings); + + } + else if (File.Exists(Path.Combine(startupDir, appSettings))) + { + _config = loadConfigJson(startupDir, appSettings); + + } + else if (File.Exists(clientConfig)) + { + _config = loadConfig(clientConfig, out logConfigSource); + logConfigurationSource = logConfigSource; + + } + configLoaded = true; + + string logConfigFile = GxContext.IsHttpContext ? "log.config" : "log.console.config"; + if (File.Exists(Path.Combine(basePath, appSettings))) + logConfig(Path.Combine(basePath, logConfigFile), out configuredFilename); + + else if (File.Exists(appSettings)) + logConfig(logConfigFile, out configuredFilename); + + else if (File.Exists(Path.Combine(startupDir, appSettings))) + logConfig(Path.Combine(startupDir, logConfigFile), out configuredFilename); + + else if (File.Exists(clientConfig)) + if (!string.IsNullOrEmpty(logConfigurationSource)) + logConfig(logConfigurationSource, out configuredFilename); + else + logConfig(logConfigFile, out configuredFilename); + + try + { + Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); + } + catch (Exception) + { + //"Could not register encoding provider"; + } #endif + } } } + log = GXLoggerFactory.GetLogger(); + GXLogging.Debug(log, "GxClasses version:", GxContext.StdClassesVersion()); + if (configuredFilename != null) + GXLogging.Debug(log, "DOMConfigurator log4net configured with ", configuredFilename); + if (isNetTrustException) + GXLogging.Info(log, ".NET trust level is lower than full", netTrustedException.Message); } return _config; } @@ -661,9 +688,10 @@ static NameValueCollection loadConfigJson(string baseDir, string appSettings) return cfg; } #endif - private static void logConfig(string filename) + private static void logConfig(string filename, out string configuredFilename) { - if (configLog) + configuredFilename = null; + if (configLog) { try { @@ -672,21 +700,20 @@ private static void logConfig(string filename) { var logRepository = LogManager.GetRepository(Assembly.GetEntryAssembly()); XmlConfigurator.ConfigureAndWatch(logRepository, new FileInfo(filename)); - GXLogging.Debug(log, "DOMConfigurator log4net configured with ", filename); + configuredFilename = filename; } #else if (filename != null) { XmlConfigurator.ConfigureAndWatch(new FileInfo(filename)); - GXLogging.Debug(log, "DOMConfigurator log4net configured with ", filename); + configuredFilename = filename; } else { XmlConfigurator.Configure(); - GXLogging.Debug(log, "DOMConfigurator log4net configured with web.config"); + configuredFilename = "web.config"; } #endif - GXLogging.Debug(log, "GxClasses version:", GxContext.StdClassesVersion()); } catch (Exception ex) { @@ -703,7 +730,6 @@ static NameValueCollection loadConfig(string filename) } static NameValueCollection loadConfig(string filename, out string logConfigSource) { - GXLogging.Debug(log, "Start loadConfig, filename '", filename, "'"); NameValueCollection cfg = new NameValueCollection(StringComparer.Ordinal); //Case sensitive logConfigSource = null; if (!File.Exists(filename)) @@ -752,7 +778,6 @@ static NameValueCollection loadConfig(string filename, out string logConfigSourc } } } - GXLogging.Debug(log, "Return loadConfig"); return cfg; } private static string MappedValue(string key, string value) @@ -767,7 +792,7 @@ private static string MappedValue(string key, string value) } public class Preferences { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Configuration.Preferences)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); static object syncRoot = new Object(); static Hashtable cachingTtl; static string _applicationPath = ""; diff --git a/dotnet/src/dotnetframework/GxClasses/Cryptography/GXAsymmetricEncryption.cs b/dotnet/src/dotnetframework/GxClasses/Cryptography/GXAsymmetricEncryption.cs index f9c110a7b..6c4840057 100644 --- a/dotnet/src/dotnetframework/GxClasses/Cryptography/GXAsymmetricEncryption.cs +++ b/dotnet/src/dotnetframework/GxClasses/Cryptography/GXAsymmetricEncryption.cs @@ -1,18 +1,12 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.IO; -using log4net; using GeneXus.Cryptography.CryptoException; using GeneXus.Cryptography.Encryption; namespace GeneXus.Cryptography { - public class GXAsymmetricEncryption + public class GXAsymmetricEncryption { - private static readonly ILog _log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - private int _lastError; + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + private int _lastError; private string _lastErrorDescription; private GXCertificate _cert; private IGXAsymmetricEncryption _asymAlg; @@ -62,7 +56,7 @@ public string Encrypt(string text) catch (EncryptionException e) { SetError(1, e.Message); - _log.Error("Encryption Error", e); + GXLogging.Error(log, "Encryption Error", e); } } return encrypted; @@ -89,7 +83,7 @@ public string Decrypt(string text) catch (EncryptionException e) { SetError(1, e.Message); - _log.Error("Encryption Error", e); + GXLogging.Error(log, "Encryption Error", e); } } return decrypted; diff --git a/dotnet/src/dotnetframework/GxClasses/Cryptography/GXCertificate.cs b/dotnet/src/dotnetframework/GxClasses/Cryptography/GXCertificate.cs index 7a195f954..3c19b6dc4 100644 --- a/dotnet/src/dotnetframework/GxClasses/Cryptography/GXCertificate.cs +++ b/dotnet/src/dotnetframework/GxClasses/Cryptography/GXCertificate.cs @@ -1,8 +1,7 @@ using System; -using System.Security.Cryptography.X509Certificates; using System.IO; using System.Security.Cryptography; -using log4net; +using System.Security.Cryptography.X509Certificates; using GeneXus.Utils; @@ -10,9 +9,9 @@ namespace GeneXus.Cryptography { public class GXCertificate { - static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); - private X509Certificate2 _cert; + private X509Certificate2 _cert; private int _lastError; private string _lastErrorDescription; private string _password; diff --git a/dotnet/src/dotnetframework/GxClasses/Cryptography/GXSymmetricEncryption.cs b/dotnet/src/dotnetframework/GxClasses/Cryptography/GXSymmetricEncryption.cs index 8bf205372..816093187 100644 --- a/dotnet/src/dotnetframework/GxClasses/Cryptography/GXSymmetricEncryption.cs +++ b/dotnet/src/dotnetframework/GxClasses/Cryptography/GXSymmetricEncryption.cs @@ -1,19 +1,13 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Security.Cryptography; -using System.IO; -using log4net; +using System; using GeneXus.Cryptography.CryptoException; using GeneXus.Cryptography.Encryption; namespace GeneXus.Cryptography { - public class GXSymmetricEncryption + public class GXSymmetricEncryption { - private static readonly ILog _log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - private const string DEFAULT_SYM_ALGORITHM = "DES"; + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + private const string DEFAULT_SYM_ALGORITHM = "DES"; private int _lastError; private string _lastErrorDescription; private IGXSymmetricEncryption _symAlg; // Algorithm instance @@ -81,7 +75,7 @@ public string Encrypt(string text) catch (EncryptionException e) { SetError(2, e.Message); - _log.Error(e); + GXLogging.Error(log, e); } } return encrypted; @@ -100,7 +94,7 @@ public string Decrypt(string text) catch (EncryptionException e) { SetError(3, e.Message); - _log.Error(e); + GXLogging.Error(log, e); } } return decrypted; diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataADO.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataADO.cs index 206a66c79..4e72f295f 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataADO.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataADO.cs @@ -11,6 +11,7 @@ using GeneXus.XML; using GxClasses.Helpers; using log4net; +using log4net.Core; using System; using System.Collections; using System.Collections.Concurrent; @@ -21,7 +22,6 @@ using System.Reflection; using System.Threading; using TZ4Net; - namespace GeneXus.Data.ADO { @@ -64,7 +64,7 @@ public override void DecOpenHandlesImpl(GxConnection con) public class GxConnectionManager :IGxConnectionManager { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Data.ADO.GxConnectionManager)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private static volatile GxConnectionManager instance; private static object instanceSync = new Object(); @@ -345,7 +345,7 @@ public class GxConnection: MarshalByRefObject, IGxConnection public class GxConnection: IGxConnection #endif { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Data.ADO.GxConnection)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private IDbTransaction transaction; private short lastErrorCode; private string lastErrorMsg; @@ -1319,7 +1319,7 @@ public ParDef(string name, GXType type, int size, int scale) public class GxCommand: IGxDbCommand { internal List ParmDefinition; - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Data.ADO.GxCommand)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); string stmt; String stmtId; GxParameterCollection parameters; @@ -2411,7 +2411,7 @@ internal void AfterCreateCommand() public class GxDataStore : IGxDataStore { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GxDataStore)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); string id; IGxConnection connection; int handle; diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs index 35b966913..362374b08 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs @@ -4,7 +4,6 @@ using System.IO; using System.Text; using System.Threading; -using log4net; using GeneXus.Application; using GeneXus.Cache; using GeneXus.Configuration; @@ -297,7 +296,8 @@ public enum GxErrorMask public abstract class GxDataRecord : IGxDataRecord { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Data.GxDataRecord)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + public static int RETRY_SLEEP = 500; //500 milliseconds. protected string m_connectionString; protected string m_datasource; @@ -1188,8 +1188,8 @@ public void Clear() public class SqlUtil { public static Hashtable mapping; - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Data.SqlUtil)); - + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + public static string SqlTypeToDbType(SqlParameter parameter) { SqlDbType type = parameter.SqlDbType; @@ -1464,8 +1464,7 @@ public static String GetKeyStmtValues(GxParameterCollection parameters, public class GxSqlDataReader : GxDataReader { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Data.GxSqlDataReader)); - + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public GxSqlDataReader(IGxConnectionManager connManager, GxDataRecord dr, IGxConnection connection, GxParameterCollection parameters, string stmt, ushort fetchSize,bool forFirst, int handle, bool withCached, SlidingTime expiration, bool dynStmt):base(connManager, dr, connection, parameters, stmt, fetchSize, forFirst, handle, withCached, expiration, dynStmt) @@ -1583,7 +1582,7 @@ public override decimal GetDecimal(int i) } public class GxSqlServer : GxDataRecord { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Data.GxSqlServer)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private static int MAX_NET_DECIMAL_PRECISION = 28; private static int MAX_GX_DECIMAL_SCALE = 15; @@ -2168,7 +2167,7 @@ public override string ConcatOp(int pos) public class GxDataReader: IDataReader { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Data.GxDataReader)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); protected IDataReader reader; protected GxParameterCollection parameters; protected int fetchSize; @@ -2541,7 +2540,8 @@ public int GetOrdinal(string name) public class GxConnectionCache { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Data.GxConnectionCache)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + private static int MAX_SIZE=Preferences.GetMaximumOpenCursors(); private SqlCommand fetchCommand; @@ -2646,7 +2646,7 @@ public void AddPreparedStmt(string stmt, int cursorId) GxItemStmt s;; if (!preparedStmtCache.TryGetValue(stmt, out s)) { - GXLogging.Info(log, "AddPreparedStmt, totalCachedStmtCursors:" + totalCachedCursors + ", cursorId: " + cursorId + ", stmt:" + stmt); + GXLogging.Info(log, msg: "AddPreparedStmt, totalCachedStmtCursors: {totalCachedCursors}, {cursorId}: , stmt: {stmt}", totalCachedCursors.ToString(), cursorId.ToString(), stmt); totalCachedCursors++; CheckCacheSize(); @@ -3130,7 +3130,8 @@ private void InitCommands() public class GxPreparedStatementCache : Dictionary { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Data.GxPreparedStatementCache)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + private IGxConnection conn; public GxPreparedStatementCache(IGxConnection connection, int maxSize):base(maxSize) @@ -3183,7 +3184,7 @@ public void dump() public class GxSqlCursorDataReader: IDataReader { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Data.GxSqlCursorDataReader)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private static int STARTPOS = -1; private int pos= STARTPOS; private ushort fetchSize; @@ -4124,7 +4125,7 @@ public string ValueList(IList Values) sealed internal class MssqlConnectionWrapper : GxAbstractConnectionWrapper { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Data.MssqlConnectionWrapper)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); int sqlserver7 = -1; int sqlserver9 = -1; @@ -4241,7 +4242,7 @@ public override bool IsSQLServer9() public abstract class GxAbstractConnectionWrapper : IDbConnection { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Data.GxAbstractConnectionWrapper)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); protected short m_spid; protected IDbConnection _connection; protected bool m_autoCommit; @@ -4380,7 +4381,7 @@ public virtual short RollbackSavePoint(IDbTransaction transaction, string savepo public class GxCacheDataReader: IDataReader { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Data.GxCacheDataReader)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); protected GxArrayList block; protected int pos; int blockSize; diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2.cs index a3849f245..ea570daad 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2.cs @@ -116,7 +116,8 @@ protected override string BuildConnectionString(string datasourceName, string us public class GxDb2 : GxDataRecord { - static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + public static string SQL_NULL_DATE_10="0000-00-00"; public static string SQL_NULL_DATE_8="00000000"; static Assembly _db2Assembly; @@ -523,7 +524,7 @@ sealed internal class Db2ConnectionWrapper : GxAbstractConnectionWrapper private static int changeConnState=-1; private static int changeConnStateExecuting = -1; private int openDataReaders; - static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); public Db2ConnectionWrapper() { try diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2400.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2400.cs index 263f83260..6c2b40478 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2400.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2400.cs @@ -45,7 +45,7 @@ public override object GetValue(int i) } sealed internal class Db2ISeriesConnectionWrapper : GxAbstractConnectionWrapper { - static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); public Db2ISeriesConnectionWrapper() { try @@ -121,7 +121,7 @@ public override DbDataAdapter CreateDataAdapter() public class GxDb2ISeries : GxDataRecord { - static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); private bool m_UseCharInDate; public static string SQL_NULL_DATE="00000000"; private string m_InitialCatalog; @@ -768,7 +768,7 @@ public override string ToDbmsConstant(DateTime Value) } sealed internal class Db2ISeriesHISConnectionWrapper : GxAbstractConnectionWrapper { - static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); public Db2ISeriesHISConnectionWrapper() : base(new MsDb2Connection()) { } @@ -827,7 +827,7 @@ public override DbDataAdapter CreateDataAdapter() public class GxISeriesHIS : GxDataRecord { - static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); private bool m_UseCharInDate; private string m_InitialCatalog; private string m_SqlPackage; diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataHana.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataHana.cs index 484449b3c..ad2cf1337 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataHana.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataHana.cs @@ -14,7 +14,7 @@ namespace GeneXus.Data { public class GxHana : GxDataRecord { - static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); static Assembly _hanaAssembly; const string HanaDbTypeEnum = "Sap.Data.Hana.HanaDbType"; #if NETCORE @@ -321,8 +321,8 @@ sealed internal class HanaConnectionWrapper : GxAbstractConnectionWrapper { const string HanaIsolationEnum = "Sap.Data.Hana.HanaIsolationLevel"; - static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - public HanaConnectionWrapper() + static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + public HanaConnectionWrapper() { try { diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataInformix.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataInformix.cs index 3c92389b9..6b326f74b 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataInformix.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataInformix.cs @@ -20,7 +20,7 @@ namespace GeneXus.Data { public class GxInformix : GxDataRecord { - static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); static Assembly _ifxAssembly; #if NETCORE internal static string InformixAssemblyName = "Informix.Net.Core"; @@ -459,7 +459,7 @@ public override IDbCommand GetCachedCommand(IGxConnection con, string stmt) public class GxInformixDataReader : GxDataReader { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GxInformixDataReader)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public GxInformixDataReader(IGxConnectionManager connManager, GxDataRecord dr, IGxConnection connection, GxParameterCollection parameters, string stmt, int fetchSize, bool forFirst, int handle, bool cached, SlidingTime expiration, bool dynStmt) : base(connManager, dr, connection, parameters, stmt, fetchSize, forFirst, handle, cached, expiration, dynStmt) @@ -586,7 +586,7 @@ sealed internal class InformixConnectionWrapper : GxAbstractConnectionWrapper { private static int changeConnState = -1; private int openDataReaders; - static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); public InformixConnectionWrapper() { try diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlConnector.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlConnector.cs index 1b4470a85..5d819d439 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlConnector.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlConnector.cs @@ -22,7 +22,7 @@ namespace GeneXus.Data public class GxMySqlConnector : GxDataRecord { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Data.GxMySqlConnector)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private int MAX_TRIES; private int m_FailedConnections; #if NETCORE @@ -479,7 +479,9 @@ public override void SetParameter(IDbDataParameter parameter, object value) [SecuritySafeCritical] sealed internal class MySqlConnectorConnectionWrapper : GxAbstractConnectionWrapper { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Data.MySqlConnectorConnectionWrapper)); + + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + [SecuritySafeCritical] public MySqlConnectorConnectionWrapper() : base(new MySQLConnection()) { } @@ -547,7 +549,7 @@ public override short RollbackSavePoint(IDbTransaction transaction, string savep [SecuritySafeCritical] public class GxMySQLConnectorDataReader : GxDataReader { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GxMySQLConnectorDataReader)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public GxMySQLConnectorDataReader(IGxConnectionManager connManager, GxDataRecord dr, IGxConnection connection, GxParameterCollection parameters, string stmt, int fetchSize, bool forFirst, int handle, bool cached, SlidingTime expiration, bool dynStmt) { @@ -599,8 +601,7 @@ public override string GetString(int i) [SecuritySafeCritical] public class GxMySQLConnectorCursorDataReader : GxDataReader { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Data.GxDataReader)); - + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public GxMySQLConnectorCursorDataReader(IGxConnectionManager connManager, GxDataRecord dr, IGxConnection connection, GxParameterCollection parameters, string stmt, int fetchSize, bool forFirst, int handle, bool cached, SlidingTime expiration, bool hasNested, bool dynStmt) { diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlDriverCS.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlDriverCS.cs index 54fb262e4..df77b2082 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlDriverCS.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlDriverCS.cs @@ -12,7 +12,8 @@ namespace GeneXus.Data { public class GxMySql : GxDataRecord { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Data.GxMySql)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + private int MAX_TRIES; private int m_FailedConnections; private bool preparedStmts; @@ -403,7 +404,7 @@ public override void SetParameter(IDbDataParameter parameter, object value) sealed internal class MySqlDriverCSConnectionWrapper : GxAbstractConnectionWrapper { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Data.MySqlDriverCSConnectionWrapper)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public MySqlDriverCSConnectionWrapper() : base(new MySQLConnection()) { } @@ -516,7 +517,7 @@ public override string GetString(int i) } public class GxMySQLDriverCSCursorDataReader : GxDataReader { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Data.GxDataReader)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public GxMySQLDriverCSCursorDataReader(IGxConnectionManager connManager, GxDataRecord dr, IGxConnection connection, GxParameterCollection parameters, string stmt, int fetchSize, bool forFirst, int handle, bool cached, SlidingTime expiration, bool hasNested, bool dynStmt) diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTier.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTier.cs index 467cb2b4f..16e1d3ba6 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTier.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTier.cs @@ -142,7 +142,7 @@ public interface IDataStoreHelper public class DataStoreHelperBase { /*DO NOT ADD INSTANCE VARIABLES IN THIS CLASS, THIS IS REFERENCED BY THE STATIC CURSORDEF ARRAY IN THE XX___DEFAULT, ALL THE VARIABLES HERE LIVE FOREVER*/ - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(DataStoreHelperBase)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private const string AND = " and "; private const string WHERE = " WHERE "; @@ -342,7 +342,8 @@ public interface IDataStoreProviderBase public class DataStoreProvider : IDataStoreProviderBase,IDataStoreProvider { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Data.NTier.DataStoreProvider)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + ICursor[] _cursor; Object[][] results; [System.Diagnostics.CodeAnalysis.SuppressMessage("GxFxCopRules", "CR1000:EnforceThreadSafeType")] diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierADO.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierADO.cs index 5d2795af9..d838c3c1a 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierADO.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierADO.cs @@ -204,7 +204,7 @@ public IGeographicNative getGeospatial(int id) } public class GXFatFieldGetter : IFieldGetter { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Data.NTier.ADO.GXFatFieldGetter)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); IGxDbCommand _gxDbCommand; IDataReader _DR; public GXFatFieldGetter(GxCommand gxDbCommand) @@ -499,7 +499,7 @@ public bool wasNull(int id) } public class GXFatFieldSetter : IFieldSetter { - protected static readonly ILog log = log4net.LogManager.GetLogger(typeof(GXFatFieldSetter)); + protected static readonly IGXLogger log = GXLoggerFactory.GetLogger(); GxCommand _gxDbCommand; public GXFatFieldSetter(GxCommand gxDbCommand) { @@ -792,7 +792,7 @@ public void RestoreParametersRT() } public class Cursor : ICursor { - protected static readonly ILog log = log4net.LogManager.GetLogger(typeof(Cursor)); + protected static readonly IGXLogger log = GXLoggerFactory.GetLogger(); protected int _state = 0; protected string _name; protected string _stmt; diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierService.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierService.cs index e29d0edb0..817de09bd 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierService.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierService.cs @@ -65,7 +65,7 @@ public ServiceCursorDef(string name, object query, GxErrorMask nmask, Object[] p public class GxServiceFactory { - protected static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + protected static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); public static GxService Create(string id, string providerId, string serviceClass) { @@ -75,7 +75,7 @@ public static GxService Create(string id, string providerId, string serviceClass public class GxService : GxDataRecord { - protected static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + protected static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); private Type m_ServiceType; private CursorDef m_CursorDef; @@ -316,8 +316,7 @@ public interface IServiceCommand sealed public class ServiceConnectionWrapper : GxAbstractConnectionWrapper { - static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - + static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); public ServiceConnectionWrapper(Type runtimeClassType, String connectionString, GxConnectionCache connCache, IsolationLevel isolationLevel, String dataSource) { try diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataOracle.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataOracle.cs index 0e93a3efe..2cb65dc02 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataOracle.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataOracle.cs @@ -19,7 +19,7 @@ namespace GeneXus.Data { public class GxODPCacheDataReader : GxOracleCacheDataReader { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GxODPCacheDataReader)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public GxODPCacheDataReader(CacheItem cacheItem, bool computeSize, string keyCache) : base(cacheItem, computeSize, keyCache) { } @@ -116,7 +116,7 @@ public override bool IsDBNull(int i) } public class GxODPManagedCacheDataReader : GxOracleCacheDataReader { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GxODPManagedCacheDataReader)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public GxODPManagedCacheDataReader(CacheItem cacheItem, bool computeSize, string keyCache) : base(cacheItem, computeSize, keyCache) { } @@ -235,7 +235,7 @@ public override long GetBytes(int i, long fieldOffset, byte[] buffer, int buffer public class GxODPOracle : GxOracle { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GxODPOracle)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); static Assembly _odpAssembly; const string OracleDbTypeEnum = "Oracle.DataAccess.Client.OracleDbType"; @@ -547,7 +547,8 @@ internal static bool IsClobType(object value) } public class GxODPManagedOracle : GxOracle { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GxODPManagedOracle)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + static Assembly _odpAssembly; const string OracleDbTypeEnum = "Oracle.ManagedDataAccess.Client.OracleDbType"; const string OracleAssemblyName = "Oracle.ManagedDataAccess"; @@ -859,7 +860,7 @@ internal static bool IsClobType(object value) public class GxOracle : GxDataRecord { const string BLANK_STRING = " "; - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GxOracle)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); #if !NETCORE public override GxAbstractConnectionWrapper GetConnection(bool showPrompt, string datasourceName, string userId, string userPassword, string databaseName, string port, string schema, string extra, GxConnectionCache connectionCache) @@ -1304,7 +1305,7 @@ public override string ConcatOp(int pos) } public class GxODPOracleDataReader : GxDataReader { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GxODPOracleDataReader)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public GxODPOracleDataReader(IGxConnectionManager connManager, GxDataRecord dr, IGxConnection connection, GxParameterCollection parameters, string stmt, int fetchSize, bool forFirst, int handle, bool cached, SlidingTime expiration, bool dynStmt) : base(connManager, dr, connection, parameters, stmt, fetchSize, forFirst, handle, cached, expiration, dynStmt) @@ -1370,7 +1371,7 @@ public override decimal GetDecimal(int i) public class GxODPManagedOracleDataReader : GxDataReader { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GxODPManagedOracleDataReader)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public GxODPManagedOracleDataReader(IGxConnectionManager connManager, GxDataRecord dr, IGxConnection connection, GxParameterCollection parameters, string stmt, int fetchSize, bool forFirst, int handle, bool cached, SlidingTime expiration, bool dynStmt) : base(connManager, dr, connection, parameters, stmt, fetchSize, forFirst, handle, cached, expiration, dynStmt) @@ -1436,7 +1437,7 @@ public override decimal GetDecimal(int i) #if !NETCORE sealed internal class MSOracleConnectionWrapper : GxAbstractConnectionWrapper { - static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); int oracle8 = -1; public MSOracleConnectionWrapper() : base(new MSOracleProvider.OracleConnection()) { @@ -1531,7 +1532,7 @@ public override short RollbackSavePoint(IDbTransaction transaction, string savep #endif sealed internal class OracleConnectionWrapper : GxAbstractConnectionWrapper { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(OracleConnectionWrapper)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public OracleConnectionWrapper() { try @@ -1625,7 +1626,7 @@ public override short RollbackSavePoint(IDbTransaction transaction, string savep sealed internal class OracleManagedConnectionWrapper : GxAbstractConnectionWrapper { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(OracleManagedConnectionWrapper)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public OracleManagedConnectionWrapper() { try diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataPostgreSQL.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataPostgreSQL.cs index b91c9e4cd..02dfcaeaa 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataPostgreSQL.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataPostgreSQL.cs @@ -20,7 +20,7 @@ namespace GeneXus.Data { public class GxPostgreSql : GxDataRecord { - static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); const string ConnectionStringEncoding = "encoding"; private byte[] _buffer; static Assembly _npgsqlAssembly; @@ -587,7 +587,7 @@ public override string ConcatOp(int pos) } sealed internal class PostgresqlConnectionWrapper : GxAbstractConnectionWrapper { - static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); public PostgresqlConnectionWrapper() { _connection = (IDbConnection)ClassLoader.CreateInstance(GxPostgreSql.NpgsqlAssembly, "Npgsql.NpgsqlConnection"); diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataSqlite.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataSqlite.cs index 5d70d808f..b7de8e9cf 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataSqlite.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataSqlite.cs @@ -19,7 +19,7 @@ namespace GeneXus.Data { public class GxSqlite : GxDataRecord { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Data.GxSqlite)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private int MAX_TRIES = 10; private int m_FailedConnections; @@ -310,8 +310,7 @@ public override void SetParameterBlob(IDbDataParameter parameter, string value, sealed internal class SQLiteConnectionWrapper : GxAbstractConnectionWrapper { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Data.SQLiteConnectionWrapper)); - + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public SQLiteConnectionWrapper() : base(new SQLiteConnection()) { } diff --git a/dotnet/src/dotnetframework/GxClasses/Diagnostics/GXDebugManager.cs b/dotnet/src/dotnetframework/GxClasses/Diagnostics/GXDebugManager.cs index 252c3caf3..55d95792d 100644 --- a/dotnet/src/dotnetframework/GxClasses/Diagnostics/GXDebugManager.cs +++ b/dotnet/src/dotnetframework/GxClasses/Diagnostics/GXDebugManager.cs @@ -20,7 +20,7 @@ public class GXDebugManager private static bool initialized; private static GXDebugManager m_Instance; - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Application.GxContext)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public static GXDebugManager Instance { get diff --git a/dotnet/src/dotnetframework/GxClasses/Diagnostics/Log.cs b/dotnet/src/dotnetframework/GxClasses/Diagnostics/Log.cs index 17ede87d5..d1947ed42 100644 --- a/dotnet/src/dotnetframework/GxClasses/Diagnostics/Log.cs +++ b/dotnet/src/dotnetframework/GxClasses/Diagnostics/Log.cs @@ -1,7 +1,10 @@ -using System; using GeneXus.Attributes; using GeneXus.Configuration; using log4net; +#if NETCORE +using GeneXus.Services.Log; +using Microsoft.Extensions.Logging; +#endif namespace GeneXus.Diagnostics { @@ -19,22 +22,28 @@ private enum LogLevel Fatal = 30 } #if NETCORE - static readonly string defaultRepository = LogManager.GetRepository(System.Reflection.Assembly.GetEntryAssembly()).Name; -#else - static readonly string defaultRepository = LogManager.GetRepository().Name; + static ILoggerFactory _instance = GXLogService.GetLogFactory(); #endif - public static string defaultUserLogNamespace = Configuration.Config.GetValueOf("USER_LOG_NAMESPACE", LogConfiguration.USER_LOG_TOPIC); - - static readonly ILog globalLog = LogManager.GetLogger(defaultRepository, defaultUserLogNamespace); - - private static ILog GetLogger(string topic) + + internal static IGXLogger GetLogger(string topic) { - if (!String.IsNullOrEmpty(topic)) + string defaultUserLogNamespace = Configuration.Config.GetValueOf("USER_LOG_NAMESPACE", LogConfiguration.USER_LOG_TOPIC); + string loggerName = defaultUserLogNamespace; + if (!string.IsNullOrEmpty(topic)) { - string loggerName = topic.StartsWith("$") ? topic.Substring(1) : string.Format("{0}.{1}", defaultUserLogNamespace, topic.Trim()); - return LogManager.GetLogger(defaultRepository, loggerName); + loggerName = topic.StartsWith("$") ? topic.Substring(1) : string.Format("{0}.{1}", defaultUserLogNamespace, topic.Trim()); } - return globalLog; +#if NETCORE + if (_instance != null) + { + return new GXLoggerMsExtensions(_instance.CreateLogger(loggerName)); + } + string defaultRepository = LogManager.GetRepository(System.Reflection.Assembly.GetEntryAssembly()).Name; +#else + string defaultRepository = LogManager.GetRepository().Name; +#endif + return new GXLoggerLog4Net(log4net.LogManager.GetLogger(defaultRepository, loggerName)); + } public static void Write(int logLevel, string message, string topic) @@ -44,7 +53,7 @@ public static void Write(int logLevel, string message, string topic) public static void Write(string message, string topic, int logLevel) { - ILog log = GetLogger(topic); + IGXLogger log = GetLogger(topic); LogLevel logLvl = (LogLevel)logLevel; switch (logLvl) @@ -52,57 +61,63 @@ public static void Write(string message, string topic, int logLevel) case LogLevel.Off: break; case LogLevel.Trace: - log.Debug(message); + GXLogging.Trace(log, message); break; case LogLevel.Debug: - log.Debug(message); + GXLogging.Debug(log, message); break; case LogLevel.Info: - log.Info(message); + GXLogging.Info(log, message); break; case LogLevel.Warn: - log.Warn(message); + GXLogging.Warn(log, message); break; case LogLevel.Error: - log.Error(message); + GXLogging.Error(log, message); break; case LogLevel.Fatal: - log.Fatal(message); + GXLogging.Critical(log, message); break; default: - log.Debug(message); + GXLogging.Debug(log, message); break; } } public static void Write(string message, string topic = "") { - GetLogger(topic).Debug(message); + IGXLogger log = GetLogger(topic); + GXLogging.Debug(log, message); } public static void Fatal(string message, string topic = "") { - GetLogger(topic).Fatal(message); + IGXLogger log = GetLogger(topic); + GXLogging.Critical(log, message); } public static void Error(string message, string topic = "") { - GetLogger(topic).Error(message); + IGXLogger log = GetLogger(topic); + GXLogging.Error(log, message); } public static void Warning(string message, string topic = "") { - GetLogger(topic).Warn(message); + IGXLogger log = GetLogger(topic); + GXLogging.Warn(log, message); } public static void Info(string message, string topic = "") { - GetLogger(topic).Info(message); + IGXLogger log = GetLogger(topic); + GXLogging.Info(log, message); } public static void Debug(string message, string topic = "") { - GetLogger(topic).Debug(message); + IGXLogger log = GetLogger(topic); + GXLogging.Debug(log, message); } } } diff --git a/dotnet/src/dotnetframework/GxClasses/Dialog/IProcess.cs b/dotnet/src/dotnetframework/GxClasses/Dialog/IProcess.cs index 74b48f2f1..04265fe3a 100644 --- a/dotnet/src/dotnetframework/GxClasses/Dialog/IProcess.cs +++ b/dotnet/src/dotnetframework/GxClasses/Dialog/IProcess.cs @@ -18,7 +18,8 @@ public interface IProcessHelper } public class OSHelper { - protected static readonly ILog log = log4net.LogManager.GetLogger(typeof(OSHelper)); + protected static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + protected static string OsProviderAssembly = "GxClasses.Win"; protected static object syncRoot = new Object(); diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/ExpressionEvaluator.cs b/dotnet/src/dotnetframework/GxClasses/Domain/ExpressionEvaluator.cs index b9dd259b3..8b6a4c4d6 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/ExpressionEvaluator.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/ExpressionEvaluator.cs @@ -17,7 +17,7 @@ namespace GeneXus.Utils /// public class ExpressionEvaluator { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Utils.ExpressionEvaluator)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); internal IGxContext context; internal bool throwExceptions; diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GXFileIO.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GXFileIO.cs index 5788c1d3e..09aeea02c 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GXFileIO.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GXFileIO.cs @@ -223,8 +223,9 @@ public void MoveTo(string desDirName) } public class GxFileInfo : IGxFileInfo { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GxFileInfo)); - private FileInfo _file; + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + + private FileInfo _file; private string _baseDirectory; public GxFileInfo(FileInfo file) @@ -654,7 +655,7 @@ public enum GxFileType public class GxFile { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GxFile)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); internal IGxFileInfo _file; string _baseDirectory; @@ -1574,7 +1575,7 @@ public void Close() public class GxDirectory { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GxDirectory)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); IGxDirectoryInfo _directory; string _baseDirectory; int _lastError; diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GXGeolocation.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GXGeolocation.cs index 6dff7a7de..9998431c6 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GXGeolocation.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GXGeolocation.cs @@ -19,7 +19,7 @@ namespace GX public class GXGeolocation { private const String MAPS_URI = "https://maps.google.com/maps/api/"; - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GX.GXGeolocation)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private static double GetComponent(String geolocation, int item) { diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GXLDAP.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GXLDAP.cs index da79ac358..0ef849ae7 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GXLDAP.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GXLDAP.cs @@ -11,7 +11,7 @@ namespace GeneXus.Utils { public class GXLDAPClient { - static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); string _server; int _port; diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs index f18f4a708..f34142d60 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs @@ -1898,7 +1898,7 @@ public void Dispose() public class GXXMLWriter: IDisposable { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GXXMLWriter)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private XmlTextWriter writer; private short errorCode; diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs index e1484d23d..49d38c131 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs @@ -802,8 +802,8 @@ public void FromStringCollection(GxSimpleCollection value) public class GxObjectCollectionBase : GxSimpleCollection { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Utils.GxObjectCollectionBase)); - + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + public string _containedName; public string _containedXmlNamespace; public string _containedType; @@ -1042,7 +1042,7 @@ public string Name [XmlType(IncludeInSchema = false)] public class GxUserType : IGxXMLSerializable, ICloneable, IGxJSONAble, IGxJSONSerializable, IGXAssigned { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Utils.GxUserType)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); protected GXProperties dirties = new GXProperties(); static object setupChannelObject = null; diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxGenericCollections.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxGenericCollections.cs index 9acc4c5b0..577126aca 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxGenericCollections.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxGenericCollections.cs @@ -50,7 +50,7 @@ public GXBaseList() public class GXBaseCollection : GXBaseList, IGxXMLSerializable, IGxJSONAble, IGxCollection, IGxJSONSerializable where T : GxUserType, IGxXMLSerializable, IGxJSONAble, new() { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Utils.GXBaseCollection)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger>(); public string _containedName; public string _containedXmlNamespace; public IGxContext context; @@ -619,7 +619,7 @@ public override void RemoveItem(int idx) [Serializable] public class GXBCCollection : GXBaseCollection, IGXBCCollection where T : GxSilentTrnSdt, new() { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Utils.GXBCCollection)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger>(); public GXBCCollection() : base() { } public GXBCCollection(IGxContext context, diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs index 0ba575f00..8496f3843 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs @@ -60,7 +60,7 @@ internal MultiPartTemplate() } public class GxHttpClient : IGxHttpClient, IDisposable { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Http.Client.GxHttpClient)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public const int _Basic = 0; public const int _Digest = 1; public const int _NTLM = 2; diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxMessaging.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxMessaging.cs index 75594364c..610bc3a8c 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxMessaging.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxMessaging.cs @@ -16,7 +16,8 @@ namespace GeneXus.Utils [SecuritySafeCritical] public class GxQueueMessage { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Utils.GxQueueMessage)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + int priority; Message message; @@ -207,7 +208,7 @@ public bool canAddMSMQPropertiesToGet( MessagePropertyFilter m, string key, stri [SecuritySafeCritical] public class GxQueue { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GxQueue)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); string provider; string user; diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxSession.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxSession.cs index d6c2ef005..2cdfddb49 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxSession.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxSession.cs @@ -33,7 +33,7 @@ string Id public class GxWebSession : IGxSession { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Http.GxWebSession)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private HttpSessionState _httpSession; #region InternalKeys GXNavigationHelper InternalKeyNavigationHelper; diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/SD/SDApis.cs b/dotnet/src/dotnetframework/GxClasses/Domain/SD/SDApis.cs index 363bd3eaf..fb6daed8f 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/SD/SDApis.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/SD/SDApis.cs @@ -11,9 +11,9 @@ namespace GX { public class ClientInformation { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GX.ClientInformation)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); - public static string AppVersionCode + public static string AppVersionCode { get { diff --git a/dotnet/src/dotnetframework/GxClasses/GxClasses.csproj b/dotnet/src/dotnetframework/GxClasses/GxClasses.csproj index 1e437fe5a..edf352ed3 100644 --- a/dotnet/src/dotnetframework/GxClasses/GxClasses.csproj +++ b/dotnet/src/dotnetframework/GxClasses/GxClasses.csproj @@ -1,4 +1,4 @@ - + net462 GxClasses diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXFileWatcher.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXFileWatcher.cs index 49cc89efe..6d91dac34 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXFileWatcher.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXFileWatcher.cs @@ -19,7 +19,7 @@ namespace GeneXus.Application public class GXFileWatcher : IDisposable { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GXFileWatcher)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private static volatile GXFileWatcher m_Instance; private static object m_SyncRoot = new Object(); TimeSpan TIMEOUT; diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXLogging.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXLogging.cs index d4a68765e..0cfa76acf 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXLogging.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXLogging.cs @@ -3,27 +3,377 @@ using System.Text; using log4net; using log4net.Core; +using System.Threading; +using log4net.Util; +using System.Globalization; +using System.Security; +#if NETCORE +using GeneXus.Services.Log; +using Microsoft.Extensions.Logging; +#endif namespace GeneXus { + public class GXLoggerFactory + { +#if NETCORE + static ILoggerFactory _instance = GXLogService.GetLogFactory(); +#endif + public static IGXLogger GetLogger(string categoryName) + { +#if NETCORE + if (_instance != null) + { + return new GXLoggerMsExtensions(_instance.CreateLogger(categoryName)); + } +#endif + return new GXLoggerLog4Net(log4net.LogManager.GetLogger(categoryName)); + } + public static IGXLogger GetLogger() where T : class + { +#if NETCORE + if (_instance != null) + { + return new GXLoggerMsExtensions(_instance.CreateLogger()); + } +#endif + return new GXLoggerLog4Net(log4net.LogManager.GetLogger(typeof(T))); + } + + } + public interface IGXLogger + { + bool IsTraceEnabled { get; } + bool IsErrorEnabled { get; } + bool IsWarningEnabled { get; } + bool IsDebugEnabled { get; } + bool IsInfoEnabled { get; } + bool IsCriticalEnabled { get; } + + bool TraceEnabled(); + bool CriticalEnabled(); + bool ErrorEnabled(); + bool WarningEnabled(); + bool DebugEnabled(); + bool InfoEnabled(); + + + void LogTrace(string value); + void LogError(string msg, Exception ex); + + void LogError(string msg); + void LogError(string msg, params string[] list); + void LogWarning(Exception ex, string msg); + void LogWarning(string msg); + void LogWarning(string msg, params string[] list); + void LogDebug(string msg); + void LogDebug(Exception ex, string msg); + void LogDebug(string msg, params string[] list); + void LogInfo(string msg); + void LogInfo(string msg, params string[] list); + void LogCritical(string msg); + void LogCritical(Exception ex , string msg); + void LogCritical(string msg, params string[] list); + } +#if NETCORE + internal class GXLoggerMsExtensions : IGXLogger + { + internal Microsoft.Extensions.Logging.ILogger log { get; set; } + + internal GXLoggerMsExtensions(Microsoft.Extensions.Logging.ILogger logInstance) + { + log = logInstance; + } + public bool IsTraceEnabled { get => TraceEnabled(); } + public bool IsErrorEnabled { get => ErrorEnabled(); } + public bool IsWarningEnabled { get => WarningEnabled(); } + public bool IsDebugEnabled { get => DebugEnabled(); } + public bool IsInfoEnabled { get => InfoEnabled(); } + public bool IsCriticalEnabled { get => CriticalEnabled(); } + public bool TraceEnabled() + { + return log.IsEnabled(LogLevel.Trace); + } + public bool ErrorEnabled() + { + return log.IsEnabled(LogLevel.Error); + } + public bool WarningEnabled() + { + return log.IsEnabled(LogLevel.Warning); + } + public bool DebugEnabled() + { + return log.IsEnabled(LogLevel.Debug); + } + public bool InfoEnabled() + { + return log.IsEnabled(LogLevel.Information); + } + public bool CriticalEnabled() + { + return log.IsEnabled(LogLevel.Critical); + } + public void LogTrace(string msg) + { + log.LogTrace(msg); + } + public void LogError(string msg, Exception ex) + { + log.LogError(ex, msg); + } + public void LogError(string msg) + { + log.LogError(msg); + } + public void LogError(string msg, params string[] list) + { + log.LogError(msg, list); + } + public void LogWarning(Exception ex, string msg) + { + log.LogWarning(ex, msg); + } + public void LogWarning(string msg) + { + log.LogWarning(msg); + } + public void LogWarning(string msg, params string[] list) + { + log.LogWarning(msg, list); + } + public void LogDebug(string msg) + { + log.LogDebug(msg); + } + public void LogDebug(string msg, params string[] list) + { + log.LogDebug(msg, list); + } + public void LogDebug(Exception ex, string msg) + { + log.LogDebug(ex, msg); + } + public void LogInfo(string msg) + { + log.LogInformation(msg); + } + + public void LogInfo(string msg, params string[] list) + { + log.LogInformation(msg, list); + } + public void LogCritical(string msg) + { + log.LogCritical(msg); + } + public void LogCritical(Exception ex, string msg) + { + log.LogCritical(ex, msg); + } + public void LogCritical(string msg, params string[] list) + { + log.LogCritical(msg, list); + } + } +#endif + internal class GXLoggerLog4Net : IGXLogger + { +#if NETCORE + const string ThreadNameNet8 = ".NET TP Worker"; + const string ThreadNameNet6 = ".NET ThreadPool Worker"; + const string ThreadId = "threadid"; +#endif + internal ILog log { get; set; } + + internal GXLoggerLog4Net(ILog logInstance) + { + log = logInstance; + } + void SetThreadIdForLogging() + { +#if NETCORE + if (ThreadContext.Properties[ThreadId] == null) + { + string name = Thread.CurrentThread.Name; + if (!string.IsNullOrEmpty(name) && name != ThreadNameNet6 && !name.StartsWith(ThreadNameNet8)) + { + ThreadContext.Properties[ThreadId] = name; + } + else + { + try + { + ThreadContext.Properties[ThreadId] = SystemInfo.CurrentThreadId.ToString(NumberFormatInfo.InvariantInfo); + } + catch (SecurityException) + { + log.Debug("Security exception while trying to get current thread ID. Error Ignored. Empty thread name."); + ThreadContext.Properties[ThreadId] = Thread.CurrentThread.GetHashCode().ToString(CultureInfo.InvariantCulture); + } + } + } +#endif + } + public bool IsTraceEnabled { get => TraceEnabled(); } + public bool IsErrorEnabled { get => ErrorEnabled(); } + public bool IsWarningEnabled { get => WarningEnabled(); } + public bool IsDebugEnabled { get => DebugEnabled(); } + public bool IsInfoEnabled { get => InfoEnabled(); } + public bool IsCriticalEnabled { get => CriticalEnabled(); } + public bool TraceEnabled() + { + return log.Logger.IsEnabledFor(Level.Trace); + } + public bool ErrorEnabled() + { + return log.IsErrorEnabled; + } + public bool WarningEnabled() + { + return log.IsWarnEnabled; + } + public bool DebugEnabled() + { + return log.IsDebugEnabled; + } + public bool InfoEnabled() + { + return log.IsInfoEnabled; + } + public bool CriticalEnabled() + { + return log.IsFatalEnabled; + } + + public void LogTrace(string value) + { + SetThreadIdForLogging(); + log.Logger.Log(MethodBase.GetCurrentMethod().DeclaringType, Level.Trace, value, null); + } + public void LogError(string msg, Exception ex) + { + SetThreadIdForLogging(); + log.Error(msg, ex); + } + public void LogError(string msg) + { + SetThreadIdForLogging(); + log.Error(msg); + } + public void LogError(string msg, params string[] list) + { + StringBuilder message = new StringBuilder(); + message.Append(msg); + foreach (string parm in list) + { + message.Append(parm); + } + + LogError(message.ToString()); + } + public void LogWarning(Exception ex, string msg) + { + SetThreadIdForLogging(); + log.Warn(msg, ex); + } + public void LogWarning(string msg) + { + SetThreadIdForLogging(); + log.Warn(msg); + } + public void LogWarning(string msg, params string[] list) + { + StringBuilder message = new StringBuilder(); + message.Append(msg); + foreach (string parm in list) + { + message.Append(parm); + } + + LogWarning(message.ToString()); + } + public void LogDebug(string msg) + { + SetThreadIdForLogging(); + log.Debug(msg); + } + + public void LogDebug(Exception ex, string msg) + { + SetThreadIdForLogging(); + log.Debug(msg, ex); + } + public void LogDebug(string msg, params string[] list) + { + StringBuilder message = new StringBuilder(); + message.Append(msg); + foreach (string parm in list) + { + message.Append(parm); + } + + LogDebug(message.ToString()); + } + public void LogInfo(string msg) + { + SetThreadIdForLogging(); + log.Info(msg); + } + public void LogInfo(string msg, params string[] list) + { + StringBuilder message = new StringBuilder(); + message.Append(msg); + foreach (string parm in list) + { + message.Append(parm); + } + + LogInfo(message.ToString()); + } + + public void LogCritical(string msg) + { + SetThreadIdForLogging(); + log.Fatal(msg); + } + public void LogCritical(Exception ex, string msg) + { + SetThreadIdForLogging(); + log.Fatal(msg, ex); + } + + public void LogCritical(string msg, params string[] list) + { + StringBuilder message = new StringBuilder(); + message.Append(msg); + foreach (string parm in list) + { + message.Append(parm); + } + + LogCritical(message.ToString()); + } + } public static class GXLogging { + #region log4NET + // Legacy // public static void Trace(this ILog log, params string[] list) { if (log.Logger.IsEnabledFor(Level.Trace)) { - log.Logger.Log(MethodBase.GetCurrentMethod().DeclaringType, Level.Trace, String.Join(" ", list), null); + log.Logger.Log(MethodBase.GetCurrentMethod().DeclaringType, Level.Trace, string.Join(" ", list), null); } } - public static void Error(ILog log, string msg, Exception ex) + public static void Error(ILog log, string msg, Exception ex) { if (log.IsErrorEnabled) { log.Error(msg, ex); } } - public static void ErrorSanitized(ILog log, string msg, Exception ex) { if (log.IsErrorEnabled) @@ -31,25 +381,25 @@ public static void ErrorSanitized(ILog log, string msg, Exception ex) log.Error(Utils.StringUtil.Sanitize(msg, Utils.StringUtil.LogUserEntryWhiteList), ex); } } - public static void Error(ILog log, string msg1, string msg2, Exception ex) { Error(log, msg1 + msg2, ex); } - public static void Error(ILog log, Exception ex, params string[] list) + public static void Error(ILog log, Exception ex, params string[] list) { - if (log.IsErrorEnabled){ - foreach (string parm in list){ + if (log.IsErrorEnabled) + { + foreach (string parm in list) + { log.Error(parm); } } } - public static void Error(ILog log, params string[] list) + public static void Error(ILog log, params string[] list) { Error(log, null, list); } - - public static void Warn(ILog log, Exception ex, params string[] list) + public static void Warn(ILog log, Exception ex, params string[] list) { if (log.IsWarnEnabled) { @@ -64,25 +414,25 @@ public static void Warn(ILog log, Exception ex, params string[] list) log.Warn(msg); } } - public static void Warn(ILog log, params string[] list) + public static void Warn(ILog log, params string[] list) { Warn(log, null, list); } - public static void Warn(ILog log, string msg, Exception ex) + public static void Warn(ILog log, string msg, Exception ex) { if (log.IsWarnEnabled) { log.Warn(msg, ex); } } - public static void Debug(ILog log, Exception ex, params string[] list) + public static void DebugSanitized(ILog log, Exception ex, params string[] list) { if (log.IsDebugEnabled) { StringBuilder msg = new StringBuilder(); foreach (string parm in list) { - msg.Append(parm); + msg.Append(Utils.StringUtil.Sanitize(parm, Utils.StringUtil.LogUserEntryWhiteList)); } if (ex != null) log.Debug(msg, ex); @@ -90,15 +440,18 @@ public static void Debug(ILog log, Exception ex, params string[] list) log.Debug(msg); } } - - public static void DebugSanitized(ILog log, Exception ex, params string[] list) + public static void Debug(ILog log, params string[] list) + { + Debug(log, null, list); + } + public static void Debug(ILog log, Exception ex, params string[] list) { if (log.IsDebugEnabled) { StringBuilder msg = new StringBuilder(); foreach (string parm in list) { - msg.Append(Utils.StringUtil.Sanitize(parm, Utils.StringUtil.LogUserEntryWhiteList)); + msg.Append(parm); } if (ex != null) log.Debug(msg, ex); @@ -106,14 +459,6 @@ public static void DebugSanitized(ILog log, Exception ex, params string[] list) log.Debug(msg); } } - - - - public static void Debug(ILog log, params string[] list) - { - Debug(log, null, list); - } - public static void DebugSanitized(ILog log, params string[] list) { DebugSanitized(log, null, list); @@ -127,18 +472,18 @@ public static void Debug(ILog log, string startMsg, Func buildMsg) log.Debug(startMsg + msg); } } - public static void Debug(ILog log, string msg1, string msg2, Exception ex) + public static void Debug(ILog log, string msg1, string msg2, Exception ex) { Debug(log, msg1 + msg2, ex); } - public static void Debug(ILog log, string msg, Exception ex) + public static void Debug(ILog log, string msg, Exception ex) { if (log.IsDebugEnabled) { log.Debug(msg, ex); } } - public static void Info(ILog log, params string[] list) + public static void Info(ILog log, params string[] list) { if (log.IsInfoEnabled) { @@ -150,6 +495,282 @@ public static void Info(ILog log, params string[] list) log.Info(msg); } } + #endregion + + #region Microsoft.Extensions + internal static void Trace(IGXLogger logger, params string[] list) + { + if (logger != null) + { + if (logger.IsTraceEnabled) + logger.LogTrace(string.Join(" ", list)); + } + } + public static void Critical(IGXLogger logger, params string[] list) + { + if (logger != null) + { + if (logger.IsCriticalEnabled) + { + logger.LogCritical(string.Join(" ", list)); + } + } + } + public static void Critical(IGXLogger logger, string msg, Exception ex) + { + if (logger != null) + { + if (logger.IsCriticalEnabled) + { + logger.LogCritical(ex, msg); + } + } + } + public static void Critical(IGXLogger logger, string msg, params string[] list) + { + if (logger != null) + { + if (logger.IsCriticalEnabled) + { + logger.LogCritical(msg, list); + } + } + } + + public static void Error(IGXLogger logger, string msg, Exception ex) + { + if (logger != null) + { + if (logger.IsErrorEnabled) + { + logger.LogError(msg, ex); + } + } + } + public static void Error(IGXLogger logger, string msg, params string[] list ) + { + if (logger != null) + { + if (logger.IsErrorEnabled) + { + logger.LogError(msg, list); + } + } + } + + internal static void ErrorSanitized(IGXLogger logger, string msg, Exception ex) + { + if (logger != null) + { + if (logger.IsErrorEnabled) + { + logger.LogError(Utils.StringUtil.Sanitize(msg, Utils.StringUtil.LogUserEntryWhiteList), ex); + } + } + } + + internal static void Error(IGXLogger logger, string msg1, string msg2, Exception ex) + { + Error(logger, msg1 + msg2, ex); + } + + internal static void Error(IGXLogger logger, Exception ex, params string[] list) + { + if (logger != null) + { + if (logger.IsErrorEnabled) + { + logger.LogError(ex.Message); + foreach (string parm in list) + { + logger.LogError(parm); + } + } + } + } + internal static void Error(IGXLogger logger, params string[] list) + { + if (logger != null) + { + if (logger.IsErrorEnabled) + { + foreach (string parm in list) + { + logger.LogError(parm); + } + } + } + } + public static void Warn(IGXLogger logger, Exception ex, params string[] list) + { + if (logger != null) + { + if (logger.IsWarningEnabled) + { + StringBuilder msg = new StringBuilder(); + foreach (string parm in list) + { + msg.Append(parm); + } + if (ex != null) + logger.LogWarning(ex, msg.ToString()); + else + logger.LogWarning(msg.ToString()); + } + } + } + public static void Warn(IGXLogger logger, params string[] list) + { + if (logger != null) + { + if (logger.IsWarningEnabled) + { + StringBuilder msg = new StringBuilder(); + foreach (string parm in list) + { + msg.Append(parm); + } + logger.LogWarning(msg.ToString()); + } + } + } + public static void Warn(IGXLogger logger, string msg, params string[] list) + { + if (logger != null) + { + if (logger.IsWarningEnabled) + { + logger.LogWarning(msg, list); + } + } + } + public static void Warn(IGXLogger logger, string msg, Exception ex) + { + if (logger != null) + { + if (logger.IsWarningEnabled) + { + logger.LogWarning(ex, msg); + } + } + } + internal static void DebugSanitized(IGXLogger logger, Exception ex, params string[] list) + { + if (logger != null) + { + if (logger.IsDebugEnabled) + { + StringBuilder msg = new StringBuilder(); + foreach (string parm in list) + { + msg.Append(Utils.StringUtil.Sanitize(parm, Utils.StringUtil.LogUserEntryWhiteList)); + } + if (ex != null) + logger.LogDebug(ex, msg.ToString()); + else + logger.LogDebug(msg.ToString()); + } + } + } + internal static void DebugSanitized(IGXLogger logger, params string[] list) + { + DebugSanitized(logger, null, list); + } + public static void Debug(IGXLogger logger, Exception ex, params string[] list) + { + if (logger != null) + { + if (logger.IsDebugEnabled) + { + StringBuilder msg = new StringBuilder(); + foreach (string parm in list) + { + msg.Append(parm); + } + if (ex != null) + logger.LogDebug(ex, msg.ToString()); + else + logger.LogDebug(msg.ToString()); + } + } + } + public static void Debug(IGXLogger logger, params string[] list) + { + if (logger != null) + { + if (logger.IsDebugEnabled) + { + StringBuilder msg = new StringBuilder(); + foreach (string parm in list) + { + msg.Append(parm); + } + + logger.LogDebug(msg.ToString()); + } + } + } + + public static void Debug(IGXLogger logger, string startMsg, Func buildMsg) + { + if (logger != null) + { + if (logger.IsDebugEnabled) + { + string msg = buildMsg(); + logger.LogDebug(startMsg + msg); + } + } + } + public static void Debug(IGXLogger logger, string msg1, string msg2, Exception ex) + { + Debug(logger, msg1 + msg2, ex); + } + public static void Debug(IGXLogger logger, string msg, params string[] list) + { + if (logger != null) + { + if (logger.IsDebugEnabled) + { + logger.LogDebug(msg, list); + } + } + } + public static void Debug(IGXLogger logger, string msg, Exception ex) + { + if (logger != null) + { + if (logger.IsDebugEnabled) + { + logger.LogDebug(ex, msg); + } + } + } + public static void Info(IGXLogger logger, params string[] list) + { + if (logger != null) + { + if (logger.IsInfoEnabled) + { + StringBuilder msg = new StringBuilder(); + foreach (string parm in list) + { + msg.Append(parm); + } + logger.LogInfo(msg.ToString()); + } + } + } + public static void Info(IGXLogger logger, string msg, params string[] list) + { + if (logger != null) { + if (logger.IsInfoEnabled) + { + logger.LogInfo(msg.ToString(), list); + } + } + } + #endregion } } diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXMetadata.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXMetadata.cs index 770cc499e..eba8f33fc 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXMetadata.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXMetadata.cs @@ -18,7 +18,7 @@ namespace GeneXus.Metadata public class ClassLoader { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Metadata.ClassLoader)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); #if NETCORE private const string GXWEBPROCEDURE_TYPE = "GeneXus.Procedure.GXWebProcedure"; diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXRes.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXRes.cs index 41967b215..a59221c8b 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXRes.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXRes.cs @@ -20,7 +20,7 @@ namespace GeneXus.Resources public class GXResourceManager { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Resources.GXResourceManager)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); static ConcurrentDictionary _rm = new ConcurrentDictionary(); static ConcurrentDictionary _localUtils = new ConcurrentDictionary(); static string _defaultLangName; diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestUtils.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestUtils.cs index da14c4012..e6e400f8e 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestUtils.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestUtils.cs @@ -96,7 +96,7 @@ public class UploadCachedFile internal class RestAPIHelpers { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Utils.RestAPIHelpers)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public static Dictionary ReadRestParameters(string restData) { diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXUtilsGeospatial.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXUtilsGeospatial.cs index 259e61060..42a1f2cf3 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXUtilsGeospatial.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXUtilsGeospatial.cs @@ -33,7 +33,7 @@ int Srid class SQLGeographyWrapper { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Utils.SQLGeographyWrapper)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); static Assembly _geoAssembly; public const string SqlGeographyClass = "Microsoft.SqlServer.Types.SqlGeography"; public const string SqlGeometryClass = "Microsoft.SqlServer.Types.SqlGeometry"; @@ -152,7 +152,7 @@ internal static object STGeomFromText(string geoText, int sRID) [DataContract] public class Geospatial : IGeographicNative { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Utils.Geospatial)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); internal const string EMPTY_GEOMETRY = "GEOMETRYCOLLECTION EMPTY"; const string EMPTY_GEOGRAPHY = "GEOGRAPHY EMPTY"; diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs index 213448533..1f3d73ab4 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs @@ -76,7 +76,7 @@ public class WrappedJsonError public class HttpHelper { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Http.HttpHelper)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); /* * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control * Specifying no-cache or max-age=0 indicates that diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/JSONHelper.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/JSONHelper.cs index 663ff5a08..a638b3873 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/JSONHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/JSONHelper.cs @@ -137,7 +137,7 @@ internal static GXJsonSerializer Instance public class JSONHelper { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Utils.JSONHelper)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); static string WFCDateTimeFormat = Preferences.WFCDateTimeMillis ? DateTimeUtil.JsonDateFormatMillis : DateTimeUtil.JsonDateFormat; public static bool IsJsonNull(object jobject) { diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/ThemeHelper.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/ThemeHelper.cs index c5111af43..aa96d8b3a 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/ThemeHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/ThemeHelper.cs @@ -10,7 +10,7 @@ namespace GeneXus.Helpers { public sealed class ThemeHelper { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Helpers.ThemeHelper)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private static ConcurrentDictionary m_themes = new ConcurrentDictionary(); private static ThemeData CreateDefaultThemeData(string themeName) { diff --git a/dotnet/src/dotnetframework/GxClasses/Management/GXManagement.cs b/dotnet/src/dotnetframework/GxClasses/Management/GXManagement.cs index ed9aa8d42..90f4fadec 100644 --- a/dotnet/src/dotnetframework/GxClasses/Management/GXManagement.cs +++ b/dotnet/src/dotnetframework/GxClasses/Management/GXManagement.cs @@ -345,7 +345,7 @@ string LastConnectionId [SecuritySafeCritical] public class WMIApplicationServer : IWMIApplicationServer { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(WMIApplicationServer)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private static WMIApplicationServer instance; private static object syncObj = new object(); public static WMIApplicationServer Instance() @@ -434,7 +434,8 @@ public void CleanUp() [SecuritySafeCritical] public class WMICache : IWMICache { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(WMICache)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + InProcessCache cache; Hashtable wmicacheItems; long maxCacheStorageSize; @@ -543,7 +544,7 @@ public void Remove(string key) [SecuritySafeCritical] public class WMICacheItem :IWMICacheItem { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(WMICacheItem)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); string stmt; ICacheItemExpiration itemExpiration; @@ -635,7 +636,7 @@ public void CleanUp() [SecuritySafeCritical] public class WMIConnection : IWMIConnection { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(WMIConnection)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); GxConnection connection; public WMIConnection(GxConnection connection) @@ -786,7 +787,7 @@ public void CleanUp() [SecuritySafeCritical] public class WMIDataSource : IWMIDataSource { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(WMIDataSource)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); GxDataStore dataSource; public WMIDataSource(GxDataStore dataSource) @@ -861,7 +862,7 @@ public void CleanUp() [SecuritySafeCritical] public class WMIServerUserInformation :IWMIServerUserInformation { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(WMIServerUserInformation)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); ServerUserInformation userInfo; string lastConnectionId; diff --git a/dotnet/src/dotnetframework/GxClasses/Management/GXPerformance.cs b/dotnet/src/dotnetframework/GxClasses/Management/GXPerformance.cs index 36d9d07c4..823738b4b 100644 --- a/dotnet/src/dotnetframework/GxClasses/Management/GXPerformance.cs +++ b/dotnet/src/dotnetframework/GxClasses/Management/GXPerformance.cs @@ -661,7 +661,7 @@ public void IncSentencesCount(ICursor cursor) [SecuritySafeCritical] public class WMIDataStoreProviders:WMIDataStoreProvidersBase { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(WMIDataStoreProviders)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private WMIDataStoreProviders() { @@ -735,7 +735,7 @@ public WMIDataStoreProvider(string datastoreName) : base() [SecuritySafeCritical] public class WMIDataStoreProviderBase { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(WMIDataStoreProviderBase)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private long statementCount; private long statementSelectCount; diff --git a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs index 8877eb7e2..e1c5cdab4 100644 --- a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs +++ b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs @@ -56,7 +56,8 @@ public abstract class GXHttpHandler : GXBaseObject, IHttpHandler public abstract class GXHttpHandler : WebControl, IHttpHandler #endif { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Http.GXHttpHandler)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + internal const string GX_AJAX_REQUEST_HEADER = "GxAjaxRequest"; internal const string GX_SPA_GXOBJECT_RESPONSE_HEADER = "X-GXOBJECT"; internal const string GX_SPA_MASTERPAGE_HEADER = "X-SPA-MP"; @@ -1837,7 +1838,7 @@ private bool ValidateObjectAccess(String cmpCtx) SendResponseStatus(HttpStatusCode.Unauthorized); if (context.GetBrowserType() != GxContext.BROWSER_INDEXBOT) { - if (log.IsWarnEnabled) + if (log.IsWarningEnabled) { GXLogging.Warn(log, $"Validation security token '{GetObjectAccessWebToken(cmpCtx)}' failed for program: '{cmpCtx + this.GetPgmname().ToUpper()}'"); } diff --git a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpModules.cs b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpModules.cs index 0398b09dd..89ab983df 100644 --- a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpModules.cs +++ b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpModules.cs @@ -206,7 +206,7 @@ public void ServicesGroupSetting(string webPath) } public class GXSessionModule : IHttpModule { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GXSessionModule)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); HttpApplication App; const string ASPNETSESSION_COOKIE = "ASP.NET_SessionId"; string cookieName= ASPNETSESSION_COOKIE; @@ -311,7 +311,7 @@ void IHttpModule.Dispose() } public class GXRewriter : IHttpModule { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GXRewriter)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private static RewriterModule rewriter; private static bool moduleStarted; private static bool enabled; diff --git a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpServices.cs b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpServices.cs index 5d7ef1e35..fd96e2a76 100644 --- a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpServices.cs +++ b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpServices.cs @@ -34,6 +34,8 @@ namespace GeneXus.Http using System.Linq; using GeneXus.Procedure; using GxClasses.Web.Middleware; + using Microsoft.AspNetCore.Hosting; + #else using System.Web.UI; @@ -144,7 +146,8 @@ public override void webExecute() public class GXReorServices : GXHttpHandler { - static readonly ILog log = LogManager.GetLogger(typeof(GXReorServices)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + static Assembly _reorAssembly; static Assembly _gxDataInitializationAssembly; readonly string[] reorArgs = { "-force", "-ignoreresume", "-nogui", "-noverifydatabaseschema" }; @@ -570,7 +573,7 @@ protected override GAMSecurityLevel IntegratedSecurityLevel internal class GXOAuthAccessToken : GXHttpHandler, IRequiresSessionState { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Http.GXOAuthAccessToken)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public GXOAuthAccessToken() { diff --git a/dotnet/src/dotnetframework/GxClasses/Middleware/HandlerFactory.cs b/dotnet/src/dotnetframework/GxClasses/Middleware/HandlerFactory.cs index 596278e73..d35f14645 100644 --- a/dotnet/src/dotnetframework/GxClasses/Middleware/HandlerFactory.cs +++ b/dotnet/src/dotnetframework/GxClasses/Middleware/HandlerFactory.cs @@ -59,7 +59,7 @@ public bool IsReusable } class HandlerFactory : IHttpHandlerFactory { - private static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); private static List GxNamespaces; public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated) diff --git a/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs b/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs index 2f8ef622c..091060c9a 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs @@ -22,7 +22,8 @@ public class GxObjectParameter } public class GXBaseObject { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GXBaseObject)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + private Dictionary callTargetsByObject = new Dictionary(); protected IGxContext _Context; bool _isMain; diff --git a/dotnet/src/dotnetframework/GxClasses/Model/GXSilentTrn.cs b/dotnet/src/dotnetframework/GxClasses/Model/GXSilentTrn.cs index 371405266..56dd05080 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/GXSilentTrn.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/GXSilentTrn.cs @@ -138,7 +138,7 @@ public msglist GX_msglist [Serializable] public class GxSilentTrnSdt : GxUserType { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Utils.GxSilentTrnSdt)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public GxSilentTrnSdt(IGxContext context){ this.context = context; diff --git a/dotnet/src/dotnetframework/GxClasses/Model/GxMockProvider.cs b/dotnet/src/dotnetframework/GxClasses/Model/GxMockProvider.cs index 166a67064..5ed03425b 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/GxMockProvider.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/GxMockProvider.cs @@ -9,7 +9,7 @@ public interface IGxMock } public class GxMockProvider { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GxMockProvider)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private static volatile IGxMock provider; diff --git a/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs b/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs index 967201629..77fe03061 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs @@ -351,8 +351,7 @@ protected void initialize(int objClass, int objId, int dbgLines, long hash) } public class GXDataGridProcedure : GXProcedure { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GXDataGridProcedure)); - + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); const string HAS_NEXT_PAGE = "HasNextPage"; const string RECORD_COUNT = "RecordCount"; const string RECORD_COUNT_SUPPORTED = "RecordCountSupported"; @@ -434,11 +433,12 @@ public class GxReportUtils public static int OUTPUT_RVIEWER_NATIVE = 1; public static int OUTPUT_RVIEWER_DLL = 2; public static int OUTPUT_PDF = 3; + + static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + #if NETCORE const string PDF_LIBRARY_ITEXT8 = "ITEXT8"; #endif - static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - static public IReportHandler GetPrinter( int outputType, string path, Stream reportOutputStream) { IReportHandler reportHandler; diff --git a/dotnet/src/dotnetframework/GxClasses/Notifications/WebSocket/GXWebSocketFactory.cs b/dotnet/src/dotnetframework/GxClasses/Notifications/WebSocket/GXWebSocketFactory.cs index b35f4dc50..a0b36e7a8 100644 --- a/dotnet/src/dotnetframework/GxClasses/Notifications/WebSocket/GXWebSocketFactory.cs +++ b/dotnet/src/dotnetframework/GxClasses/Notifications/WebSocket/GXWebSocketFactory.cs @@ -6,9 +6,8 @@ namespace GeneXus.Notifications.WebSocket { public class GXWebSocketFactory { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GXWebSocketFactory)); - - public static IGXWebSocketAsync GetWebSocketProvider() + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + public static IGXWebSocketAsync GetWebSocketProvider() { IGXWebSocketAsync ws = null; try diff --git a/dotnet/src/dotnetframework/GxClasses/Printer/GxPrinter.cs b/dotnet/src/dotnetframework/GxClasses/Printer/GxPrinter.cs index 45b9b3989..760e2320d 100644 --- a/dotnet/src/dotnetframework/GxClasses/Printer/GxPrinter.cs +++ b/dotnet/src/dotnetframework/GxClasses/Printer/GxPrinter.cs @@ -1116,7 +1116,7 @@ float convertY( float y) } public class GxTxtPrinter : IPrintHandler { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GxTxtPrinter)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); StreamReader streamToRead; StreamWriter streamToWrite; List pageContents; diff --git a/dotnet/src/dotnetframework/GxClasses/Reorg/GXReorg.cs b/dotnet/src/dotnetframework/GxClasses/Reorg/GXReorg.cs index e2c0bba8f..ac28d111c 100644 --- a/dotnet/src/dotnetframework/GxClasses/Reorg/GXReorg.cs +++ b/dotnet/src/dotnetframework/GxClasses/Reorg/GXReorg.cs @@ -31,7 +31,7 @@ public interface IReorgReader public class GXReorganization { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Reorg.GXReorganization)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public virtual void initialize() { } public virtual void cleanup() { } static ArrayList lstMsgs; diff --git a/dotnet/src/dotnetframework/GxClasses/Security/GxSecurityProvider.cs b/dotnet/src/dotnetframework/GxClasses/Security/GxSecurityProvider.cs index fc6d125bf..c7b59f95f 100644 --- a/dotnet/src/dotnetframework/GxClasses/Security/GxSecurityProvider.cs +++ b/dotnet/src/dotnetframework/GxClasses/Security/GxSecurityProvider.cs @@ -35,7 +35,7 @@ public interface ISecurityProvider } public class GxSecurityProvider { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Security.GxSecurityProvider)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private static volatile ISecurityProvider provider; private static object syncRoot = new Object(); diff --git a/dotnet/src/dotnetframework/GxClasses/Security/WebSecurity.cs b/dotnet/src/dotnetframework/GxClasses/Security/WebSecurity.cs index 8199d0488..ab50dd078 100644 --- a/dotnet/src/dotnetframework/GxClasses/Security/WebSecurity.cs +++ b/dotnet/src/dotnetframework/GxClasses/Security/WebSecurity.cs @@ -1,8 +1,3 @@ -using GeneXus.Application; -using GeneXus.Configuration; -using GeneXus.Utils; -using log4net; -using Microsoft.IdentityModel.Tokens; using System; using System.IdentityModel.Tokens.Jwt; using System.Linq; @@ -10,6 +5,11 @@ using System.Security; using System.Security.Claims; using System.Text; +using GeneXus.Application; +using GeneXus.Configuration; +using GeneXus.Utils; +using log4net; +using Microsoft.IdentityModel.Tokens; using static GeneXus.Web.Security.SecureTokenHelper; namespace GeneXus.Web.Security @@ -17,7 +17,8 @@ namespace GeneXus.Web.Security [SecuritySafeCritical] public static class WebSecurityHelper { - private static readonly ILog _log = LogManager.GetLogger(typeof(GeneXus.Web.Security.WebSecurityHelper)); + static readonly IGXLogger _log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + const int SecretKeyMinimumLength = 16; public static string StripInvalidChars(string input) @@ -111,9 +112,10 @@ internal static bool VerifySecureSignedSDTToken(string cmpCtx, GxUserType value, [SecuritySafeCritical] public static class SecureTokenHelper { - private static readonly ILog _log = LogManager.GetLogger(typeof(GeneXus.Web.Security.SecureTokenHelper)); + + static readonly IGXLogger _log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); - public enum SecurityMode + public enum SecurityMode { Sign, SignEncrypt, diff --git a/dotnet/src/dotnetframework/GxClasses/Services/Caching/GxCache.cs b/dotnet/src/dotnetframework/GxClasses/Services/Caching/GxCache.cs index d186d0d91..bdb789012 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/Caching/GxCache.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/Caching/GxCache.cs @@ -95,8 +95,9 @@ public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOp public class CacheFactory { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Cache.CacheFactory)); - public static string CACHE_SD = "SD"; + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + + public static string CACHE_SD = "SD"; public static string CACHE_DB = "DB"; public static string CACHE_FILES = "FL"; public static string FORCE_HIGHEST_TIME_TO_LIVE = "FORCE_HIGHEST_TIME_TO_LIVE"; @@ -175,7 +176,7 @@ public static bool ForceHighestTimetoLive } public sealed class InProcessCache : ICacheService2 { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Cache.InProcessCache)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); ICacheStorage cacheStorage; IScavengingAlgorithm storageScavengingImplementation; @@ -644,7 +645,7 @@ public interface ICacheStorage public class SingletonCacheStorage : ICacheStorage { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Cache.SingletonCacheStorage)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private HybridDictionary cacheStorage = new HybridDictionary(); private long size; @@ -715,8 +716,9 @@ void ICacheStorage.Update(string key, object keyData) public class LruScavenging : IScavengingAlgorithm { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Cache.LruScavenging)); - private HybridDictionary itemsLastUsed; + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + + private HybridDictionary itemsLastUsed; private ICacheService cachingService; private ICacheStorage cacheStorage; private ICacheMetadata cacheMetadata; diff --git a/dotnet/src/dotnetframework/GxClasses/Services/GXRestServices.cs b/dotnet/src/dotnetframework/GxClasses/Services/GXRestServices.cs index 9eb75a4d3..65bcd4ce8 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/GXRestServices.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/GXRestServices.cs @@ -107,7 +107,7 @@ internal class CorrelationState } class CustomOperationSelector : WebHttpDispatchOperationSelector { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(CustomOperationSelector)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public CustomOperationSelector(ServiceEndpoint endpoint) : base(endpoint) { } protected override string SelectOperation(ref Message message, out bool uriMatched) { @@ -231,7 +231,8 @@ public override object ConvertStringToValue(string parameter, Type parameterType } public class GxRestService : System.Web.SessionState.IRequiresSessionState { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GxRestService)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + internal const string WARNING_HEADER = "Warning"; protected IGxContext context; private HttpContext httpContext; diff --git a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs index ad837f6d6..8909d45d8 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs @@ -51,7 +51,7 @@ public class GxRestWrapper public class GxRestWrapper : IHttpHandler, IRequiresSessionState #endif { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Application.GxRestWrapper)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); protected HttpContext _httpContext; protected IGxContext _gxContext; private GXBaseObject _procWorker; diff --git a/dotnet/src/dotnetframework/GxClasses/Services/Storage/ExternalProviderBase.cs b/dotnet/src/dotnetframework/GxClasses/Services/Storage/ExternalProviderBase.cs index 0a2a6dc20..6ce9055af 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/Storage/ExternalProviderBase.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/Storage/ExternalProviderBase.cs @@ -12,7 +12,7 @@ namespace GeneXus.Services { public abstract class ExternalProviderBase { - static readonly ILog logger = log4net.LogManager.GetLogger(typeof(ExternalProviderBase)); + static readonly IGXLogger logger = GXLoggerFactory.GetLogger(); private GXService service; @@ -41,7 +41,7 @@ public ExternalProviderBase(GXService s) s = ServiceFactory.GetGXServices()?.Get(GXServices.STORAGE_SERVICE); } catch (Exception) { - logger.Warn("STORAGE_SERVICE is not activated in CloudServices.config"); + GXLogging.Warn(logger, "STORAGE_SERVICE is not activated in CloudServices.config"); } } @@ -82,7 +82,7 @@ protected String GetEncryptedPropertyValue(String propertyName, String alternati if (value == null) { String errorMessage = String.Format($"Service configuration error - Property name {ResolvePropertyName(propertyName)} must be defined"); - logger.Fatal(errorMessage); + GXLogging.Critical(logger, errorMessage); throw new Exception(errorMessage); } return value; @@ -102,7 +102,7 @@ protected String GetEncryptedPropertyValue(String propertyName, String alternati } catch (Exception) { - logger.Warn($"Could not decrypt property name: {ResolvePropertyName(propertyName)}"); + GXLogging.Warn(logger, $"Could not decrypt property name: {ResolvePropertyName(propertyName)}"); } } return value; @@ -114,7 +114,7 @@ protected String GetPropertyValue(String propertyName, String alternativePropert if (value == null) { String errorMessage = String.Format($"Service configuration error - Property name {ResolvePropertyName(propertyName)} must be defined"); - logger.Fatal(errorMessage); + GXLogging.Critical(logger, errorMessage); throw new Exception(errorMessage); } return value; diff --git a/dotnet/src/dotnetframework/GxClasses/Services/Storage/GXServices.cs b/dotnet/src/dotnetframework/GxClasses/Services/Storage/GXServices.cs index 0c652ecf7..fc59e7b5c 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/Storage/GXServices.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/Storage/GXServices.cs @@ -1,21 +1,17 @@ -using GeneXus.Application; -using GeneXus.Utils; -using GeneXus.XML; -using log4net; using System; -using System.Linq; using System.Collections.Generic; using System.IO; -using System.Reflection; +using GeneXus.Application; +using GeneXus.Utils; +using GeneXus.XML; using GxClasses.Helpers; -using System.Reflection.Emit; - namespace GeneXus.Services { public class GXServices { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Services.GXServices)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + public static string STORAGE_SERVICE = "Storage"; public static string STORAGE_APISERVICE = "StorageAPI"; public static string CACHE_SERVICE = "Cache"; @@ -30,7 +26,6 @@ public class GXServices private Dictionary services = new Dictionary(); private static GXServices s_instance = null; private static object syncRoot = new Object(); - public static GXServices Instance { get @@ -52,7 +47,6 @@ public static GXServices Instance } set { } } - public void AddService(string name, GXService service) { services[name] = service; @@ -67,7 +61,7 @@ public static void LoadFromFile(string fileName, ref GXServices services) { if (services == null) services = new GXServices(); - GXLogging.Debug(log, "Loading service:", filePath); + GXXMLReader reader = new GXXMLReader(); reader.Open(filePath); reader.ReadType(1, "Services"); @@ -178,8 +172,7 @@ public class GXService public class ServiceFactory { private static ExternalProvider externalProvider = null; - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Services.ServiceFactory)); - + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public static GXServices GetGXServices() { return GXServices.Instance; diff --git a/dotnet/src/dotnetframework/GxClasses/View/GXWebControls.cs b/dotnet/src/dotnetframework/GxClasses/View/GXWebControls.cs index 434bb2bf6..ff887b8a5 100644 --- a/dotnet/src/dotnetframework/GxClasses/View/GXWebControls.cs +++ b/dotnet/src/dotnetframework/GxClasses/View/GXWebControls.cs @@ -711,7 +711,7 @@ public void FromJSONObject(dynamic obj) public abstract class GXWebControl : IGxJSONAble, IGxJSONSerializable { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GXWebControl)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); bool ForeColorFlag; bool BackColorFlag; Color _ForeColor; diff --git a/dotnet/src/dotnetframework/GxDataInitialization/GXDataInitialization.cs b/dotnet/src/dotnetframework/GxDataInitialization/GXDataInitialization.cs index a6a5291ed..c90fb871e 100644 --- a/dotnet/src/dotnetframework/GxDataInitialization/GXDataInitialization.cs +++ b/dotnet/src/dotnetframework/GxDataInitialization/GXDataInitialization.cs @@ -26,7 +26,7 @@ public DynTrnInitializer() { } public class GXDataInitialization : GXProcedure { - static readonly ILog log = log4net.LogManager.GetLogger(typeof(GXDataInitialization)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public GXDataInitialization() { context = GxContext.CreateDefaultInstance(); diff --git a/dotnet/src/dotnetframework/GxDataInitialization/GXDataInitialization.csproj b/dotnet/src/dotnetframework/GxDataInitialization/GXDataInitialization.csproj index a54201c6f..6cb86a0b4 100644 --- a/dotnet/src/dotnetframework/GxDataInitialization/GXDataInitialization.csproj +++ b/dotnet/src/dotnetframework/GxDataInitialization/GXDataInitialization.csproj @@ -8,11 +8,6 @@ DataInitialization GeneXus.DataInitialization - - - runtime - - diff --git a/dotnet/src/dotnetframework/GxExcel/GxExcel.csproj b/dotnet/src/dotnetframework/GxExcel/GxExcel.csproj index 8a28b9670..1166d138b 100644 --- a/dotnet/src/dotnetframework/GxExcel/GxExcel.csproj +++ b/dotnet/src/dotnetframework/GxExcel/GxExcel.csproj @@ -9,7 +9,6 @@ - diff --git a/dotnet/src/dotnetframework/GxExcel/GxExcelEPPlus.cs b/dotnet/src/dotnetframework/GxExcel/GxExcelEPPlus.cs index 134c531d2..2ebb4d027 100644 --- a/dotnet/src/dotnetframework/GxExcel/GxExcelEPPlus.cs +++ b/dotnet/src/dotnetframework/GxExcel/GxExcelEPPlus.cs @@ -10,9 +10,9 @@ namespace GeneXus.Office.ExcelGXEPPlus public class ExcelDocument : IGxError, IExcelDocument { - static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); - private ExcelPackage p; + private ExcelPackage p; public string dateFormat = "m/d/yy h:mm"; public bool OpenFromTemplate { get; set;} @@ -357,9 +357,9 @@ public short Init(string previousMsgError) public class ExcelCells : IExcelCells { - static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); - private IGxError m_errAccess; + private IGxError m_errAccess; private int pWidth, pHeight; private int pColPos; private ExcelWorksheet pSelectedSheet; diff --git a/dotnet/src/dotnetframework/GxExcel/GxExcelI.cs b/dotnet/src/dotnetframework/GxExcel/GxExcelI.cs index 149d69078..14bdb537c 100644 --- a/dotnet/src/dotnetframework/GxExcel/GxExcelI.cs +++ b/dotnet/src/dotnetframework/GxExcel/GxExcelI.cs @@ -12,9 +12,10 @@ namespace GeneXus.Office { public class ExcelDocumentI { - static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - public short Index = -1; + static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + + public short Index = -1; private string fileName; [Obsolete("It is here for backward compatibility", false)] @@ -739,7 +740,7 @@ public short Underline public class IExcelDocumentWrapper : IExcelDocument { - static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); Interop.GXOFFICE2Lib.IExcelDocument doc; @@ -935,9 +936,8 @@ public void CalculateFormulas() #endif public class ExcelUtils { - static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - public static void Show(string xlsFileName) + static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + public static void Show(string xlsFileName) { Process p = new Process(); p.StartInfo.FileName = "excel"; diff --git a/dotnet/src/dotnetframework/GxExcel/GxExcelLite.cs b/dotnet/src/dotnetframework/GxExcel/GxExcelLite.cs index 59f035170..258f9f879 100644 --- a/dotnet/src/dotnetframework/GxExcel/GxExcelLite.cs +++ b/dotnet/src/dotnetframework/GxExcel/GxExcelLite.cs @@ -13,7 +13,7 @@ namespace GeneXus.Office.ExcelLite { public class ExcelCells : IExcelCells { - static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); public ExcelCells(IGxError errAccess, object ef, int row, int col, int height, int width) { @@ -368,7 +368,7 @@ public int Color public class ExcelDocument : IGxError, IExcelDocument { - static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); public static string nmspace; #if NETCORE public static string license = "FREE-LIMITED-KEY"; diff --git a/dotnet/src/dotnetframework/GxMail/Exchange/ExchangeSession.cs b/dotnet/src/dotnetframework/GxMail/Exchange/ExchangeSession.cs index e74e2b95d..079858e07 100644 --- a/dotnet/src/dotnetframework/GxMail/Exchange/ExchangeSession.cs +++ b/dotnet/src/dotnetframework/GxMail/Exchange/ExchangeSession.cs @@ -10,7 +10,8 @@ namespace GeneXus.Mail.Exchange { public class ExchangeSession : IMailService { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(ExchangeSession)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + private string _attachDir = string.Empty; private string _userName = string.Empty; private string _password = string.Empty; @@ -139,7 +140,7 @@ public void Login(GXMailServiceSession sessionInfo) } catch (Exception e) { - log.Error("Exchange Login Error", e); + GXLogging.Error(log, "Exchange Login Error", e); HandleError(e, 3); } } diff --git a/dotnet/src/dotnetframework/GxMail/Exchange/Service.cs b/dotnet/src/dotnetframework/GxMail/Exchange/Service.cs index e1f617b16..a50ff52f4 100644 --- a/dotnet/src/dotnetframework/GxMail/Exchange/Service.cs +++ b/dotnet/src/dotnetframework/GxMail/Exchange/Service.cs @@ -8,9 +8,9 @@ namespace GeneXus.Mail.Exchange { public static class Service { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(Service)); - - static Service() + + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static Service() { CertificateCallback.Initialize(); } diff --git a/dotnet/src/dotnetframework/GxMail/Exchange/TraceListener.cs b/dotnet/src/dotnetframework/GxMail/Exchange/TraceListener.cs index 2b2106118..a8ed7829e 100644 --- a/dotnet/src/dotnetframework/GxMail/Exchange/TraceListener.cs +++ b/dotnet/src/dotnetframework/GxMail/Exchange/TraceListener.cs @@ -1,4 +1,4 @@ -using log4net; +using log4net; using Microsoft.Exchange.WebServices.Data; using System; using System.Collections.Generic; @@ -9,14 +9,10 @@ namespace GeneXus.Mail.Exchange { public class TraceListener : ITraceListener { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(TraceListener)); - - public void Trace(string traceType, string traceMessage) + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + public void Trace(string traceType, string traceMessage) { - if (log.IsDebugEnabled) - { - log.Debug(String.Format("Trace Type: {0} - Message: {1}", traceType, traceMessage)); - } + GXLogging.Debug(log, string.Format("Trace Type: {0} - Message: {1}", traceType, traceMessage)); } } } diff --git a/dotnet/src/dotnetframework/GxMail/GXMailSession.cs b/dotnet/src/dotnetframework/GxMail/GXMailSession.cs index 1f775cf3f..8d8d2bd73 100644 --- a/dotnet/src/dotnetframework/GxMail/GXMailSession.cs +++ b/dotnet/src/dotnetframework/GxMail/GXMailSession.cs @@ -6,7 +6,7 @@ namespace GeneXus.Mail public abstract class GXMailSession { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GXMailSession)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); protected short errorCode; protected string errorDescription; diff --git a/dotnet/src/dotnetframework/GxMail/GXPOP3Session.cs b/dotnet/src/dotnetframework/GxMail/GXPOP3Session.cs index 65ae678ed..2db01333e 100644 --- a/dotnet/src/dotnetframework/GxMail/GXPOP3Session.cs +++ b/dotnet/src/dotnetframework/GxMail/GXPOP3Session.cs @@ -8,7 +8,8 @@ namespace GeneXus.Mail public class GXPOP3Session : GXMailSession { - private static readonly ILog log = LogManager.GetLogger(typeof(GXSMTPSession)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + private IPOP3Session session; private short secure; private short newMessages; diff --git a/dotnet/src/dotnetframework/GxMail/GXSMTPSession.cs b/dotnet/src/dotnetframework/GxMail/GXSMTPSession.cs index efaff579a..4938afd0e 100644 --- a/dotnet/src/dotnetframework/GxMail/GXSMTPSession.cs +++ b/dotnet/src/dotnetframework/GxMail/GXSMTPSession.cs @@ -9,9 +9,8 @@ namespace GeneXus.Mail public class GXSMTPSession : GXMailSession { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GXSMTPSession)); - - private ISMTPSession session; + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + private ISMTPSession session; private string attachDir; private short authentication; private short secure; diff --git a/dotnet/src/dotnetframework/GxMail/GxMail.csproj b/dotnet/src/dotnetframework/GxMail/GxMail.csproj index 3094e94a5..fc8df79cd 100644 --- a/dotnet/src/dotnetframework/GxMail/GxMail.csproj +++ b/dotnet/src/dotnetframework/GxMail/GxMail.csproj @@ -9,7 +9,6 @@ - diff --git a/dotnet/src/dotnetframework/GxMail/MAPISession.cs b/dotnet/src/dotnetframework/GxMail/MAPISession.cs index 7e61fc0a0..62f201422 100644 --- a/dotnet/src/dotnetframework/GxMail/MAPISession.cs +++ b/dotnet/src/dotnetframework/GxMail/MAPISession.cs @@ -8,8 +8,7 @@ namespace GeneXus.Mail.Internals internal class MAPISession { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(MAPISession)); - + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private enum RecipientType { TO = 1, diff --git a/dotnet/src/dotnetframework/GxMail/MailMessage.cs b/dotnet/src/dotnetframework/GxMail/MailMessage.cs index 8ed31895f..e7afe0a91 100644 --- a/dotnet/src/dotnetframework/GxMail/MailMessage.cs +++ b/dotnet/src/dotnetframework/GxMail/MailMessage.cs @@ -14,7 +14,7 @@ namespace GeneXus.Mail.Internals.Pop3 internal class MailMessage { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(MailMessage)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private const string CRLF = "\r\n"; private static Hashtable monthList = new Hashtable(); diff --git a/dotnet/src/dotnetframework/GxMail/Mentalis/RFC822EndReader.cs b/dotnet/src/dotnetframework/GxMail/Mentalis/RFC822EndReader.cs index ebed69898..052f93e51 100644 --- a/dotnet/src/dotnetframework/GxMail/Mentalis/RFC822EndReader.cs +++ b/dotnet/src/dotnetframework/GxMail/Mentalis/RFC822EndReader.cs @@ -10,7 +10,7 @@ namespace GeneXus.Mail.Internals.Pop3 /// internal class RFC822EndReader : StreamReader { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(RFC822EndReader)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private const int BUFFER_SIZE = 1024; private bool textPlain = false; diff --git a/dotnet/src/dotnetframework/GxMail/OutlookSession.cs b/dotnet/src/dotnetframework/GxMail/OutlookSession.cs index 52ee82071..fc6d1aaf8 100644 --- a/dotnet/src/dotnetframework/GxMail/OutlookSession.cs +++ b/dotnet/src/dotnetframework/GxMail/OutlookSession.cs @@ -10,7 +10,7 @@ namespace GeneXus.Mail.Internals internal class OutlookSession { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(OutlookSession)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private enum RecipientType { diff --git a/dotnet/src/dotnetframework/GxMail/POP3Session.cs b/dotnet/src/dotnetframework/GxMail/POP3Session.cs index 75be7b0a3..f8e878428 100644 --- a/dotnet/src/dotnetframework/GxMail/POP3Session.cs +++ b/dotnet/src/dotnetframework/GxMail/POP3Session.cs @@ -15,8 +15,7 @@ namespace GeneXus.Mail.Internals internal class POP3Session : Pop3SessionBase { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(POP3Session)); - + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private const string CRLF = "\r\n"; private string userName; diff --git a/dotnet/src/dotnetframework/GxMail/POP3SessionOpenPop.cs b/dotnet/src/dotnetframework/GxMail/POP3SessionOpenPop.cs index 45cb1e583..3545ddfb7 100644 --- a/dotnet/src/dotnetframework/GxMail/POP3SessionOpenPop.cs +++ b/dotnet/src/dotnetframework/GxMail/POP3SessionOpenPop.cs @@ -13,9 +13,9 @@ namespace GeneXus.Mail { internal class POP3SessionOpenPop : Pop3SessionBase { - private static readonly ILog log = LogManager.GetLogger(typeof(POP3SessionOpenPop)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); - private Pop3Client client; + private Pop3Client client; public override int GetMessageCount() { diff --git a/dotnet/src/dotnetframework/GxMail/Pop3MailKit.cs b/dotnet/src/dotnetframework/GxMail/Pop3MailKit.cs index 0cb0ea71a..a7e9fd364 100644 --- a/dotnet/src/dotnetframework/GxMail/Pop3MailKit.cs +++ b/dotnet/src/dotnetframework/GxMail/Pop3MailKit.cs @@ -13,8 +13,7 @@ namespace GeneXus.Mail { internal class Pop3MailKit : Pop3SessionBase { - - private static readonly ILog log = LogManager.GetLogger(typeof(Pop3MailKit)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private Pop3Client client; diff --git a/dotnet/src/dotnetframework/GxMail/Pop3SessionBase.cs b/dotnet/src/dotnetframework/GxMail/Pop3SessionBase.cs index f59a38dc0..619d7d45e 100644 --- a/dotnet/src/dotnetframework/GxMail/Pop3SessionBase.cs +++ b/dotnet/src/dotnetframework/GxMail/Pop3SessionBase.cs @@ -13,7 +13,7 @@ internal abstract class Pop3SessionBase : IPOP3Session protected int lastReadMessage; protected int count; protected List uIds; - private static readonly ILog log = LogManager.GetLogger(typeof(Pop3SessionBase)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public bool DownloadAttachments { get; set; } @@ -63,11 +63,11 @@ public virtual string GetNextUID(GXPOP3Session session) public abstract void Receive(GXPOP3Session sessionInfo, GXMailMessage gxmessage); - protected void LogError(string title, string message, int code, Exception e, ILog log) + protected void LogError(string title, string message, int code, Exception e, IGXLogger log) { #if DEBUG - if (e != null && log.IsErrorEnabled) log.Error(message, e); + if (e != null && log.IsErrorEnabled) GXLogging.Error(log, message, e); #endif if (_sessionInfo != null) { @@ -75,20 +75,20 @@ protected void LogError(string title, string message, int code, Exception e, ILo } } - protected void LogError(string title, string message, int code, ILog log) + protected void LogError(string title, string message, int code, IGXLogger log) { LogError(title, message, code, null,log); } - protected void LogDebug(string title, string message, int code, ILog log) + protected void LogDebug(string title, string message, int code, IGXLogger log) { LogDebug(title, message, code, null, log); } - protected void LogDebug(string title, string message, int code, Exception e, ILog log) + protected void LogDebug(string title, string message, int code, Exception e, IGXLogger log) { #if DEBUG - if (e != null && log.IsDebugEnabled) log.Debug(message, e); + if (e != null && log.IsDebugEnabled) GXLogging.Debug(log, message, e); #endif if (_sessionInfo != null) { diff --git a/dotnet/src/dotnetframework/GxMail/SMTP/SmtpHelper.cs b/dotnet/src/dotnetframework/GxMail/SMTP/SmtpHelper.cs index 5d32bd771..23642d907 100644 --- a/dotnet/src/dotnetframework/GxMail/SMTP/SmtpHelper.cs +++ b/dotnet/src/dotnetframework/GxMail/SMTP/SmtpHelper.cs @@ -11,7 +11,7 @@ namespace GeneXus.Mail.Smtp public class SmtpHelper { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(SMTPMailClient)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); #if NETCORE const string SMTP_TRANSPORT = "_transport"; const string SMTP_CONNECTION = "_connection"; diff --git a/dotnet/src/dotnetframework/GxMail/SMTPMailClient.cs b/dotnet/src/dotnetframework/GxMail/SMTPMailClient.cs index f598c05a6..6a2acfa79 100644 --- a/dotnet/src/dotnetframework/GxMail/SMTPMailClient.cs +++ b/dotnet/src/dotnetframework/GxMail/SMTPMailClient.cs @@ -9,7 +9,7 @@ namespace GeneXus.Mail { internal class SMTPMailClient : ISMTPSession { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(SMTPMailClient)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); SmtpClient client; private string attachDir; diff --git a/dotnet/src/dotnetframework/GxMail/SMTPMailKit.cs b/dotnet/src/dotnetframework/GxMail/SMTPMailKit.cs index 24f11fdbc..d1b710e15 100644 --- a/dotnet/src/dotnetframework/GxMail/SMTPMailKit.cs +++ b/dotnet/src/dotnetframework/GxMail/SMTPMailKit.cs @@ -12,7 +12,7 @@ namespace GeneXus.Mail internal class SMTPMailKit : ISMTPSession { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(SMTPMailKit)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); SmtpClient client; private string attachDir; diff --git a/dotnet/src/dotnetframework/GxMail/SMTPSession.cs b/dotnet/src/dotnetframework/GxMail/SMTPSession.cs index f8f26847c..02de5d996 100644 --- a/dotnet/src/dotnetframework/GxMail/SMTPSession.cs +++ b/dotnet/src/dotnetframework/GxMail/SMTPSession.cs @@ -16,7 +16,7 @@ namespace GeneXus.Mail.Internals internal class SMTPSession: ISMTPSession { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(SMTPSession)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); #region Mail Constants private const int CR = 13; private const int LF = 10; diff --git a/dotnet/src/dotnetframework/GxOffice/ExcelSpreadsheetGXWrapper.cs b/dotnet/src/dotnetframework/GxOffice/ExcelSpreadsheetGXWrapper.cs index a1ac17645..cc839e38c 100644 --- a/dotnet/src/dotnetframework/GxOffice/ExcelSpreadsheetGXWrapper.cs +++ b/dotnet/src/dotnetframework/GxOffice/ExcelSpreadsheetGXWrapper.cs @@ -7,7 +7,7 @@ namespace GeneXus.MSOffice.Excel { public class ExcelSpreadsheetGXWrapper : IGXError { - private static readonly ILog logger = LogManager.GetLogger(typeof(ExcelSpreadsheetGXWrapper)); + private static readonly IGXLogger logger = GXLoggerFactory.GetLogger(); private int _errCode; private string _errDescription = string.Empty; private IExcelWorksheet _currentWorksheet; @@ -58,7 +58,7 @@ public bool Open(string filePath, string template) { try { - logger.Debug("Opening Excel file: " + filePath); + GXLogging.Debug(logger, "Opening Excel file: " + filePath); _document = ExcelFactory.Create(this, filePath, template); if (_autofit) { @@ -75,7 +75,7 @@ public bool Open(string filePath, string template) } catch (Exception e)//InvalidOpertaionException { - logger.Error("Excel File could not be loaded", e); + GXLogging.Error(logger, "Excel File could not be loaded", e); SetError(ErrorCodes.FILE_EXCEPTION, "Could not open file"); } return _document != null; @@ -150,13 +150,13 @@ public ExcelCells GetCell(int rowIdx, int colIdx) public void SetError(ExcelException e) { SetError(e.ErrorCode, e.ErrorDescription); - logger.Error(e.ErrorDescription, e); + GXLogging.Error(logger, e.ErrorDescription, e); } public void SetError(string errorMsg, ExcelException e) { SetError(e.ErrorCode, e.ErrorDescription); - logger.Error(errorMsg); + GXLogging.Error(logger, errorMsg); } public ExcelCells GetCells(int rowIdx, int colIdx, int rowCount, int colCount) diff --git a/dotnet/src/dotnetframework/GxOffice/GxOffice.csproj b/dotnet/src/dotnetframework/GxOffice/GxOffice.csproj index ba4b31da3..c80721437 100644 --- a/dotnet/src/dotnetframework/GxOffice/GxOffice.csproj +++ b/dotnet/src/dotnetframework/GxOffice/GxOffice.csproj @@ -8,7 +8,6 @@ - diff --git a/dotnet/src/dotnetframework/GxOffice/poi/xssf/ExcelCells.cs b/dotnet/src/dotnetframework/GxOffice/poi/xssf/ExcelCells.cs index b7b95ef1a..135a5d14d 100644 --- a/dotnet/src/dotnetframework/GxOffice/poi/xssf/ExcelCells.cs +++ b/dotnet/src/dotnetframework/GxOffice/poi/xssf/ExcelCells.cs @@ -14,7 +14,8 @@ namespace GeneXus.MSOffice.Excel.Poi.Xssf { public class ExcelCells : IExcelCellRange { - private static readonly ILog logger = LogManager.GetLogger(typeof(ExcelCells)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + protected IGXError _errorHandler; protected ExcelSpreadsheet doc; protected int cellCount; @@ -428,7 +429,7 @@ public void SetSize(double value) } catch (Exception ex) { - GXLogging.Error(logger, "SetSize error", ex); + GXLogging.Error(log, "SetSize error", ex); } } diff --git a/dotnet/src/dotnetframework/GxOffice/poi/xssf/ExcelSpreadsheet.cs b/dotnet/src/dotnetframework/GxOffice/poi/xssf/ExcelSpreadsheet.cs index c74e4046e..8200cede2 100644 --- a/dotnet/src/dotnetframework/GxOffice/poi/xssf/ExcelSpreadsheet.cs +++ b/dotnet/src/dotnetframework/GxOffice/poi/xssf/ExcelSpreadsheet.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.IO; using GeneXus.Application; -using log4net; using NPOI.SS.UserModel; using NPOI.Util; using NPOI.XSSF.UserModel; @@ -11,7 +10,9 @@ namespace GeneXus.MSOffice.Excel.Poi.Xssf { public class ExcelSpreadsheet : IExcelSpreadsheet { - private static readonly ILog logger = LogManager.GetLogger(typeof(ExcelSpreadsheet)); + + static readonly IGXLogger logger = GXLoggerFactory.GetLogger(); + private XSSFWorkbook _workbook; private string _documentFileName; private bool _autoFitColumnsOnSave = false; @@ -247,7 +248,7 @@ private void RecalculateFormulas() } catch (Exception e) { - logger.Error("recalculateFormulas", e); + GXLogging.Error(logger, "recalculateFormulas", e); } } diff --git a/dotnet/src/dotnetframework/GxPdfReportsCS/GxPdfReportsCS.csproj b/dotnet/src/dotnetframework/GxPdfReportsCS/GxPdfReportsCS.csproj index 1c2d10b46..12fd568d7 100644 --- a/dotnet/src/dotnetframework/GxPdfReportsCS/GxPdfReportsCS.csproj +++ b/dotnet/src/dotnetframework/GxPdfReportsCS/GxPdfReportsCS.csproj @@ -12,11 +12,6 @@ - - - - - diff --git a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs index a656d7d07..a0cee76a1 100644 --- a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs +++ b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs @@ -35,7 +35,7 @@ public abstract class PDFReportItextBase : IReportHandler { protected int lineHeight, pageLines; - static ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); protected bool fontUnderline; protected bool fontStrikethru; @@ -904,7 +904,7 @@ protected float reconvertScale(float value) public class ParseINI { - static ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); private static int MAX_LINE_LENGTH=255; private static String GENERAL="&General&"; @@ -1431,9 +1431,7 @@ public class Const public class NativeSharpFunctionsMS { - - static ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - + static IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); public int shellExecute(String cmd, String fileName) { Process p = new Process(); @@ -1708,7 +1706,7 @@ public class Type1FontMetrics public class MSPDFFontDescriptor { - static ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + static IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); private static String TRUE_TYPE_REGISTRY_SIGNATURE = "(TrueType)"; private static String REGISTRY_FONTS_ENTRY = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts"; // Fonts NT/2000 diff --git a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext4.cs b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext4.cs index 8db5286b9..8e183e247 100644 --- a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext4.cs +++ b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext4.cs @@ -17,8 +17,7 @@ namespace com.genexus.reports public class PDFReportItextSharp : PDFReportItextBase { - static ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - + static IGXLogger log = GXLoggerFactory.GetLogger(); private BaseFont baseFont; Barcode barcode = null; //Color for, BaseColor for => Itext5 diff --git a/dotnet/src/dotnetframework/GxPdfReportsCS/PdfReportInterface.cs b/dotnet/src/dotnetframework/GxPdfReportsCS/PdfReportInterface.cs index 905dc60fb..5c677d48d 100644 --- a/dotnet/src/dotnetframework/GxPdfReportsCS/PdfReportInterface.cs +++ b/dotnet/src/dotnetframework/GxPdfReportsCS/PdfReportInterface.cs @@ -6,8 +6,7 @@ namespace GeneXus.Printer public class GxReportBuilderPdf : IReportHandler { - static ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - + static IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); string _appPath; protected IReportHandler _pdfReport; diff --git a/dotnet/src/dotnetframework/GxSearch/DocumentHandler.cs b/dotnet/src/dotnetframework/GxSearch/DocumentHandler.cs index 00914d6c9..a80904a8a 100644 --- a/dotnet/src/dotnetframework/GxSearch/DocumentHandler.cs +++ b/dotnet/src/dotnetframework/GxSearch/DocumentHandler.cs @@ -25,7 +25,7 @@ namespace GeneXus.Utils { public class DocumentHandler { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Utils.DocumentHandler)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); static IndexReader reader; static ConcurrentDictionary queries = new ConcurrentDictionary(); @@ -152,10 +152,10 @@ public interface IDocumentHandler public class NTidyHTMLHandler : IDocumentHandler { #if !NETCORE - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Utils.DocumentHandler)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); Assembly ntidy; #endif - public NTidyHTMLHandler() + public NTidyHTMLHandler() { #if !NETCORE try diff --git a/dotnet/src/dotnetframework/GxSearch/GxSearch.csproj b/dotnet/src/dotnetframework/GxSearch/GxSearch.csproj index 0d0f0108b..cd3574c66 100644 --- a/dotnet/src/dotnetframework/GxSearch/GxSearch.csproj +++ b/dotnet/src/dotnetframework/GxSearch/GxSearch.csproj @@ -9,7 +9,6 @@ - diff --git a/dotnet/src/dotnetframework/GxSearch/Indexer.cs b/dotnet/src/dotnetframework/GxSearch/Indexer.cs index 8ca23e70f..41bb64752 100644 --- a/dotnet/src/dotnetframework/GxSearch/Indexer.cs +++ b/dotnet/src/dotnetframework/GxSearch/Indexer.cs @@ -24,7 +24,7 @@ namespace GeneXus.Search [SecuritySafeCritical] public sealed class Indexer { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Search.Indexer)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public static Lucene.Net.Util.Version LUCENE_VERSION = Lucene.Net.Util.Version.LUCENE_24; #region Singleton diff --git a/dotnet/src/dotnetframework/GxSearch/Searcher.cs b/dotnet/src/dotnetframework/GxSearch/Searcher.cs index 40d9a1cda..2013f428e 100644 --- a/dotnet/src/dotnetframework/GxSearch/Searcher.cs +++ b/dotnet/src/dotnetframework/GxSearch/Searcher.cs @@ -18,7 +18,7 @@ namespace GeneXus.Search [SecuritySafeCritical] public sealed class Searcher { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Search.Searcher)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); #region Singleton private static Searcher m_instance = new Searcher(); diff --git a/dotnet/src/dotnetframework/GxSearch/Settings.cs b/dotnet/src/dotnetframework/GxSearch/Settings.cs index 1bef3ee9e..85f049cbf 100644 --- a/dotnet/src/dotnetframework/GxSearch/Settings.cs +++ b/dotnet/src/dotnetframework/GxSearch/Settings.cs @@ -11,7 +11,7 @@ namespace GeneXus.Search [SecuritySafeCritical] public class Settings { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Search.Settings)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private static Settings m_instance = new Settings(); private Lucene.Net.Store.Directory m_storeFolder; private string m_indexFolder; diff --git a/dotnet/src/dotnetframework/GxSearch/SpellChecker.cs b/dotnet/src/dotnetframework/GxSearch/SpellChecker.cs index a132a03d7..db3cc170f 100644 --- a/dotnet/src/dotnetframework/GxSearch/SpellChecker.cs +++ b/dotnet/src/dotnetframework/GxSearch/SpellChecker.cs @@ -12,7 +12,7 @@ namespace GeneXus.Search { public sealed class Spelling { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Search.Indexer)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); #region Singleton private static Spelling m_instance = new Spelling(); diff --git a/dotnet/src/dotnetframework/GxWebSocket/GXWebSocket.csproj b/dotnet/src/dotnetframework/GxWebSocket/GXWebSocket.csproj index 48b03dc26..c6d442ee1 100644 --- a/dotnet/src/dotnetframework/GxWebSocket/GXWebSocket.csproj +++ b/dotnet/src/dotnetframework/GxWebSocket/GXWebSocket.csproj @@ -9,7 +9,6 @@ - diff --git a/dotnet/src/dotnetframework/GxWebSocket/WSHandler.cs b/dotnet/src/dotnetframework/GxWebSocket/WSHandler.cs index b4f51285f..bb81262c5 100644 --- a/dotnet/src/dotnetframework/GxWebSocket/WSHandler.cs +++ b/dotnet/src/dotnetframework/GxWebSocket/WSHandler.cs @@ -16,7 +16,7 @@ namespace GeneXus.Http.WebSocket { public class WSHandler : WebSocketHandler, IGXWebSocketAsync { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(WSHandler)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private const string GX_NOTIFICATIONINFO_NAME = "GeneXus.Core.genexus.server.SdtNotificationInfo"; @@ -127,7 +127,7 @@ public override void OnError() string key = GetClientKey(this); if (!ExecuteHandler(HandlerType.OnError, new Object[] { key })) { - log.Debug($"An unknown error ocurred on WebSocket client ('{key}')"); + GXLogging.Debug(log, $"An unknown error ocurred on WebSocket client ('{key}')"); } OnSessionClosed?.Invoke(key, "WebSocket Error"); } @@ -146,7 +146,7 @@ private static void LogDebug(string msg) private static void LogError(string msg, Exception e = null) { - GXLogging.Error(log, e, msg); + GXLogging.Error(log, msg, e); } public enum HandlerType { diff --git a/dotnet/src/dotnetframework/Projects/StoreManager/Store/StoreManager.cs b/dotnet/src/dotnetframework/Projects/StoreManager/Store/StoreManager.cs index 3d95f7675..87f7a08d9 100644 --- a/dotnet/src/dotnetframework/Projects/StoreManager/Store/StoreManager.cs +++ b/dotnet/src/dotnetframework/Projects/StoreManager/Store/StoreManager.cs @@ -13,8 +13,7 @@ namespace GeneXus.SD.Store { public class StoreManager { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(StoreManager)); - + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public int ErrCode { get; set; diff --git a/dotnet/src/dotnetframework/Projects/StoreManager/StoreManager.csproj b/dotnet/src/dotnetframework/Projects/StoreManager/StoreManager.csproj index 39fa35871..30b4f1d29 100644 --- a/dotnet/src/dotnetframework/Projects/StoreManager/StoreManager.csproj +++ b/dotnet/src/dotnetframework/Projects/StoreManager/StoreManager.csproj @@ -10,12 +10,11 @@ - - + diff --git a/dotnet/src/dotnetframework/Providers/Cache/GxMemcached/GxMemcached.cs b/dotnet/src/dotnetframework/Providers/Cache/GxMemcached/GxMemcached.cs index 2a5945e01..917758d7e 100644 --- a/dotnet/src/dotnetframework/Providers/Cache/GxMemcached/GxMemcached.cs +++ b/dotnet/src/dotnetframework/Providers/Cache/GxMemcached/GxMemcached.cs @@ -15,7 +15,7 @@ namespace GeneXus.Cache [SecuritySafeCritical] public class Memcached : ICacheService2 { - private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(Memcached)); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); MemcachedClient _cache; const int DEFAULT_MEMCACHED_PORT = 11211; diff --git a/dotnet/src/dotnetframework/Providers/Cache/GxRedis/GxRedis.cs b/dotnet/src/dotnetframework/Providers/Cache/GxRedis/GxRedis.cs index 80d5d9781..f15c789e9 100644 --- a/dotnet/src/dotnetframework/Providers/Cache/GxRedis/GxRedis.cs +++ b/dotnet/src/dotnetframework/Providers/Cache/GxRedis/GxRedis.cs @@ -17,7 +17,8 @@ namespace GeneXus.Cache { public sealed class Redis : ICacheService2 { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(Redis)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + ConnectionMultiplexer _redisConnection; IDatabase _redisDatabase; ConfigurationOptions _redisConnectionOptions; diff --git a/dotnet/src/dotnetframework/Providers/Cache/GxRedis/GxRedis.csproj b/dotnet/src/dotnetframework/Providers/Cache/GxRedis/GxRedis.csproj index ded298efb..f9b7978e5 100644 --- a/dotnet/src/dotnetframework/Providers/Cache/GxRedis/GxRedis.csproj +++ b/dotnet/src/dotnetframework/Providers/Cache/GxRedis/GxRedis.csproj @@ -8,7 +8,6 @@ GeneXus.Redis - diff --git a/dotnet/src/dotnetframework/Providers/Storage/GXAmazonS3/ExternalProviderS3.cs b/dotnet/src/dotnetframework/Providers/Storage/GXAmazonS3/ExternalProviderS3.cs index be6ab97a9..2a1dbe829 100644 --- a/dotnet/src/dotnetframework/Providers/Storage/GXAmazonS3/ExternalProviderS3.cs +++ b/dotnet/src/dotnetframework/Providers/Storage/GXAmazonS3/ExternalProviderS3.cs @@ -17,8 +17,7 @@ namespace GeneXus.Storage.GXAmazonS3 { public class ExternalProviderS3 : ExternalProviderBase, ExternalProvider { - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(ExternalProviderS3)); - + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public const string Name = "AWSS3"; const string ACCESS_KEY = "ACCESS_KEY"; @@ -220,7 +219,7 @@ private void BucketExists() { if (!DoesS3BucketExist()) { - log.Warn(String.Format("Bucket {0} doesn't exist, please create the bucket", Bucket)); + GXLogging.Warn(log, String.Format("Bucket {0} doesn't exist, please create the bucket", Bucket)); } } diff --git a/dotnet/src/dotnetframework/Providers/Storage/GXAmazonS3/GXAmazonS3.csproj b/dotnet/src/dotnetframework/Providers/Storage/GXAmazonS3/GXAmazonS3.csproj index be853d2d5..d6b7d73b7 100644 --- a/dotnet/src/dotnetframework/Providers/Storage/GXAmazonS3/GXAmazonS3.csproj +++ b/dotnet/src/dotnetframework/Providers/Storage/GXAmazonS3/GXAmazonS3.csproj @@ -8,7 +8,6 @@ - diff --git a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj b/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj index a2955f0e4..90fa92d9a 100644 --- a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj +++ b/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj @@ -26,7 +26,7 @@ - + @@ -62,9 +62,9 @@ - + - + diff --git a/dotnet/src/extensions/Azure/Handlers/HttpHandler/GXHttpAzureContextAccessor.cs b/dotnet/src/extensions/Azure/Handlers/HttpHandler/GXHttpAzureContextAccessor.cs index bc58ac9d3..2a9e3c97a 100644 --- a/dotnet/src/extensions/Azure/Handlers/HttpHandler/GXHttpAzureContextAccessor.cs +++ b/dotnet/src/extensions/Azure/Handlers/HttpHandler/GXHttpAzureContextAccessor.cs @@ -26,7 +26,7 @@ public class GXHttpAzureContextAccessor : HttpContext public HttpResponse httpResponseData; private ICacheService2 _redis; private string sessionId; - private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GXHttpAzureContextAccessor)); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); internal const string AzureSessionId = "GX_AZURE_SESSIONID"; public GXHttpAzureContextAccessor(HttpRequestData requestData, HttpResponseData responseData, ICacheService2 redis) { diff --git a/dotnet/src/extensions/Azure/test/AzureFunctionsTest/AzureFunctionsTest.csproj b/dotnet/src/extensions/Azure/test/AzureFunctionsTest/AzureFunctionsTest.csproj index f3d9485b2..86add5f40 100644 --- a/dotnet/src/extensions/Azure/test/AzureFunctionsTest/AzureFunctionsTest.csproj +++ b/dotnet/src/extensions/Azure/test/AzureFunctionsTest/AzureFunctionsTest.csproj @@ -7,6 +7,7 @@ + diff --git a/dotnet/test/DotNetCoreAttackMitigationTest/Middleware/RestServiceTest.cs b/dotnet/test/DotNetCoreAttackMitigationTest/Middleware/RestServiceTest.cs index 3c292308a..d292393c7 100644 --- a/dotnet/test/DotNetCoreAttackMitigationTest/Middleware/RestServiceTest.cs +++ b/dotnet/test/DotNetCoreAttackMitigationTest/Middleware/RestServiceTest.cs @@ -25,7 +25,6 @@ public RestServiceTest() : base() } - [Fact] public async Task TestSimpleRestPost() { server.AllowSynchronousIO = true; @@ -35,7 +34,6 @@ public async Task TestSimpleRestPost() Assert.Equal(System.Net.HttpStatusCode.BadRequest, response.StatusCode); } - [Fact] public async Task RunController() { @@ -66,7 +64,6 @@ public async Task RunController() response = await client.PostAsync("rest/apps/saveimage", body); Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); } - [Fact] public async Task HttpFirstPost() { HttpClient client = server.CreateClient(); @@ -79,7 +76,6 @@ public async Task HttpFirstPost() response.EnsureSuccessStatusCode(); Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); } - [Fact] public async Task HttpFirstGet() { HttpClient client = server.CreateClient(); diff --git a/dotnet/test/DotNetCoreOpenTelemetryTest/TestOpenTelemetry.cs b/dotnet/test/DotNetCoreOpenTelemetryTest/TestOpenTelemetry.cs index 11f71c618..5719632c5 100644 --- a/dotnet/test/DotNetCoreOpenTelemetryTest/TestOpenTelemetry.cs +++ b/dotnet/test/DotNetCoreOpenTelemetryTest/TestOpenTelemetry.cs @@ -1,13 +1,9 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Net.Http; using System.Reflection; -using System.Text; using System.Threading.Tasks; -using GeneXus.Configuration; +using GeneXus.Application; using GeneXus.Metadata; -using Microsoft.Extensions.Logging; using Xunit; using xUnitTesting; @@ -20,6 +16,10 @@ public TestOpenTelemetry() { server.AllowSynchronousIO = true; } + protected override void SetEnvironmentVars() + { + Environment.SetEnvironmentVariable(Startup.APPLICATIONINSIGHTS_CONNECTION_STRING, "InstrumentationKey=dummykey;IngestionEndpoint=https://dummyendpoint;", EnvironmentVariableTarget.Process); + } [Fact] public async Task TestCouldNotLoadSystemDiagnosticsDiagnosticSource7_0_0_0() { diff --git a/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj b/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj index 56882bd28..88b4efc68 100644 --- a/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj +++ b/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj @@ -10,6 +10,9 @@ DEBUG;TRACE;NETCORE + + + @@ -28,6 +31,7 @@ + @@ -46,6 +50,9 @@ PreserveNewest + + PreserveNewest + @@ -104,9 +111,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest @@ -161,6 +165,7 @@ + diff --git a/dotnet/test/DotNetCoreUnitTest/log.config b/dotnet/test/DotNetCoreUnitTest/log.console.config similarity index 97% rename from dotnet/test/DotNetCoreUnitTest/log.config rename to dotnet/test/DotNetCoreUnitTest/log.console.config index 6dc70d5c6..b52a4d897 100644 --- a/dotnet/test/DotNetCoreUnitTest/log.config +++ b/dotnet/test/DotNetCoreUnitTest/log.console.config @@ -18,7 +18,7 @@ - + diff --git a/dotnet/test/DotNetCoreWebUnitTest/Middleware/MiddlewareTest.cs b/dotnet/test/DotNetCoreWebUnitTest/Middleware/MiddlewareTest.cs index 7a22fdddc..15c2c86c5 100644 --- a/dotnet/test/DotNetCoreWebUnitTest/Middleware/MiddlewareTest.cs +++ b/dotnet/test/DotNetCoreWebUnitTest/Middleware/MiddlewareTest.cs @@ -17,10 +17,15 @@ public class MiddlewareTest protected TestServer server; public MiddlewareTest() { - GXRouting.ContentRootPath = Directory.GetCurrentDirectory(); + SetEnvironmentVars(); server = new TestServer(WebHost.CreateDefaultBuilder().UseStartup().UseEnvironment(DOTNET_ENVIRONMENT)); + GXRouting.ContentRootPath = Directory.GetCurrentDirectory(); server.PreserveExecutionContext= true; server.CreateClient(); + } + protected virtual void SetEnvironmentVars() + { + } protected string GetHeader(HttpResponseMessage response, string headerName) { diff --git a/dotnet/test/DotNetUnitTest/DotNetUnitTest.csproj b/dotnet/test/DotNetUnitTest/DotNetUnitTest.csproj index d8d055b01..ed384f5fb 100644 --- a/dotnet/test/DotNetUnitTest/DotNetUnitTest.csproj +++ b/dotnet/test/DotNetUnitTest/DotNetUnitTest.csproj @@ -4,9 +4,11 @@ DotNetUnitTest DotNetUnitTest NODATIME + true + @@ -15,6 +17,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/dotnet/test/DotNetUnitTest/Log/LogTest.cs b/dotnet/test/DotNetUnitTest/Log/LogTest.cs new file mode 100644 index 000000000..980f8cade --- /dev/null +++ b/dotnet/test/DotNetUnitTest/Log/LogTest.cs @@ -0,0 +1,19 @@ +using GeneXus; +using GeneXus.Configuration; +using Xunit; + +namespace DotNetUnitTest.Log +{ + public class LogTest + { + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + [Fact] + public void TestLogOutput() + { + Config.LoadConfiguration(); + GXLogging.Debug(log, "Test Debug"); + GXLogging.Info(log, "Test Info"); + GXLogging.Warn(log, "Test Warn"); + } + } +} diff --git a/dotnet/test/DotNetUnitTest/log.console.config b/dotnet/test/DotNetUnitTest/log.console.config new file mode 100644 index 000000000..45213e60d --- /dev/null +++ b/dotnet/test/DotNetUnitTest/log.console.config @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 26cc6f11f54d8ceb1a1c4106b31eea8f875d2c34 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Fri, 3 Nov 2023 17:21:01 -0300 Subject: [PATCH 057/164] Delay reading the HttpClient response until the ReceiveData property is accessed (#879) * Delay reading the HttpClient response until the ReceiveData property is accessed. It allows chunked reading when the ReadChunk method is called. * Rename _chunkedResponse to _response (the previous local variable 'response' is now an instance variable named '_response'). Rename ReadReponseData to ReadResponseData. * Reset the _receiveData variable on HttpClientExecute; otherwise, a second execution on the same HttpClient instance may read the previous content. * Disable compression in ASP.NET when streaming, as buffering is not supported alongside compression. --- dotnet/DotNetStandardClasses.sln | 6 + .../GxClasses.Web/Properties/AssemblyInfo.cs | 1 + .../GxClasses/Properties/AssemblyInfo.cs | 1 + .../GxClasses/Core/Web/GxHttpServer.cs | 11 +- .../GxClasses/Domain/GxHttpClient.cs | 199 +++++++++++------- .../GxClasses/Middleware/GXHttp.cs | 4 + .../ChunkedServiceTest.cs | 97 +++++++++ .../DotNetCoreChunkedTest.csproj | 65 ++++++ 8 files changed, 311 insertions(+), 73 deletions(-) create mode 100644 dotnet/test/DotNetCoreChunkedTest/ChunkedServiceTest.cs create mode 100644 dotnet/test/DotNetCoreChunkedTest/DotNetCoreChunkedTest.csproj diff --git a/dotnet/DotNetStandardClasses.sln b/dotnet/DotNetStandardClasses.sln index cab5bac35..bbd55c51d 100644 --- a/dotnet/DotNetStandardClasses.sln +++ b/dotnet/DotNetStandardClasses.sln @@ -249,6 +249,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GXAzureEventGrid", "src\dot EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetCoreAttackMitigationTest", "test\DotNetCoreAttackMitigationTest\DotNetCoreAttackMitigationTest.csproj", "{2D615969-53E2-4B77-9A9A-75C33865CF76}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetCoreChunkedTest", "test\DotNetCoreChunkedTest\DotNetCoreChunkedTest.csproj", "{5D2B1299-479F-430A-8D72-34D44FB299FD}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetPDFUnitTest", "test\DotNetPdfTest\DotNetPDFUnitTest.csproj", "{0FCFB078-5584-469F-92CC-61B0A6216D0D}" EndProject Global @@ -605,6 +606,10 @@ Global {2D615969-53E2-4B77-9A9A-75C33865CF76}.Debug|Any CPU.Build.0 = Debug|Any CPU {2D615969-53E2-4B77-9A9A-75C33865CF76}.Release|Any CPU.ActiveCfg = Release|Any CPU {2D615969-53E2-4B77-9A9A-75C33865CF76}.Release|Any CPU.Build.0 = Release|Any CPU + {5D2B1299-479F-430A-8D72-34D44FB299FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5D2B1299-479F-430A-8D72-34D44FB299FD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5D2B1299-479F-430A-8D72-34D44FB299FD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5D2B1299-479F-430A-8D72-34D44FB299FD}.Release|Any CPU.Build.0 = Release|Any CPU {0FCFB078-5584-469F-92CC-61B0A6216D0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0FCFB078-5584-469F-92CC-61B0A6216D0D}.Debug|Any CPU.Build.0 = Debug|Any CPU {0FCFB078-5584-469F-92CC-61B0A6216D0D}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -728,6 +733,7 @@ Global {5BBC75F0-E51A-4EBD-A628-92498D319B1D} = {4C43F2DA-59E5-46F5-B691-195449498555} {7250CDB1-95C4-4822-B01B-3CBD73324CC9} = {30159B0F-BE61-4DB7-AC02-02851426BE4B} {2D615969-53E2-4B77-9A9A-75C33865CF76} = {1D6F1776-FF4B-46C2-9B3D-BC46CCF049DC} + {5D2B1299-479F-430A-8D72-34D44FB299FD} = {1D6F1776-FF4B-46C2-9B3D-BC46CCF049DC} {0FCFB078-5584-469F-92CC-61B0A6216D0D} = {1D6F1776-FF4B-46C2-9B3D-BC46CCF049DC} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution diff --git a/dotnet/src/dotnetcore/GxClasses.Web/Properties/AssemblyInfo.cs b/dotnet/src/dotnetcore/GxClasses.Web/Properties/AssemblyInfo.cs index efaae7382..c6a284870 100644 --- a/dotnet/src/dotnetcore/GxClasses.Web/Properties/AssemblyInfo.cs +++ b/dotnet/src/dotnetcore/GxClasses.Web/Properties/AssemblyInfo.cs @@ -7,3 +7,4 @@ [assembly: InternalsVisibleTo("GeneXus.Deploy.AzureFunctions.Handlers")] [assembly: InternalsVisibleTo("AzureFunctionsTest")] [assembly: InternalsVisibleTo("DotNetCoreAttackMitigationTest")] +[assembly: InternalsVisibleTo("DotNetCoreChunkedTest")] diff --git a/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs b/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs index cb985cdac..ee4196dbb 100644 --- a/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs +++ b/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs @@ -14,3 +14,4 @@ [assembly: InternalsVisibleTo("GeneXus.Deploy.AzureFunctions.Handlers")] [assembly: InternalsVisibleTo("AzureFunctionsTest")] [assembly: InternalsVisibleTo("GXMessageBroker")] +[assembly: InternalsVisibleTo("DotNetCoreChunkedTest")] \ No newline at end of file diff --git a/dotnet/src/dotnetframework/GxClasses/Core/Web/GxHttpServer.cs b/dotnet/src/dotnetframework/GxClasses/Core/Web/GxHttpServer.cs index dbb4e1092..f834c38b4 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/Web/GxHttpServer.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/Web/GxHttpServer.cs @@ -148,7 +148,16 @@ public void AppendHeader( string name, string value) { value = GXUtil.EncodeContentDispositionHeader(value, _context.GetBrowserType()); } - if (_context!=null) +#if !NETCORE + else if (string.Compare(name,"Content-Type", true) == 0) + { + if (string.Compare(value, "text/event-stream", true) == 0) + { + _context.HttpContext.Response.BufferOutput = false; + } + } +#endif + if (_context!=null) _context.SetHeader(name, value); } diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs index 8496f3843..0115c7b6d 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs @@ -77,6 +77,11 @@ public class GxHttpClient : IGxHttpClient, IDisposable NameValueCollection _headers; NameValueCollection _formVars; MultiPartTemplate _multipartTemplate; + bool _isChunkedResponse; + HttpResponseMessage _response; + bool _eof; + bool _encodingFound; + string _charset; string _scheme = "http://"; @@ -135,6 +140,7 @@ internal byte[] ReceiveData { get { + ReadResponseData(); return _receiveData; } } @@ -703,58 +709,40 @@ HttpResponseMessage ExecuteRequest(string method, string requestUrl, CookieConta reqStream.Seek(0, SeekOrigin.Begin); request.Content = new ByteArrayContent(reqStream.ToArray()); setHeaders(request, handler.CookieContainer); - response = client.SendAsync(request).GetAwaiter().GetResult(); + response = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).GetAwaiter().GetResult(); } } return response; - } - void ReadReponseContent(HttpResponseMessage response) + } + void ReadResponseData() { - _receiveData = Array.Empty(); - try + if (_receiveData == null && _response!=null) { - Stream stream = response.Content.ReadAsStreamAsync().GetAwaiter().GetResult(); - string charset; - if (response.Content.Headers.ContentType == null) - charset = null; - else - charset = response.Content.Headers.ContentType.CharSet; - bool encodingFound = false; - if (!string.IsNullOrEmpty(charset)) + _receiveData = Array.Empty(); + try { - int idx = charset.IndexOf("charset="); - if (idx > 0) + Stream stream = _response.Content.ReadAsStreamAsync().GetAwaiter().GetResult(); + + using (MemoryStream ms = new MemoryStream()) { - idx += 8; - charset = charset.Substring(idx, charset.Length - idx); - _encoding = GetEncoding(charset); - if (_encoding != null) - encodingFound = true; + stream.CopyTo(ms); + _receiveData = ms.ToArray(); } - else + _eof = true; + int bytesRead = _receiveData.Length; + GXLogging.Debug(log, "BytesRead " + _receiveData.Length); + if (bytesRead > 0 && !_encodingFound) { - charset = String.Empty; + _encoding = DetectEncoding(_charset, out _encodingFound, _receiveData, bytesRead); } } - - using (MemoryStream ms = new MemoryStream()) + catch (IOException ioEx) { - stream.CopyTo(ms); - _receiveData = ms.ToArray(); + if (_errCode == 1) + GXLogging.Warn(log, "Could not read response", ioEx); + else + throw ioEx; } - int bytesRead = _receiveData.Length; - GXLogging.Debug(log, "BytesRead " + _receiveData.Length); - if (bytesRead > 0 && !encodingFound) - { - _encoding = DetectEncoding(charset, out encodingFound, _receiveData, bytesRead); - } - } - catch (IOException ioEx) - { - if (_errCode == 1) - GXLogging.Warn(log, "Could not read response", ioEx); - else - throw ioEx; } } bool UseOldHttpClient(string name) @@ -790,10 +778,22 @@ public void Execute(string method, string name) HttpClientExecute(method, name); } } - + internal void ProcessResponse(HttpResponseMessage httpResponse) + { + _response = httpResponse; + LoadResponseHeaders(_response); + _statusCode = ((short)_response.StatusCode); + _statusDescription = GetStatusCodeDescrption(_response); + if ((_statusCode >= 400 && _statusCode < 600) && _errCode != 1) + { + _errCode = 1; + _errDescription = "The remote server returned an error: (" + _statusCode + ") " + _statusDescription + "."; + } + } public void HttpClientExecute(string method, string name) { - HttpResponseMessage response = null; + _receiveData = null; + _response = null; Byte[] Buffer = new Byte[1024]; _errCode = 0; _errDescription = string.Empty; @@ -803,7 +803,7 @@ public void HttpClientExecute(string method, string name) string requestUrl = GetRequestURL(name); bool contextCookies = _context != null && !String.IsNullOrEmpty(requestUrl); CookieContainer cookies = contextCookies ? _context.GetCookieContainer(requestUrl, IncludeCookies) : new CookieContainer(); - response = ExecuteRequest(method, requestUrl, cookies); + _response = ExecuteRequest(method, requestUrl, cookies); if (contextCookies) _context.UpdateSessionCookieContainer(); @@ -819,9 +819,9 @@ public void HttpClientExecute(string method, string name) _errDescription = aex.InnerException.Message; else _errDescription = aex.Message; - response = new HttpResponseMessage(); - response.Content = new StringContent(HttpHelper.StatusCodeToTitle(HttpStatusCode.InternalServerError)); - response.StatusCode = HttpStatusCode.InternalServerError; + _response = new HttpResponseMessage(); + _response.Content = new StringContent(HttpHelper.StatusCodeToTitle(HttpStatusCode.InternalServerError)); + _response.StatusCode = HttpStatusCode.InternalServerError; } #endif catch (HttpRequestException e) @@ -832,12 +832,12 @@ public void HttpClientExecute(string method, string name) _errDescription = e.Message + " " + e.InnerException.Message; else _errDescription = e.Message; - response = new HttpResponseMessage(); - response.Content = new StringContent(HttpHelper.StatusCodeToTitle(HttpStatusCode.InternalServerError)); + _response = new HttpResponseMessage(); + _response.Content = new StringContent(HttpHelper.StatusCodeToTitle(HttpStatusCode.InternalServerError)); #if NETCORE - response.StatusCode = (HttpStatusCode)(e.StatusCode != null ? e.StatusCode : HttpStatusCode.InternalServerError); + _response.StatusCode = (HttpStatusCode)(e.StatusCode != null ? e.StatusCode : HttpStatusCode.InternalServerError); #else - response.StatusCode = HttpStatusCode.InternalServerError; + _response.StatusCode = HttpStatusCode.InternalServerError; #endif } catch (TaskCanceledException e) @@ -845,9 +845,9 @@ public void HttpClientExecute(string method, string name) GXLogging.Warn(log, "Error Execute", e); _errCode = 1; _errDescription = "The request has timed out. " + e.Message; - response = new HttpResponseMessage(); - response.StatusCode = 0; - response.Content = new StringContent(String.Empty); + _response = new HttpResponseMessage(); + _response.StatusCode = 0; + _response.Content = new StringContent(String.Empty); } catch (Exception e) { @@ -857,29 +857,20 @@ public void HttpClientExecute(string method, string name) _errDescription = e.Message + " " + e.InnerException.Message; else _errDescription = e.Message; - response = new HttpResponseMessage(); - response.Content = new StringContent(HttpHelper.StatusCodeToTitle(HttpStatusCode.InternalServerError)); - response.StatusCode = HttpStatusCode.InternalServerError; + _response = new HttpResponseMessage(); + _response.Content = new StringContent(HttpHelper.StatusCodeToTitle(HttpStatusCode.InternalServerError)); + _response.StatusCode = HttpStatusCode.InternalServerError; } GXLogging.Debug(log, "Reading response..."); - if (response == null) + if (_response == null) return; - LoadResponseHeaders(response); - ReadReponseContent(response); - _statusCode = ((short)response.StatusCode); - _statusDescription = GetStatusCodeDescrption(response); - if ((_statusCode >= 400 && _statusCode < 600) && _errCode != 1) - { - _errCode = 1; - _errDescription = "The remote server returned an error: (" + _statusCode + ") " + _statusDescription + "."; - } + ProcessResponse(_response); ClearSendStream(); - GXLogging.DebugSanitized(log, "_responseString " + ToString()); } NameValueCollection _respHeaders; private bool disposedValue; - void LoadResponseHeaders(HttpResponseMessage resp) + internal void LoadResponseHeaders(HttpResponseMessage resp) { _respHeaders = new NameValueCollection(); foreach (KeyValuePair> header in resp.Headers) @@ -890,6 +881,29 @@ void LoadResponseHeaders(HttpResponseMessage resp) { _respHeaders.Add(header.Key, String.Join(",", header.Value)); } + _isChunkedResponse = resp.Headers.TransferEncodingChunked.HasValue && resp.Headers.TransferEncodingChunked.Value; + + if (_response.Content.Headers.ContentType == null) + _charset = null; + else + _charset = _response.Content.Headers.ContentType.CharSet; + _encodingFound = false; + if (!string.IsNullOrEmpty(_charset)) + { + int idx = _charset.IndexOf("charset="); + if (idx > 0) + { + idx += 8; + _charset = _charset.Substring(idx, _charset.Length - idx); + _encoding = GetEncoding(_charset); + if (_encoding != null) + _encodingFound = true; + } + else + { + _charset = String.Empty; + } + } } private string GetStatusCodeDescrption(HttpResponseMessage message) @@ -1366,14 +1380,54 @@ private Encoding ExtractEncodingFromCharset(string responseText, string regExpP, } return enc; } + public bool Eof + { + get + { + return _eof; + + } + } + StreamReader _receivedChunkedStream; + public string ReadChunk() + { + if (!_isChunkedResponse) + return ToString(); + + if (_response == null) + return string.Empty; + try + { + if (_receivedChunkedStream == null) + { + _receivedChunkedStream = new StreamReader(_response.Content.ReadAsStreamAsync().GetAwaiter().GetResult()); + } + _eof = _receivedChunkedStream.EndOfStream; + if (!_eof) + { + string line = _receivedChunkedStream.ReadLine(); + if (line != null) + { + return line; + } + } + } + catch (Exception ex) + { + GXLogging.Error(log, String.Format("Error reading chunk", ex)); + } + return string.Empty; + } public override string ToString() { + if (ReceiveData == null) + return string.Empty; if (_encoding == null) _encoding = Encoding.UTF8; - if (_receiveData == null) - return string.Empty; - return _encoding.GetString(_receiveData); + string responseString = _encoding.GetString(ReceiveData); + GXLogging.DebugSanitized(log, "_responseString " + responseString); + return responseString; } public void ToFile(string fileName) { @@ -1385,9 +1439,9 @@ public void ToFile(string fileName) if (fileName.IndexOfAny(new char[] { '\\', ':' }) == -1) pathName = Path.Combine(GxContext.StaticPhysicalPath(), fileName); - if (_receiveData != null) + if (ReceiveData != null) { - File.WriteAllBytes(pathName, _receiveData); + File.WriteAllBytes(pathName, ReceiveData); } } @@ -1463,6 +1517,7 @@ protected virtual void Dispose(bool disposing) { _receiveData = null; _sendStream?.Dispose(); + _receivedChunkedStream?.Dispose(); } disposedValue = true; } diff --git a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs index e1c5cdab4..f5fe21520 100644 --- a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs +++ b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs @@ -2275,7 +2275,11 @@ public bool IsReusable protected virtual void SetCompression(HttpContext httpContext) { +#if NETCORE if (CompressHtmlResponse()) +#else + if (CompressHtmlResponse() && httpContext.Response.BufferOutput) +#endif { GXUtil.SetGZip(httpContext); } diff --git a/dotnet/test/DotNetCoreChunkedTest/ChunkedServiceTest.cs b/dotnet/test/DotNetCoreChunkedTest/ChunkedServiceTest.cs new file mode 100644 index 000000000..6d71bcd86 --- /dev/null +++ b/dotnet/test/DotNetCoreChunkedTest/ChunkedServiceTest.cs @@ -0,0 +1,97 @@ +using System; +using System.IO; +using System.Net; +using System.Net.Http; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using GeneXus.Application; +using GeneXus.Http; +using GeneXus.Http.Client; +using GeneXus.Metadata; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using StackExchange.Redis; +using Xunit; +namespace xUnitTesting +{ + public class ChunkedServiceTest : MiddlewareTest + { + const string BufferedContent = $"Line 1\nLine 2\nLine 3\n"; + const string Chunk1 = @"Line 1"; + const string Chunk2 = @"Line 2"; + const string Chunk3 = @"Line 3"; + string fileName = Path.Combine(Directory.GetCurrentDirectory(), "tmp.txt"); + [Fact] + public async Task TestChunkedResponse() + { + var server = new TestServer(new WebHostBuilder().UseStartup()); + var client = server.CreateClient(); + var response = await client.GetAsync("/", HttpCompletionOption.ResponseHeadersRead); + Assert.True(response.Headers.TransferEncodingChunked); + response.EnsureSuccessStatusCode(); + GxHttpClient gxHttp = new GxHttpClient(); + gxHttp.ProcessResponse(response); + Assert.False(gxHttp.Eof); + Assert.Equal(Chunk1, gxHttp.ReadChunk()); + Assert.False(gxHttp.Eof); + Assert.Equal(Chunk2, gxHttp.ReadChunk()); + Assert.False(gxHttp.Eof); + Assert.Equal(Chunk3, gxHttp.ReadChunk()); + Assert.False(gxHttp.Eof); + Assert.Equal(string.Empty, gxHttp.ReadChunk()); + Assert.True(gxHttp.Eof); + } + + [Fact] + public async Task TestBufferedResponse() + { + var server = new TestServer(new WebHostBuilder().UseStartup()); + var client = server.CreateClient(); + var response = await client.GetAsync("/", HttpCompletionOption.ResponseHeadersRead); + Assert.True(response.Headers.TransferEncodingChunked); + response.EnsureSuccessStatusCode(); + GxHttpClient gxHttp = new GxHttpClient(); + gxHttp.ProcessResponse(response); + Assert.Equal(BufferedContent, gxHttp.ToString()); + gxHttp.ToFile(fileName); + Assert.True(File.Exists(fileName)); + if (File.Exists(fileName)) + { + string content = File.ReadAllText(fileName); + Assert.Equal(BufferedContent, content); + } + + } + + } + public class TestStartup + { + public void ConfigureServices(IServiceCollection services) + { + } + + public void Configure(IApplicationBuilder app) + { + + app.Run(async context => + { + context.Response.Headers.Add(HttpHeader.TRANSFER_ENCODING, "chunked"); + + var responseStream = context.Response.Body; + + for (int i = 0; i < 3; i++) + { + string line = $"Line {i + 1}\n"; + byte[] data = Encoding.UTF8.GetBytes(line); + await responseStream.WriteAsync(data, 0, data.Length); + await responseStream.FlushAsync(); + await Task.Delay(1000); + } + }); + } + } +} diff --git a/dotnet/test/DotNetCoreChunkedTest/DotNetCoreChunkedTest.csproj b/dotnet/test/DotNetCoreChunkedTest/DotNetCoreChunkedTest.csproj new file mode 100644 index 000000000..4e4d04086 --- /dev/null +++ b/dotnet/test/DotNetCoreChunkedTest/DotNetCoreChunkedTest.csproj @@ -0,0 +1,65 @@ + + + net6.0 + CS8032;1701;1702;NU1701 + Major + + + TRACE;NETCORE + + + DEBUG;TRACE;NETCORE + + + + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + Always + + + PreserveNewest + + + + + + From 4563df60baccfaf076fba0d78004dde90d59aa53 Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Sat, 4 Nov 2023 11:43:41 -0300 Subject: [PATCH 058/164] Support custom log levels for App Insights and Azure Monitor (#897) --- .../AzureAppInsightsLogProvider.cs | 58 ++++++++++++++----- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/dotnet/src/dotnetcore/GxClasses/Services/LogService/AzureAppInsights/AzureAppInsightsLogProvider.cs b/dotnet/src/dotnetcore/GxClasses/Services/LogService/AzureAppInsights/AzureAppInsightsLogProvider.cs index a5b7fbf2a..8a1e4318c 100644 --- a/dotnet/src/dotnetcore/GxClasses/Services/LogService/AzureAppInsights/AzureAppInsightsLogProvider.cs +++ b/dotnet/src/dotnetcore/GxClasses/Services/LogService/AzureAppInsights/AzureAppInsightsLogProvider.cs @@ -19,12 +19,7 @@ public static ILoggerFactory GetAzureMonitorLoggerFactory() if (appInsightsConnection != null) { - string loglevelvalue = Environment.GetEnvironmentVariable(LOG_LEVEL_ENVVAR); - LogLevel loglevel = LogLevel.Information; - if (!string.IsNullOrEmpty(loglevelvalue)) - { - Enum.TryParse(loglevelvalue, out loglevel); - } + LogLevel loglevel = GetLogLevel(); loggerFactory = LoggerFactory.Create(builder => { builder.AddOpenTelemetry(options => @@ -55,12 +50,7 @@ public static ILoggerFactory GetLoggerFactory() if (appInsightsConnection != null) { - string loglevelvalue = Environment.GetEnvironmentVariable(LOG_LEVEL_ENVVAR); - LogLevel loglevel = LogLevel.Information; - if (!string.IsNullOrEmpty(loglevelvalue)) - { - Enum.TryParse(loglevelvalue, out loglevel); - } + LogLevel loglevel = GetLogLevel(); loggerFactory = LoggerFactory.Create(builder => builder.AddApplicationInsights( configureTelemetryConfiguration: (config) => @@ -81,6 +71,25 @@ public static ILoggerFactory GetLoggerFactory() return loggerFactory; } + private static LogLevel GetLogLevel() + { + string loglevelvalue = Environment.GetEnvironmentVariable(LOG_LEVEL_ENVVAR); + LogLevel loglevel = LogLevel.Information; + if (!string.IsNullOrEmpty(loglevelvalue)) + { + if (!Enum.TryParse(loglevelvalue, out loglevel)) + { + CustomLogLevel customLogLevel = CustomLogLevel.Info; + if (Enum.TryParse(loglevelvalue, out customLogLevel)) + { + loglevel = toLogLevel(customLogLevel); + } + else + loglevel = LogLevel.Information; + } + } + return loglevel; + } public void AddProvider(ILoggerProvider provider) { @@ -94,6 +103,29 @@ public ILogger CreateLogger(string name) { return loggerFactory.CreateLogger(name); } - + private enum CustomLogLevel + { + None, + All, + Debug, + Info, + Warn, + Error, + Fatal + } + private static LogLevel toLogLevel(CustomLogLevel customLogLevel) + { + switch (customLogLevel) + { + case CustomLogLevel.None: return LogLevel.None; + case CustomLogLevel.All: return LogLevel.Trace; + case CustomLogLevel.Debug: return LogLevel.Debug; + case CustomLogLevel.Info: return LogLevel.Information; + case CustomLogLevel.Warn: return LogLevel.Warning; + case CustomLogLevel.Error: return LogLevel.Error; + case CustomLogLevel.Fatal: return LogLevel.Critical; + default: return LogLevel.Information; + } + } } } \ No newline at end of file From 1e6433793b0f8bec69b5e039e6d3adb2ec6cb4d8 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 7 Nov 2023 09:03:20 -0300 Subject: [PATCH 059/164] Build for TargetFramework 8.0 (#822) * Build for TargetFramework 7.0 * Install .NET7 for Build.yml and External-Storage-Tests.yml * Fix packaging error for duplicated content files. error NU5118: Warning As Error: File '\dotnet\src\dotnetcore\Reor\bin\Release\net7.0\Reor.deps.json' is not added because the package already contains file 'contentFiles\any\any\Reor.deps.json * Continue building Azure Functions only for .NET 6.0. * Retarget Net7 to Net8. * Update requirements. * Include NET8 SDK on github workflow. * Fix error SYSLIB0051 Exception.Exception(SerializationInfo, StreamingContext) is obsolete * Fix error SYSLIB0051 Exception.Exception(SerializationInfo, StreamingContext) is obsolete * Update dotnet version for the Fortify scan. * Prepare project for multi target build. * Fix preview version of dotnet 8 in fortify scan. Try to fix error NETSDK1045: The current .NET SDK does not support targeting .NET 8.0. Either target .NET 7.0 or lower, or use a version of the .NET SDK that supports .NET 8.0 when packaging code with msbuild 17.6.3.22601 * Change msbuild build tool by dotnet msbuild. * Upgrade msbuild version. * Specify a preview version in global.json to allow building with 8.0 preview irrespective of the checkbox "Use previews of the .NET Core SDK" on visual studio. * Upgrade msbuild for fortify-net-framework.yml * Add Jayrock for net8.0 * Add jayrock lib for net8.0 * Temporary include jayrock library for .NET8 package. * Fix Startup warning: The WebRootPath was not found. * Set the .NET version to 8 RC1 for packages * Fix version of RC1. * Fix version. Remove Warning Unexpected input(s) 'include-prerelease' * Add the target framework 'net8.0' to projects that haven't been configured with it yet. * Add NET 8 support for Azure functions * Remove the target framework 6.0 from AzureFunctionsTest.csproj since it doesn't support building for multiple targets * Remove hardcoded GeneXus.Deploy.AzureFunctions.Handlers.runtimeconfig.json with aspnet core 6.0 and take it from output directory. * Remove the target framework 6.0 from AzureFunctionsTest.csproj since it doesn't support building for multiple targets * Upgrade PackageHealthTest to test for net8. --------- Co-authored-by: sjuarezgx --- .github/workflows/Build.yml | 5 +++ .github/workflows/External-Storage-Tests.yml | 6 ++++ .github/workflows/fortify-net-framework.yml | 15 ++++++--- .github/workflows/fortify.yml | 15 ++++++--- .github/workflows/veracode.yml | 5 +++ README.md | 4 +-- .../DynService.Core/DynService.Core.csproj | 2 +- .../DynService.DynamoDB.csproj | 2 +- .../GxCryptography/EncryptionProvider.cs | 4 ++- .../GxCryptography/GxCryptography.csproj | 4 +-- .../GxCryptographyCommon.csproj | 2 +- .../dotnetcommon/GxEncrypt/GxEncrypt.csproj | 2 +- .../Cosmos/DynService.CosmosDB.csproj | 2 +- .../DynService/OData/DynServiceOData.csproj | 2 +- .../GxClasses.Web/GxClasses.Web.csproj | 18 ++++++---- .../src/dotnetcore/GxClasses/GxClasses.csproj | 31 +++++++++++++----- .../GXDataInitialization.csproj | 6 ++-- dotnet/src/dotnetcore/GxExcel/GxExcel.csproj | 2 +- dotnet/src/dotnetcore/GxMail/GxMail.csproj | 2 +- dotnet/src/dotnetcore/GxMaps/GxMaps.csproj | 23 ++++++++----- .../GxNetCoreStartup/GxNetCoreStartup.csproj | 13 +++++--- .../dotnetcore/GxNetCoreStartup/Startup.cs | 1 + .../src/dotnetcore/GxOffice/GxOffice.csproj | 2 +- .../GxPdfReportsCS/GxPdfReportsCS.csproj | 2 +- .../src/dotnetcore/GxSearch/GxSearch.csproj | 20 ++++++----- dotnet/src/dotnetcore/GxXsl/GxXsl.csproj | 2 +- .../Projects/StoreManager/StoreManager.csproj | 11 +++++-- .../Cache/GxMemcached/GxMemcached.csproj | 2 +- .../Providers/Cache/GxRedis/GxRedis.csproj | 2 +- .../Messaging/GXAmazonSQS/GXAmazonSQS.csproj | 2 +- .../GXAzureEventGrid/GXAzureEventGrid.csproj | 2 +- .../GXAzureQueue/GXAzureQueue.csproj | 2 +- .../GXAzureServiceBus.csproj | 2 +- .../GXEventRouter/GXEventRouter.csproj | 2 +- .../GXMessageBroker/GXMessageBroker.csproj | 2 +- .../Messaging/GXQueue/GXQueue.csproj | 2 +- .../GeneXus.OpenTelemetry.csproj | 2 +- .../GeneXus.OpenTelemetry.AWS.AspNet.csproj | 2 +- ...Xus.OpenTelemetry.Azure.AppInsights.csproj | 2 +- ...eXus.OpenTelemetry.Lightstep.AspNet.csproj | 2 +- .../Storage/GXAmazonS3/GXAmazonS3.csproj | 2 +- .../GXAzureStorage/GXAzureStorage.csproj | 2 +- .../GXGoogleCloud/GXGoogleCloud.csproj | 2 +- dotnet/src/dotnetcore/Reor/Reor.csproj | 6 ++-- dotnet/src/dotnetcore/libs/net8.0/Jayrock.dll | Bin 0 -> 30720 bytes .../GxClasses/Core/GXUtilsCommon.cs | 2 ++ .../Hashing/HashAlgorithmProvider.cs | 2 ++ .../Hashing/HashedKeyAlgorithmProvider.cs | 3 ++ .../Signing/Standards/PKCS1Signature.cs | 9 +++-- .../ErrorHandling/GxADODataException.cs | 4 --- .../GxNotImplementedException.cs | 4 --- .../GxClasses/Printer/GxPrinter.cs | 5 --- ...eXus.Deploy.AzureFunctions.Handlers.csproj | 26 ++++++++------- ...AzureFunctions.Handlers.runtimeconfig.json | 15 --------- .../AzureFunctionsTest.csproj | 2 +- .../GeneXus.Programs.Common.csproj | 2 +- .../amyprocedurehandler/amyprochandler.csproj | 2 +- .../test/apiattractions/apiattractions.csproj | 2 +- .../GeneXusCryptographyNetCore.csproj | 2 +- .../GeneXusFtpsNetCore.csproj | 2 +- .../GeneXusJWTNetCore.csproj | 2 +- .../GeneXusSftpNetCore.csproj | 2 +- .../GeneXusXmlSignatureNetCore.csproj | 2 +- .../SecurityAPICommonsNetCore.csproj | 2 +- .../GeneXusFtps/GeneXusFtps/FtpsClient.cs | 2 ++ .../SecurityAPITestNetCore.csproj | 2 +- .../commons/SecurityAPITestObject.cs | 2 ++ .../TestMockDBAccess/TestMockDBAccess.csproj | 2 +- .../DotNetCoreAttackMitigationTest.csproj | 2 +- .../DotNetCoreOpenTelemetryTest.csproj | 2 +- .../DotNetCoreUnitTest.csproj | 2 +- .../test/DotNetCoreUnitTest/Serialization.cs | 15 ++++----- .../DotNetCoreWebUnitTest.csproj | 2 +- .../DotNetPdfTest/DotNetPDFUnitTest.csproj | 2 +- .../DotNetRedisTest/DotNetRedisTest.csproj | 2 +- .../PackageVersionsConsistency.cs | 10 +++--- .../ProjectHealthTest.csproj | 8 ++--- dotnet/test/TestApp/TestApp.csproj | 2 +- global.json | 5 +++ 79 files changed, 226 insertions(+), 165 deletions(-) create mode 100644 dotnet/src/dotnetcore/libs/net8.0/Jayrock.dll delete mode 100644 dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.runtimeconfig.json create mode 100644 global.json diff --git a/.github/workflows/Build.yml b/.github/workflows/Build.yml index 04663dd9c..7466e8623 100644 --- a/.github/workflows/Build.yml +++ b/.github/workflows/Build.yml @@ -45,6 +45,11 @@ jobs: dotnet-version: '6.0.x' include-prerelease: false + - name: Install .NET 8 + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '8.0.100-rc.1.23455.8' + - name: Calculate environment variables id: buildVariables run: | diff --git a/.github/workflows/External-Storage-Tests.yml b/.github/workflows/External-Storage-Tests.yml index 5fae5df91..fbdafdbba 100644 --- a/.github/workflows/External-Storage-Tests.yml +++ b/.github/workflows/External-Storage-Tests.yml @@ -32,6 +32,12 @@ jobs: uses: actions/setup-dotnet@v2 with: dotnet-version: '6.0.x' + + - name: Install .NET 8 + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '8.x' + include-prerelease: true - name: Restore packages run: dotnet restore $Env:SolutionFile diff --git a/.github/workflows/fortify-net-framework.yml b/.github/workflows/fortify-net-framework.yml index 0c37aa982..d1c37d84c 100644 --- a/.github/workflows/fortify-net-framework.yml +++ b/.github/workflows/fortify-net-framework.yml @@ -27,17 +27,22 @@ jobs: with: repository: '' + - name: Setup MSBuild + uses: microsoft/setup-msbuild@v1.1 + with: + vs-prerelease: true + # Java 8 required by ScanCentral Client and FoD Uploader(Univeral CI Tool) - name: Setup Java uses: actions/setup-java@v1 with: java-version: 1.8 - - - name: Setup MSBuild - uses: microsoft/setup-msbuild@v1 + + - name: Install .NET 8 + uses: actions/setup-dotnet@v3 with: - vs-version: 10.0 - + dotnet-version: '8.0.100-preview.3.23178.7' + - name: Create temporal solution run: | $fortifysolution = "FortifySolution" diff --git a/.github/workflows/fortify.yml b/.github/workflows/fortify.yml index 4da890cd9..946f6482d 100644 --- a/.github/workflows/fortify.yml +++ b/.github/workflows/fortify.yml @@ -27,17 +27,22 @@ jobs: with: repository: '' + - name: Setup MSBuild + uses: microsoft/setup-msbuild@v1.1 + with: + vs-prerelease: true + # Java 8 required by ScanCentral Client and FoD Uploader(Univeral CI Tool) - name: Setup Java uses: actions/setup-java@v1 with: java-version: 1.8 - - - name: Setup MSBuild - uses: microsoft/setup-msbuild@v1 + + - name: Install .NET 8 + uses: actions/setup-dotnet@v3 with: - vs-version: 10.0 - + dotnet-version: '8.0.100-preview.3.23178.7' + - name: Create temporal solution run: | $fortifysolution = "FortifySolution" diff --git a/.github/workflows/veracode.yml b/.github/workflows/veracode.yml index aa0b97599..b635e46b3 100644 --- a/.github/workflows/veracode.yml +++ b/.github/workflows/veracode.yml @@ -50,6 +50,11 @@ jobs: dotnet-version: '6.0.x' include-prerelease: false + - name: Install .NET 8 + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '8.x' + include-prerelease: true - name: Build run: | diff --git a/README.md b/README.md index 2b52c8372..9324fe365 100644 --- a/README.md +++ b/README.md @@ -66,8 +66,8 @@ This repository contains projects for .NET and .NET Framework. It is organized a # How to build ## Requirements -- Visual Studio 2022 -- .NET 6 +- Visual Studio 2022 (17.6.1 if using .NET 8 up to preview 3 or 17.7 if using .NET 8 last preview). +- .NET 6 & .NET 8 - .NET Framework 4.7 DevPack # Instructions diff --git a/dotnet/src/dotnetcommon/DynService.Core/DynService.Core.csproj b/dotnet/src/dotnetcommon/DynService.Core/DynService.Core.csproj index 6d8118577..dde00ac2a 100644 --- a/dotnet/src/dotnetcommon/DynService.Core/DynService.Core.csproj +++ b/dotnet/src/dotnetcommon/DynService.Core/DynService.Core.csproj @@ -1,6 +1,6 @@ - net462;net6.0 + net462;net6.0;net8.0 GeneXus.Data.NTier GeneXus.Data.DynService.Core CA1812 diff --git a/dotnet/src/dotnetcommon/DynService.Dynamo/DynService.DynamoDB.csproj b/dotnet/src/dotnetcommon/DynService.Dynamo/DynService.DynamoDB.csproj index 0cbb8aec8..58d869618 100644 --- a/dotnet/src/dotnetcommon/DynService.Dynamo/DynService.DynamoDB.csproj +++ b/dotnet/src/dotnetcommon/DynService.Dynamo/DynService.DynamoDB.csproj @@ -1,6 +1,6 @@ - net462;net6.0 + net462;net6.0;net8.0 GeneXus.Data.NTier GeneXus.Data.DynService.DynamoDB false diff --git a/dotnet/src/dotnetcommon/GxCryptography/EncryptionProvider.cs b/dotnet/src/dotnetcommon/GxCryptography/EncryptionProvider.cs index c17a4064e..549cd8bcd 100644 --- a/dotnet/src/dotnetcommon/GxCryptography/EncryptionProvider.cs +++ b/dotnet/src/dotnetcommon/GxCryptography/EncryptionProvider.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography; using System.IO; @@ -58,7 +58,9 @@ public NativeSymmetricEncryption(string algorithm, int keySize) _symAlg = Aes.Create(); break; default: +#pragma warning disable SYSLIB0045 // Type or member is obsolete _symAlg = SymmetricAlgorithm.Create(algorithm); +#pragma warning restore SYSLIB0045 // Type or member is obsolete break; } if (_symAlg != null) diff --git a/dotnet/src/dotnetcommon/GxCryptography/GxCryptography.csproj b/dotnet/src/dotnetcommon/GxCryptography/GxCryptography.csproj index b5ffc6cc1..fef7ad094 100644 --- a/dotnet/src/dotnetcommon/GxCryptography/GxCryptography.csproj +++ b/dotnet/src/dotnetcommon/GxCryptography/GxCryptography.csproj @@ -1,8 +1,8 @@ - net462;net6.0 + net462;net6.0;net8.0 GxCryptography - 618;1607;1698;SYSLIB0021;SYSLIB0027;SYSLIB0028;SYSLIB0023 + 618;1607;1698;SYSLIB0021;SYSLIB0027;SYSLIB0028;SYSLIB0023;SYSLIB0022 GxCryptography Data Access GeneXus.Cryptography diff --git a/dotnet/src/dotnetcommon/GxCryptographyCommon/GxCryptographyCommon.csproj b/dotnet/src/dotnetcommon/GxCryptographyCommon/GxCryptographyCommon.csproj index 4b040e8f1..d6db9c1ef 100644 --- a/dotnet/src/dotnetcommon/GxCryptographyCommon/GxCryptographyCommon.csproj +++ b/dotnet/src/dotnetcommon/GxCryptographyCommon/GxCryptographyCommon.csproj @@ -1,6 +1,6 @@ - net462;net6.0 + net462;net6.0;net8.0 GxCryptographyCommon 618;1607;1698 GxCryptographyCommon diff --git a/dotnet/src/dotnetcommon/GxEncrypt/GxEncrypt.csproj b/dotnet/src/dotnetcommon/GxEncrypt/GxEncrypt.csproj index 9ebbb61f4..5f7d6885f 100644 --- a/dotnet/src/dotnetcommon/GxEncrypt/GxEncrypt.csproj +++ b/dotnet/src/dotnetcommon/GxEncrypt/GxEncrypt.csproj @@ -1,6 +1,6 @@ - net462;net6.0 + net462;net6.0;net8.0 GeneXus.Encryption GxEncrypt Encrypt64 Decrypt64 diff --git a/dotnet/src/dotnetcore/DynService/Cosmos/DynService.CosmosDB.csproj b/dotnet/src/dotnetcore/DynService/Cosmos/DynService.CosmosDB.csproj index 253f9f40c..281cac6cd 100644 --- a/dotnet/src/dotnetcore/DynService/Cosmos/DynService.CosmosDB.csproj +++ b/dotnet/src/dotnetcore/DynService/Cosmos/DynService.CosmosDB.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0 GeneXus.Data.NTier GeneXus.Data.DynService.CosmosDB false diff --git a/dotnet/src/dotnetcore/DynService/OData/DynServiceOData.csproj b/dotnet/src/dotnetcore/DynService/OData/DynServiceOData.csproj index ae4beeb73..0d2a21dba 100644 --- a/dotnet/src/dotnetcore/DynService/OData/DynServiceOData.csproj +++ b/dotnet/src/dotnetcore/DynService/OData/DynServiceOData.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0 NETCORE DynService OData GeneXus.DynService.OData.Core diff --git a/dotnet/src/dotnetcore/GxClasses.Web/GxClasses.Web.csproj b/dotnet/src/dotnetcore/GxClasses.Web/GxClasses.Web.csproj index dc3708d0b..b838905a3 100644 --- a/dotnet/src/dotnetcore/GxClasses.Web/GxClasses.Web.csproj +++ b/dotnet/src/dotnetcore/GxClasses.Web/GxClasses.Web.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0 NETCORE; GXGeolocation GXHttpServices WebSocket GeneXus.Classes.Web.Core @@ -44,11 +44,15 @@ - - - False - ..\libs\Jayrock.dll - - + + + False + ..\libs\net8.0\Jayrock.dll + + + False + ..\libs\Jayrock.dll + + \ No newline at end of file diff --git a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj index 2e8ab31ff..f2cba9c17 100644 --- a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj +++ b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj @@ -1,13 +1,14 @@  - net6.0 + net6.0;net8.0 Library NETCORE;NODATIME Data Access GeneXus.Classes.Core true 618;1607;1698;SYSLIB0021;SYSLIB0027;SYSLIB0028;SYSLIB0023 + $(TargetsForTfmSpecificContentInPackage);CustomContentTarget @@ -188,11 +189,25 @@ - - - - False - ..\libs\Jayrock.dll - - + + + + False + ..\libs\net8.0\Jayrock.dll + + + False + ..\libs\Jayrock.dll + True + + + + + + lib/$(TargetFramework) + true + + + + \ No newline at end of file diff --git a/dotnet/src/dotnetcore/GxDataInitialization/GXDataInitialization.csproj b/dotnet/src/dotnetcore/GxDataInitialization/GXDataInitialization.csproj index 7c41acaec..886477ee5 100644 --- a/dotnet/src/dotnetcore/GxDataInitialization/GXDataInitialization.csproj +++ b/dotnet/src/dotnetcore/GxDataInitialization/GXDataInitialization.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0 Exe DataInitialization GeneXus.DataInitialization.Core @@ -19,11 +19,11 @@ - contentFiles/any/any + contentFiles/any/$(TargetFramework) true - contentFiles/any/any + contentFiles/any/$(TargetFramework) true diff --git a/dotnet/src/dotnetcore/GxExcel/GxExcel.csproj b/dotnet/src/dotnetcore/GxExcel/GxExcel.csproj index 95f6df2d8..775944fc7 100644 --- a/dotnet/src/dotnetcore/GxExcel/GxExcel.csproj +++ b/dotnet/src/dotnetcore/GxExcel/GxExcel.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0 NETCORE GxExcelI EPPlus Lite diff --git a/dotnet/src/dotnetcore/GxMail/GxMail.csproj b/dotnet/src/dotnetcore/GxMail/GxMail.csproj index 50db5ccbf..61616d6d9 100644 --- a/dotnet/src/dotnetcore/GxMail/GxMail.csproj +++ b/dotnet/src/dotnetcore/GxMail/GxMail.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0 1701;1702;NU1701;CS0618 NETCORE SMTP Exchange POP3 diff --git a/dotnet/src/dotnetcore/GxMaps/GxMaps.csproj b/dotnet/src/dotnetcore/GxMaps/GxMaps.csproj index 128f906e0..bf243af4a 100644 --- a/dotnet/src/dotnetcore/GxMaps/GxMaps.csproj +++ b/dotnet/src/dotnetcore/GxMaps/GxMaps.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0 1701;1702;NU1701 NETCORE Maps @@ -11,12 +11,17 @@ - - - - False - ..\libs\Jayrock.dll - - + + + + False + ..\libs\net8.0\Jayrock.dll + + + False + ..\libs\Jayrock.dll + + + - \ No newline at end of file + \ No newline at end of file diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj b/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj index 6028dd9b1..ebd33f667 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0 GxNetCoreStartup GeneXus.NetCoreStartup true @@ -34,20 +34,25 @@ - + + False + ..\libs\net8.0\Jayrock.dll + + False ..\libs\Jayrock.dll + - contentFiles/any/any + contentFiles/any/$(TargetFramework) true - contentFiles/any/any + contentFiles/any/$(TargetFramework) true diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs index 3c9dc0804..fff6d6c6b 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs @@ -91,6 +91,7 @@ static IWebHost BuildWebHostPort(string[] args, string port, string schema) return WebHost.CreateDefaultBuilder(args) .UseUrls($"{schema}://*:{port}") .UseStartup() + .UseWebRoot(Startup.LocalPath) .UseContentRoot(Startup.LocalPath) .Build(); } diff --git a/dotnet/src/dotnetcore/GxOffice/GxOffice.csproj b/dotnet/src/dotnetcore/GxOffice/GxOffice.csproj index 58b337cfa..3169f7bcf 100644 --- a/dotnet/src/dotnetcore/GxOffice/GxOffice.csproj +++ b/dotnet/src/dotnetcore/GxOffice/GxOffice.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0 NETCORE Genexus.Office GxOffice diff --git a/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj b/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj index 2d941fcda..01a52310d 100644 --- a/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj +++ b/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0 1701;1702;NU1701 NETCORE Itext PDF Report diff --git a/dotnet/src/dotnetcore/GxSearch/GxSearch.csproj b/dotnet/src/dotnetcore/GxSearch/GxSearch.csproj index a56b1af66..e2ef170a8 100644 --- a/dotnet/src/dotnetcore/GxSearch/GxSearch.csproj +++ b/dotnet/src/dotnetcore/GxSearch/GxSearch.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0 1701;1702;NU1701;NU1603;CS0618 NETCORE Lucene Search @@ -28,13 +28,17 @@ - - - - False - ..\libs\Jayrock.dll - - + + + + False + ..\libs\net8.0\Jayrock.dll + + + False + ..\libs\Jayrock.dll + + \ No newline at end of file diff --git a/dotnet/src/dotnetcore/GxXsl/GxXsl.csproj b/dotnet/src/dotnetcore/GxXsl/GxXsl.csproj index ece24ed17..d3f5fde98 100644 --- a/dotnet/src/dotnetcore/GxXsl/GxXsl.csproj +++ b/dotnet/src/dotnetcore/GxXsl/GxXsl.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0 GxXsl GxXsl XML xsl apply diff --git a/dotnet/src/dotnetcore/Projects/StoreManager/StoreManager.csproj b/dotnet/src/dotnetcore/Projects/StoreManager/StoreManager.csproj index fba3e8425..64129d3dd 100644 --- a/dotnet/src/dotnetcore/Projects/StoreManager/StoreManager.csproj +++ b/dotnet/src/dotnetcore/Projects/StoreManager/StoreManager.csproj @@ -1,7 +1,7 @@ - + - net6.0 + net6.0;net8.0 GeneXus.SD.Store.StoreManager GeneXus.SD.Store StoreManager @@ -37,9 +37,14 @@ - + + False + ..\..\libs\net8.0\Jayrock.dll + + False ..\..\libs\Jayrock.dll + diff --git a/dotnet/src/dotnetcore/Providers/Cache/GxMemcached/GxMemcached.csproj b/dotnet/src/dotnetcore/Providers/Cache/GxMemcached/GxMemcached.csproj index 7b96da27f..f69db1bbf 100644 --- a/dotnet/src/dotnetcore/Providers/Cache/GxMemcached/GxMemcached.csproj +++ b/dotnet/src/dotnetcore/Providers/Cache/GxMemcached/GxMemcached.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0 Memcached GeneXus.Memcached.Core NETCORE diff --git a/dotnet/src/dotnetcore/Providers/Cache/GxRedis/GxRedis.csproj b/dotnet/src/dotnetcore/Providers/Cache/GxRedis/GxRedis.csproj index ef7f8104e..9d38c6b46 100644 --- a/dotnet/src/dotnetcore/Providers/Cache/GxRedis/GxRedis.csproj +++ b/dotnet/src/dotnetcore/Providers/Cache/GxRedis/GxRedis.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0 Redis GeneXus.Redis.Core diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/GXAmazonSQS.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/GXAmazonSQS.csproj index 53ad7604c..525f3c3c1 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/GXAmazonSQS.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/GXAmazonSQS.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0 GeneXus.AWS.Queue AWS SQS Queue Messaging diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj index 2f000f396..1bacb83af 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0 GeneXus.Azure.EventGrid Azure EventGrid Messaging diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj index 3f5265ff9..543b2cd48 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0 GeneXus.Azure.Queue Azure Queue Messaging diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj index 121e87165..15a2e62da 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0 GeneXus.Azure.ServiceBus Azure ServiceBus Messaging diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/GXEventRouter.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/GXEventRouter.csproj index d1e59a220..c2c2ccf43 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/GXEventRouter.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/GXEventRouter.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0 GeneXus.Message.EventRouter Event Bus Messaging Router TRACE;DEBUG;NETCORE diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/GXMessageBroker.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/GXMessageBroker.csproj index a1fc0121d..2cc2f4242 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/GXMessageBroker.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/GXMessageBroker.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0 GeneXus.Message.MessageBroker Broker Messaging TRACE;DEBUG;NETCORE diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/GXQueue.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/GXQueue.csproj index 771581f34..4779d04dc 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/GXQueue.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/GXQueue.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0 TRACE;DEBUG;NETCORE GeneXus.Message.Queue diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/GeneXus.OpenTelemetry.csproj b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/GeneXus.OpenTelemetry.csproj index 1564bc6e3..6c23dac29 100644 --- a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/GeneXus.OpenTelemetry.csproj +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/GeneXus.OpenTelemetry.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0 enable enable GeneXus.OpenTelemetry diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAWSOtel/GeneXus.OpenTelemetry.AWS.AspNet.csproj b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAWSOtel/GeneXus.OpenTelemetry.AWS.AspNet.csproj index 2fe0c462b..1fb368fc7 100644 --- a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAWSOtel/GeneXus.OpenTelemetry.AWS.AspNet.csproj +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAWSOtel/GeneXus.OpenTelemetry.AWS.AspNet.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0 NETCORE; Properties false diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/GeneXus.OpenTelemetry.Azure.AppInsights.csproj b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/GeneXus.OpenTelemetry.Azure.AppInsights.csproj index 0f89f3098..12ae1791b 100644 --- a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/GeneXus.OpenTelemetry.Azure.AppInsights.csproj +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/GeneXus.OpenTelemetry.Azure.AppInsights.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0 NETCORE; Properties false diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryLightStep/GeneXus.OpenTelemetry.Lightstep.AspNet.csproj b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryLightStep/GeneXus.OpenTelemetry.Lightstep.AspNet.csproj index 5702ecd91..6114b9112 100644 --- a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryLightStep/GeneXus.OpenTelemetry.Lightstep.AspNet.csproj +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryLightStep/GeneXus.OpenTelemetry.Lightstep.AspNet.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0 NETCORE; Properties false diff --git a/dotnet/src/dotnetcore/Providers/Storage/GXAmazonS3/GXAmazonS3.csproj b/dotnet/src/dotnetcore/Providers/Storage/GXAmazonS3/GXAmazonS3.csproj index 2f83482a0..2e1e3ce13 100644 --- a/dotnet/src/dotnetcore/Providers/Storage/GXAmazonS3/GXAmazonS3.csproj +++ b/dotnet/src/dotnetcore/Providers/Storage/GXAmazonS3/GXAmazonS3.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0 TRACE;DEBUG;NETCORE Properties false diff --git a/dotnet/src/dotnetcore/Providers/Storage/GXAzureStorage/GXAzureStorage.csproj b/dotnet/src/dotnetcore/Providers/Storage/GXAzureStorage/GXAzureStorage.csproj index 2e414d14e..099f6efb1 100644 --- a/dotnet/src/dotnetcore/Providers/Storage/GXAzureStorage/GXAzureStorage.csproj +++ b/dotnet/src/dotnetcore/Providers/Storage/GXAzureStorage/GXAzureStorage.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0 TRACE;DEBUG;NETCORE Properties false diff --git a/dotnet/src/dotnetcore/Providers/Storage/GXGoogleCloud/GXGoogleCloud.csproj b/dotnet/src/dotnetcore/Providers/Storage/GXGoogleCloud/GXGoogleCloud.csproj index f036cd022..0c3bfd68c 100644 --- a/dotnet/src/dotnetcore/Providers/Storage/GXGoogleCloud/GXGoogleCloud.csproj +++ b/dotnet/src/dotnetcore/Providers/Storage/GXGoogleCloud/GXGoogleCloud.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0 TRACE;DEBUG;NETCORE Properties false diff --git a/dotnet/src/dotnetcore/Reor/Reor.csproj b/dotnet/src/dotnetcore/Reor/Reor.csproj index f02fc7005..59e7feedf 100644 --- a/dotnet/src/dotnetcore/Reor/Reor.csproj +++ b/dotnet/src/dotnetcore/Reor/Reor.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0 Exe Reorg GeneXus.Reorganization.Core @@ -19,11 +19,11 @@ - contentFiles/any/any + contentFiles/any/$(TargetFramework) true - contentFiles/any/any + contentFiles/any/$(TargetFramework) true diff --git a/dotnet/src/dotnetcore/libs/net8.0/Jayrock.dll b/dotnet/src/dotnetcore/libs/net8.0/Jayrock.dll new file mode 100644 index 0000000000000000000000000000000000000000..fd1736afd37fd77285a16b5f092da19b42c8fb54 GIT binary patch literal 30720 zcmeHwd7M7=$5sarCA0Hg4-~F4zdgkAP71(Ll3mh^c}lOPoy)RO1as{rbHy&mx?4)k%cSTBR%fsM69eVFiDGUTST+#|U5;v%Y)ys7kN0_!iI-yj8@KNg*SKC|+Fg}a7K z!Y2v2D>$>4=sh;X$j?JWrJ!AO3DN42WuJs2M82YOAMlAqIF?PEodtd*g#=~NSFJaY zd?G}r$I_W}Cy?m27a8to8duThcnnu8o#=MK$hy))xLDRUTt%Pbi53(=$=<+r#fNn> z$wLh%5N%vcWC-=YpG+~W(NVPR)Dcz9uqX@>kQFp7+Z{y|2soEEn$>mArODAVolFfV zJDi$p>!cdG=5S7N3e6o2j=Bk^74>l8EHgR=gv?=FFJ?BFX5G%Q%rRc_R^4JV3adNr z;UIFUHN46MvpQPAf|i(88fx`M{Xo%L7O}jTWJkv-vC;8-CpvtFNymwe&=(udIWA>cLLHWjyn;z#^1jjbo!v6QR-`Od@h_m@M0Yq@JEx%DAGtlw(yZ= zbTUdTcM8(Fc}fthFqPqWGaBVP?82fQGtZz}Vkot3cN+6S80%rVP`U`!4?_)%Vvva5 zIn^IpEWMiR^RQvuOoEj-E@0e*C*U-icAbn)jSE?MK8!?;4{AD^FWQI(qA}H`1+^dg z$OQ?tST+nYqK;*E*Ey=vbgl$-YFy-;I_CeRHfHEH#0}h;`8KK#YJ>G>1~!W2va(sY zidjGbM#^tZ;`;E%VCGgZ229625_esHf@Qi-aZ9I|PlYhJ(OHn{&Si=4sl#~))Oa>= zYw%e{?raA0(6o%A8dPO#3_E5X1+9i!D^OEXU+H+SEj4}7d5}28J9=G-7t>|dpR^;~ zrS3e7lw^fRuNU_*b0|88+Y`S%3-TQv%M6^_30MsYtE8s1e!bUsZJEE1jZkF=?S^B5 zHuo}6<*5$^J>t|=juUiT(E}85=|8+YF6a@TuJQ)G4Y-tBJATFI8@;a7=Y_ue#7C5` zPowaOgy~PTW2E*qO6?k@@3G2zYb^Iu(8N^!0)IZFeJ~$~*{5!7dJX0@hNaOQU1#nz zF@!uUhyb`;ZKFN^xno|o+iL%d480d=eJ<^ zjFONMoeyfGlPQM`bn0jzO%x|X{uq$lW0B}!@ZceW0o(z-2xN{&GKl$R^Zd)jhefOM z@qxu#ZZp!lIu4M_xa-J97l2grp;>o^Il$E$OUz75PL?9E4Y9sLE=D?NHI}41U?lE) zK$S~_t!#OpZi`6Iaab+iR+12I%rls9j14lmzlH68Mv#jbM(^V;qn2TY4 z^jXyAIlKxL;FTQ9m%<*H@M4c-kv&A_5|rfwdlptVO3+6P{3i!?HEv@mGEa>g>u^vU zS)=XD5%Lk?=<+?SK-M{ zoyFrCh_)jMIESrYgw>Tc;~LVJi96F6W4)6*7C^bfr)VuMOz}K_8u|L2rgaMn4VyPr z4(8k~a5SLJ8excl5*neeKwTP57PLhp7!qY$HG&<1;Bg`oHUv6DAsJ}fJyRju#gygs z&mu_YeO=J%vk|KU+;_)zPv>H*F9H#mrG69BF|J66ZoJ{}n?Bp!#3b8NYb$&&;QoLq z<82iSC%}jh?bPv{*obyG?%Cptxwuzf9QW+v80WG_GDRX?kuyGd2xqjFGv;F3rxq$- zoM2mOEnRL`7)ndT@PPY6R;ob57#&1A`4F^qhoG%L1nrbV(BPuF4OZ$AR)90gUV6>o zrKP6Me5wosA?+S81Ktsz9>&o2tT zow*DQ2vt!`OQ-I8JV6Vk<^T)h5dS(#MY5%6?q`|3&UCZ5kN(g=gKodd)&QX`_M_Rj zW4Q{dGAmY>{sUT8l>#C9u%-&VlF(%B=4=!m7|8I<Y0BhIOT5PRD+9$l=EG4{%cRT^gWBJfVpCU-`!U*rexJ-Cj;<-rxg z6~@(#3)4$3ES)s>dq}YFWb3=tNa}K66a!UI7>7o$9Vy6EoK^*9@iR_*hB$bFiFp1l158cG#v(CECNaZQg|E}Y+~ zOMi>2J&){;^iPph@|0_d<)ujZ=45nF`KH);m^Y^XLn?FEqlmHcOoRpk%C9{%5q3s^ z51I`=Q=a@9o%G*O1y(_SuqcdOmq9cRlz77vI1mS>)RfNs6&f^s9Ek&E{_w__#~+^1 zRO1bAR2*Kvy3hR<`26FWg5LChK_tiOz?8YyGBNCDs%7S>=Lt2?RPIgt^VIsY{NYk2 zRTN04`NL&Q8dV^j(z3GW43u2=#of^B|g^Q>{ zrBuByr?YIqo#V!T^wCH89(&c6W7q>U?@wBxGk?tJZkTsOys_LKw2^rOC4&LpUDXVh z@-34Bd9Z}D1CmCs0*mW{ikOwwR}@5VLQ?012bw~P?EVD=GkTpOZx}(on#mai?m&rCT3?Obuegw|`YuY*Qe;+n zdK$(@0(YQh)(b_FmFYP&!_$<1mZV$2tfq!P9Y^Gy= zfIoUO+wPZ|>C`4a$JQ@1t;jq%7s8xUE@Vcztva-h!PKpP0Tk6b(^QF^4PepXm{}O} zhM3n0pBkG`Kkbv7t*_22ldiIIgYgN8P^j#R_G~$~L;HpP4>tL*l!=k? zK$re>p|WaR31y*&J9<4R%IZv0C3+6Gp_jwjJ*KI)xX;JN z#%ah6;z%Pr4_(<`q>Tz3`%o%@qcG~#`Sx$jx6d?lfKzGTCafRB+i!@KI^p>|_=B;U zdKijhz~n%9u<7ueJ#zQ-J4I^nxaa`zNk+kZ&_>ytSBh!o0H^#=UR|v$h^$@6R@;io z`>ze+8Cb?^*DvxQZ>l~}q$poM-c+%2^twR~nf2v4yk4+rtC(p?T=X=QDv$Mu4J~zE z@-XCKz=B2Nfe4zl8fb-cdG6ONSCxA-yXj`fXM=S-h#VmXv$KKeD(uCh&# zi?AnX*UYL4dTM5s2kmg>DM8P=r^~=nI(#*qb)8;8e{Le|2F&nLGd#$xuQS8Vv&ziy z;u$`~lXc-{ro@@jr77|Cb)&EvX0{;^M{k1)bvK$ju?@2av4^qE=yM?Py8A@_DF9Cm z*nsh&)PUS~n$df~WbzrO9sLexr64@uV(S^GTczQkKr{MXZsbqq0L$MAQ`t>eTUk=L zL2;;u8cmz0Xu>Ee@zYB563B>tn+5UVyJSu=twyh`PxT(PW(j$gsa7Wec~xsisJdae zs;3sK+NJv^I$G}8=#v@U&uxFt92gBjjWA~*(+~O}Lq$~mQ?bKRif_VPVFs7C3EI3O zC#8*nr>>F4s5=*x#8PbCn0F`h)O(7|ft?H+&)vbcu9{&GIQTFV^NZz8V3DSaEhacP{#F_48Dsb^*K#icN27tqo-8r}XUzIVh%@r4jH5Khn5N=df(z4E zu5)ppdkYdg{`8@e91_T*LXN=a7jv*fh*NxpdgWY)SPD~br zI7>Ysh+iB9n^^1@YUetL7I(wyM&RX1Q(m^Fyo^#+vXe`eNl9Qzb>L+WC)y8YLkK=q zRb(}RL-I9bfsFiEs%j*Uq9Z?xJWL;N?Ou)>IuiXOI%H-RBOQ#fe&RO^L?T*8l*WEj zpPkFYav(=iGh~1(f%I*jG@pi+SaO+!Q#LrggIJT}sPN=D6fOFyvZYo5QNbCU&MKe| z-yty`tX{p zo*Q|r@SMg}+_;~rl03pSG-z-Z%zzWEz5pCvF)16Af`)l!N_~r8U^GfM_0uH-Map~M zX`^MFhS-5>R92jbJ@E~;UjEcA`ZhzXpR>TqcMQ2LZxy4w&&G&SY4kx_v_jzG zs}REjB1X|%>|OCHX}W%ub0oqHyve-))KZ_k$Y{jTj(Z`nI!*T#FL_Vomb@~51KzJr z0@sVf&e0dq{2{g8@l!{Q`vG@HV%BQt&mXHgisg+L@+1%KLgaUFEXm}N6KBp$G6uyjOCf|3ID>_uRV)Y?`p=V!hnmsFpYDuvfC#YS`FvF9AbCg?=|74V1n- zPQQpflv%6me06FMQA+bqP&VZ~!vx(2EX%7P(*02B=XYS5GPXAC&gbM#-8M6GDL4k% zQaa13D&La#IMW~taebsu_05IG+-Jv*S~y@4k*Bgq@bf#u({abvFlecFgzjam$mN{u zK@zCXy(q-`DK9Fo;Gzd1z%sq=l?;9cpgaEwFA8&esF^3K{$tgb`N4Kz-Nzq7_jv`~ zokQt<#t7X%&+1&oNl^!|XO4iBJ!A*2X67$&Qq+r|Iv(~htP=Evj)G}6#o6R1Dh!pr^}xk(-d%dH=S@28BO>Bl>LcBy(~YOYn@HF{kD??d*2eb)C!*a=Sr?MoIIYD+2Kv)eX1 zHY3(FqiH7mmfzlBve4rgsEIp?W}|c0BNR<+&!&^9Eg9x`3Zdb72edWq^fg$m610gY ztZ7A1rh9>J#&&4pf^L3iD<2b`KRNtmKVBvf{oQEdjfsKmdR%Bm7TPf&`~i7{P}+-Y z46f0*cyHjxH69o9ay`D7kHryP<715e(^ovNmOIqxaC(OQ?eYrpRxte(&py9H9*5Hd zp7X06+G#%yo`~~HpF=;jH+vmgBBk?%^F5n6M@jw-Nv{yfr6S)6a;YK(!UAi{Q%4HL-TU1 zS?41Ca{0NStbpbr+EF!tQ^_rUPFG2Oe30`W7z1c)EP7o-FZl08elWmxI9jCr%F8la zOLl|O6yp4nQcmv{3tS~Ut0cWp^j}C^IziI8lD;OK-;i{kpG$vS!o8bc!7{&&y5)2( z^em@6NJI3dXn4KFy0wa)4+&;jR`&X%;`^pq5BO_8t&jey6Yfx4$Wlw~-%tVmmvM*G{N=^l;CF6)n_X%FOaNDrV3edQVzdT*l}~`iG!8DVs~C!95zKkw?(4g>x?X1RbGK ziJ;jUl^fjKF9|w|LI$=Dl*W|*HXTKy1bs6|^aRjh#>$~bj5%oe4QH-x(5}$Y_AWXj zbiA$T2K^$m&|W*#ST%>%4o#HwNTf&5m8B4{#$r%bJ?3pxM(oK>smGl-#FGuP)8CnB<+G!=y z4U+!Q$N67*IeoN*(|OQm?T{1XbWbIx-xT^`)ttYninaZ8*;cgm=d$j6Pn8b8tL#PT zdsSJK-c!l?T!+-4%d6HPy#u!5cDZ+xD$a)f)s=%tZAp77=U`1&8lGUCi?*yFrw>(f zT2syG530_!+aiR|)l?n45OOx=(Pg$p7i#o&)it(5d-7iU=x)1= zzA0$em_9_|O8UMoyUKf?T}hAS(S9RHKh@~x-u*@uy&_1}8%64Kz|&Rvuw9HEvuo%r z;k-av7(;){qe`qS0n7^`E<0MjlgsEp*>rCkVP`I%17#({(0fi%nP;5$Cw89G(+q^& zu&U?zTcsoCstgZ!z7u-J9;b?c_EfgXcOq0-3DzO(;N)|_^H3;Vgl?*8qX>=9>xt-3 z(L8#=j?j664)`DUZGnGZq0!U6Zp71liqrRZ?_8Qhw<<)BhJI~NqPrERaT~sTKbd}z zN8L1qp4MoMH%(FcwMI8pY{#zoO^r5s*Haz+L!*-_|6tdXcY^fDc-+}S4OE>+f3h2C zx<;S!|G}P4N9WO>?HLr;=vMQu_AKhnqkq^5y{pmNRUyxOGI{$z2aFdg$9RsWNdREfA8m+2W3AB+9tV#8K6`iAy^mY}!D~Lz)RcfbjlsO-vy3nh5#))YZ z3!dybnOZe!_r8jC_hgOMmpJ&Q;ATN8PHd!}JgP+5t~@##EA%yj4xshN><-$?50dnV zaaQSLcAWmE(fz*1>`wYfqchCYJPGpgqXIaWRd;!|(2z!WW$j7Q#TxB$wtLQ`8#FqW zc6xf~PK~PQe2+_yYBY;>d(NU4G>ZGK^knEwjecuh@986>UbT05jnZhE|29uQ zjo0WN@133jnkq>3eUPRLx|+U8_j(3taZ%Y$T0RV&oJS9Mc2bu@^p^D#`_q)oqenbL zbVDBf$g_*p!skHQ0{_#Va}@v@TXiE9kjFO{=*Oy_?_@k1olC#aQf?8XDjx7G6)CUj zvZel?LuRyrOD~|EnA4x3Pif@%PXlVx=-VY+)}fJsC%DhhSsF#@MbBsGB8`4w{s!n; zjV>~O5A+R<*7#lndO)Mwuv7gEJ*H7gTKKs}^GkjXP9M&JS+k#DeK?PT8vUY*QLRQF z1WyB6s?lqqHlTHa4j8Y6-twGB=izWVHy_TYZwoq4=JfgWkf5t+iG81aKD|AiIaMsU zfIbk!BmJ)D0$Mpkr1*FoE~NDu@i<&aT^jK?Tu8kN5!?DgdR)*hj5MR#S<-^Qs<^CEqpyS*U8^}a7|eN}F8fHzrsCupdiwgLY^g%@wMwpcpGLb&7*)3o*9=FwPZH$A1% z2foS9WwaMhz(jj!m35ze8O_A`7^8T}H0N^KB1p}uJ(SI(n6rnj7j(e?MClyo3c6V# z`U`yG3VKAN-GW}wsK2BVWz~GlfH-(D;^&n#L8FII_Iaw;DC8eSSJ48E?uJKRO)E5V zu-CYn_-{y9%8l^4tLZ#JyJ!;jTvyYL8XXr*(--JTjj}<9uAx6_)MPU<<&;1PAhtvSu_bUW zB%cEwwgk>~G-69!PgjU82mI^H<~!HZ*EH%bJ09pxg$(Y)4Rp6g50xx-ZlK5V=p^Sx z`c)p`NrB$Zqc&$RS@XET1I9xoYn**FI*&FwU#4U8DDK=u35~v6^@4pf_2!Z5xrLtB z=u1wTzDlnNx`19U>2khCUL2Hh40!?QR+=J6&HmdcCP>-(Hkzk6B{JMbEqPRlx4vuh z=xF*nogwIte%}4wPG@PvyWiXCY>jyLdpmtvA%l0nx6?%$@$UDVWaHF_H4FQ@oo`X8 zpg$VC7ruic8u4EE4oYdnd*Qq2GL3jId>4ILBi;+&ML*Pt_riD6?*;9mu_2r%(ClNm zye(?Chs|^XNfi zKfR{WkGzA<_vn|$vrM(``96IhNcHIZWH)meqjR0_Q?;N+i1#7)(c`L&s>?2R9-wCh z9WbiP_BapG>;+u!fN@#bwayP|okl+`+v_|+Hw)TDKLUD`YFn67$vi+y1gX{^r>%kx z5buH>r@ex%q-@n!oqwa+gjX;pVPKcU|jaXv+F6mdR9lNPa* zJv1h`-}xC`BS^`7mi7u#GM}aA1YL=f(H}TJr@t3*K2PT2f-cWfNgh?w^E642lJWwb zENB-sT0e4rMOi_Q5bw`kqI(7Hp=bQhI=`j~ClqA9!daZ^ux2kgIds7IcjIZ#?{wJ# zd<$_zTCl+TVfSi|!c{TL@5|FhBoA4}lWq_(2`s}9p&N4o~KmvE`d zKWi|BQChUKR@! zmmWMW#iLf7XZ>@dd5&4gpC&r1zE3Zr7xVwW&d(KpdtR)e{A!F)R2s)ApFt`;n5R%` z((&SNOfl)x`C5u@X^N8nhPPmOH5O`oi&G`-J2KZkj;EOapUD?I%A{MQkE&L2e-9qh z;<={yi#*l zTv}YWIDf9p_k&|d_s7tuK=Yhu4wF;ljVXyX#ibKP+k^dq90cPS1G=2TZ1!sKlPOxIH~8;#>0>XXd2Q=nknf~LT^So3V%hy=}MummozSE zQqr>|?U!_yq!%MK=uXMMg4Cg-jK1=*)QXh%r>Tl5^gi;ubNwd8u&Qz1Fgf*`S5?nJ z%BOUUVdLMhY^`QJZbQ(QPzsBj)ep-Tan0JWJ z0N*D*``eE{-ku9eL#P`RKF52X`26mD;&Z#8d7(8#hvCl}EEDd~Dirx{F- zOFk)Svy4%{wBk3rDwi96v%h+cvC@3Y+F-0l+6n%*tdx;Ny3Lqoyk+eKPgmtdNINP& zZ>)y|gVq~w(pNzFQN`_`yh(RS>3*cY#aZP_<9Bo;#igyd@iuxIH`pd|gHH%q0(-?q z?~~wv#djldTR$@{7Wyt@q5Y1*X{AWO+YfnOiJP5xE0;uS;ID&9Xao9wrMb5Jyu=8d$E`m3AGeRP#^8uERW*tN=t z?3c0LM}PEfF!zf-4;z0m&N5#yzEQE=ywwz6H5}_kdKhCpXg+N$s`{*Xr^!4|7%t8d zo(6pjyW>McTU}?LA1FinE?C`eOK- z?jyZ1{Ds1CNDrsekWQp6NbBixq)n(Bqxtj%@-6gJq$kmHNZY9jbvIB1X(u%zJ(G?@ zni2W{Qp@-pt@pJ^dXsS-b^3m2+(g~JNxmx~bD^Z?NqPh%pF>~99DN9Se?%olr7^~+ zHx?SL#-+w}#v{f{#w*x`{?%~IGIO*!-E1|Nn{jiCd7gQ>dA0c!^I`Kb(~HRIgN*}t z_gH~62#bgC_PrYKN@@@>N6QVCQ(u4Im(l-P2 z&sK3Ow;G3g`R%NQH6w&?3z!%uFVgW?4Gg?#@gpC>2%7lIBfQ^5h3HonhoPtQ( zP{YLg)=^0NU;`6BLv$F@?HFql{xlBh9!N5AK63=pt1$W|d}}h&YiTOd8?erpI47t_ zx({zwO+0T;M|uD&k3o+iHSxB!3F)u!Zq=k0=~GBw!<$Z%-h}6v^cLPze2eTMUfYU4 zEm-sLU;guqITx$uNZN%`KAi8**e{IaI~=>-k+gf61PcYxH*7A5Rwd$_TT|JlS+v?! z_r-3yC!SUL6B0V3*^Zn|`QqaI%p>XOW$xy_?!>XQV8vqElE`)}!hLz`QfkdCk1wb8 z{!BK}6Kh>T+v44QiH?pOWnnxU&*fX(?(RfqHtD7^vE^>+ghVQlPIiip)Vz5!L@i8o zB~yvbhpN!to9Il&yOTRmygr%e-b^b}i&C4V_G*`N&Aq(|+*rA`csi33IL*WIBWL;SEZOswf3Lh4R)6Mj(;y zigzYN!FIPVjci9o-7zq$`+E~D__;Fb*qrE!_jN;hCKKP1pdNikms?ZY+%prjAh9Kx z(s}Of>iDMa1hM5+PK~L`w=PQc^(4~5q3A_~M4_y8VKUR}W`vJrwx%#xC&n{dvqEZJ zl5tb2z9Oi6F{Mi!O_j2LEp+=>t<|p1C|(WFVVzsmm&zu465Rb0?GS#qEZ!|SB}%f|owY6mXH8H` zH>Yb-iA-m_H$m|%zFM`Z4^p6MPDe^~CwdYo89d5z!7?|k)WP_~)5&-$+k&y|15q3x z74PP8D$I-p@l1kPP35g43Kk}1`oz=y!l%XvE}}e3ydD!`TLRvX=>aECZbm<88JbLX z#xvQ4&~FPV?KSL- zc|;2noBFnFVc#gwTHKzs$xLz>tvQpy1nll#oy-=qvOBeINulLJ^%a{kZZ{MwP*%s& z7~;igm}k42KC@8J(wE7)Jq4U=WpT1Qu@=@q$T_&MHHDrc7NRiT{jppvZmKJ}r7taf z2MbvUcSt9DSxBJ}VNA_f4mAbxszg_NyepCIUxi4TDbQi3-Xz8XGFBzJ<7Z2*sJywm z+ue@A%_9E6a%prnvAG3#^sFEy*XOo0B6Vl>;DQ#nw?CcSvbCtFWobJ%-pzhlsDP&8 zJrcYMw48KikEi+z1$vGMJ)7K=>`rEjO4XcN&=1ey$thu%-0saPBd(>g#V&kMpyuhN z*mNvZAeGpzGKrqvY`@BGZPcoa_rb9xyuZXhRRo{*r&a=F)ySqSH z?Jn=*K`c;KV2pZP2y9JlPMp1>E4Nl@JH)gjAv(#@q?#bY5lz0h z$sNzt!UCkTi@3Ww-`=+=qgXq)Qd?hUD=qHkl&!rqk=l|~*@cN-ui2**y?GQ(0^y65XVQ#x{2&&-M_Zk`YTuPWg^xS#T>h7?jCnlw4Yk@x{IY-kIEz z;^@Px1o4tayzsVkC*moQy}(5*L0-h?z-l*_(|)R%PDo^P1>Ev#EV4?9%JHbFTt`-l z7OD`A1%?nVvdL7ROkwIQ2HFxQ;2XBQjZqxAg(lIZcSh7&2>FF2yojc)f)FSUUsO`i zqKJrS(3?nS`*U&1O&1k%jaBaUB1&g|i-tun+uqmP>!uNG7MpskpuP{QUeAkC-t zVg+)N_a_CYtW>}&uqJjPiWVr^@@#?_yt4;=%XuX?NbP4Pdsn;SMY!ojo0kk~!(W)K zNU>|BNxFPu;_Q~K06a02UdqjM{^LU1uw}cjztmHKqmB}zA`qzw&u!!i*w>4(I7AVV z`=QIlWicT%Oe-m^Bi2ng%eEwokLOnTJf&4xG>?08tV*o~eaUXFsJK>Sw<6DNiha_w z8cpkLM=$Tq(}XaqkqSRZ9>wabMl4oxFS9n!TzEwyqKFz@rEN?`^T z3X8Yc5Wh6OqrV;7x6W*Vg|% zkM#2bBRnMJ_M=7ASSOdoI_1W;FT@^FQ=*6fhZ+%|a)Y=q8OMe&gNI-%&Sj^JE5CR0(HQZSq0AXu!=imNX@$TY(KVYLg&HC z(9&ckt8&RyXLsM`1Qy`V?l^X}B6q}u5}J%~M!7izxLdFl$3AY+Sy&%4vS7rMDb)u2 z0EATEPY;og*wyY}ZAu;y~5hwna@J+N|#@ zQkYECk#hAT5%v*?5joJ2E>faGF_QzPEEt#|l2?-|htk8SI>-{JYC`bS0(B(iwnX}s zpAia44~q&^R?h$hR=euX6G7$R%o2_ANM&+6{5Pn!$b0vqN`x}V(M4vBAg7|aFl_5?hWu{^%uY_fehxj3uD5e%*#Tq&H} zGCrGQV>eY^Q@;gE}qRPuLg zdE`A4eEmerno);aO5>l4D}uBW|N4ZYM=k?y=IjIq+AQ0S zd=h%HJSxl86V$R;cv-^;4bTi4#C^N;hWVH_Q`6$oU+#zMBg@;&@=Lm)M>k3nL~DxW zErLFawY;QQQQ3=Y_CQKDuX`3+u-<2a(uA*5_y-T63+>t34htnGXa0=K%R||%xPBAl%!pf!iL@%uoS+wit;}EA$$XV zAoo;QX*#~$Jppeb25`!L49@Lo+%ohhgMT@lw~3|tpeHo)BRrx$taj#V?LTapvqih9 zdNiiO8e36|eJ$r@EUgp0VDDgW3%C@PLxTG-Nl=x@nG%SHVPh4JlDC7@-MWwz8!s2 zBe>!d>>h#UJZCwwu@!kNl+SQ0#WmaD8(H?&e~IKpGHS*0AsK(~o71`ZkY35!eX_=d zdU<{S1yYr^1=-Mb8jrg2o*uC}$A4u*o+gQ;r%wAfr6A#_P30iP})oj!-B8dM#%LA;VV-WHRaps`Yum??b6!aAMY4 zUZd87pDNtt$6HjhHnb~TJJP#|<7UMGiE26v5u8qh1$6IzL15ExhMtF7?* zLJ`h{BBDe9$_$+!9J)A^^q}FP^Cf+Wo35>u{3YD6(9k8UQmw~}b_a#NiyMkaXUb98 zi_Y(1-B+S*WJ4?c5M3D>+7*gJ&2m-`lFD)8ibo>}E_KK%FNaigr@S0oJ}wTB6(|qx zYDN~MQYLXf`HnZn!J(@-hbpKEb%IOrjSWaCFAsPfUufudpH&V^L*v^msBGzcxm4hh zD);%kHadN~#mHx&xiZ}x3~br>?JFxU%I5=*VWD@Sp+{|ezoV3sGRJGO0Pyo5u|%)M zB7M>a=J_#f>it2F z$~$cFT`SS8S`dZhbs?>n{F|En9mT%uRH3R$akPu!V3#Zx!*N&Mhv9tV%F*IDD1XOs z9iI+97nrx|U%!Q0`p?Ai+#V~p?ia`F;=P$Kw*?3k_E5gu7SY7-Ltws=&9l}9!f(uQ z!bBUhhVZ8nNbuzZ!XL&W!B-f`#`oE1^FO2G|8%XfoX{j({kR5k)#BP{JE5UFEho6t zbbKa$1O{-3lZQ=*%d2tCz!k+6Vfu5NyktAUq4VHHwV`F9l|K9cDBn#Val}E+PnhRI z5>Hb+rV!w|4+l3k`>&<wPf$a&x5G1z~E=>4O(s1oScsL z;yrx+0DtvXJX&WA@R^vAL{Wn#E@@w}ym3`qOC*VRn(`uEUL{0uFcoQTZ;LHov>Lyh zXi!uBRcIvIIW014#*8@)k>+f&E7H6pxg!>7?(UAro6<}K2P`;cOl-#9#KUodQ{0a+ zXbg*M;WyU3y$$-U-!a?f#%4g>^6LCcYJNxG9hYMfAJ>S01HYH!&AnG626*k8;1~b+ zGA5PI1V?O6Z1${~M>XN;$DnFWnfa-vSx3%^L>DBo@oCuC7-Y*!G5k;i4T*9M22EX) zNkj@K|FIEABlthz;q7sp`-58Y6(a5xK1;5+>oa65Yh!cbNsL~+1eePt>cb7-E5kGu z*MduN^(uNU#aDudeO9$EY|r#KclY_vX}#!g8y~uE_cgDvjFx#D7bdoCT)k?|@{=~| zliZCbtlNmM11(Qv*`OOU+07fZeKz9MZlgBO##AB;+vJL3y_+{t`-#o7<{U}7q5fP$ z=!{i;%Yl#X`)l8K54TS8?SaC%&(}F0$)Vx*-2aeHQ9Gc`!tU;6IG?4SOea)J$SX@- z=cCCGGqT&m<^3=EZ&-kTi9~)wXlQsPnQ?p`a1fpOPQ=3q(B3y(Sp;dC~h zB4GnM9W5C625IrLFrHrW=TnX7E&n@>H z9;fB_POO2EF6JL;_2D+3iEp+xq0dL6$83WI(49{bu=dCp@VGalU)(c30qce(BbXV( hM{=efMIK4^-(jC2_5TcgNd7i+Sjqo_{|_wie*l>hlWPC~ literal 0 HcmV?d00001 diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs index 5164f74e9..6235c5785 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs @@ -3661,7 +3661,9 @@ public static string GetBasePath() #endif public static string GetStartupDirectory() { +#pragma warning disable SYSLIB0044 string dir = Assembly.GetCallingAssembly().GetName().CodeBase; +#pragma warning restore SYSLIB0012 Uri uri = new Uri(dir); return Path.GetDirectoryName(uri.LocalPath); } diff --git a/dotnet/src/dotnetframework/GxClasses/Cryptography/Hashing/HashAlgorithmProvider.cs b/dotnet/src/dotnetframework/GxClasses/Cryptography/Hashing/HashAlgorithmProvider.cs index b7b999077..5bb9a6247 100644 --- a/dotnet/src/dotnetframework/GxClasses/Cryptography/Hashing/HashAlgorithmProvider.cs +++ b/dotnet/src/dotnetframework/GxClasses/Cryptography/Hashing/HashAlgorithmProvider.cs @@ -42,7 +42,9 @@ public HashAlgorithmProvider(string algorithm) _hash = new SHA512CryptoServiceProvider(); break; default: +#pragma warning disable SYSLIB0045 // Type or member is obsolete _hash = HashAlgorithm.Create(algorithm); +#pragma warning restore SYSLIB0045 // Type or member is obsolete break; } diff --git a/dotnet/src/dotnetframework/GxClasses/Cryptography/Hashing/HashedKeyAlgorithmProvider.cs b/dotnet/src/dotnetframework/GxClasses/Cryptography/Hashing/HashedKeyAlgorithmProvider.cs index f9b8e916b..1449f4953 100644 --- a/dotnet/src/dotnetframework/GxClasses/Cryptography/Hashing/HashedKeyAlgorithmProvider.cs +++ b/dotnet/src/dotnetframework/GxClasses/Cryptography/Hashing/HashedKeyAlgorithmProvider.cs @@ -14,7 +14,10 @@ public HashedKeyAlgorithmProvider(string algorithm) { if (GXUtil.IsWindowsPlatform) { +#pragma warning disable SYSLIB0045 // Type or member is obsolete _keyedHash = KeyedHashAlgorithm.Create(algorithm); +#pragma warning restore SYSLIB0045 // Type or member is obsolete + } if (_keyedHash == null) { diff --git a/dotnet/src/dotnetframework/GxClasses/Cryptography/Signing/Standards/PKCS1Signature.cs b/dotnet/src/dotnetframework/GxClasses/Cryptography/Signing/Standards/PKCS1Signature.cs index 23b4c6629..e4bb4e65c 100644 --- a/dotnet/src/dotnetframework/GxClasses/Cryptography/Signing/Standards/PKCS1Signature.cs +++ b/dotnet/src/dotnetframework/GxClasses/Cryptography/Signing/Standards/PKCS1Signature.cs @@ -77,7 +77,9 @@ private string SignRSA(string signed, byte[] data) throw new AlgorithmNotSupportedException("Private Key does not support RSA Sign Algorithm"); } +#pragma warning disable SYSLIB0045 // Type or member is obsolete HashAlgorithm ha = HashAlgorithm.Create(_hashAlgorithm); +#pragma warning restore SYSLIB0045 // Type or member is obsolete byte[] signature = null; try { @@ -118,8 +120,9 @@ private string SignDSA(string signed, string oid, byte[] data) throw new AlgorithmNotSupportedException("Private Key does not support DSA Sign Algorithm"); } - +#pragma warning disable SYSLIB0045 // Type or member is obsolete HashAlgorithm ha = System.Security.Cryptography.HashAlgorithm.Create(_hashAlgorithm); +#pragma warning restore SYSLIB0045 // Type or member is obsolete byte[] hash = ha.ComputeHash(data); byte[] signature = dsa.SignHash(hash, oid); @@ -134,8 +137,10 @@ public bool Verify(string signatureB64, string text) { try { +#pragma warning disable SYSLIB0045 // Type or member is obsolete HashAlgorithm ha = GXUtil.IsWindowsPlatform ? HashAlgorithm.Create(_hashAlgorithm) : null; - string oid = CryptoConfig.MapNameToOID(_hashAlgorithm); +#pragma warning restore SYSLIB0045 // Type or member is obsolete + string oid = CryptoConfig.MapNameToOID(_hashAlgorithm); if (ha != null && !string.IsNullOrEmpty(oid)) { byte[] textData = Constants.DEFAULT_ENCODING.GetBytes(text); diff --git a/dotnet/src/dotnetframework/GxClasses/ErrorHandling/GxADODataException.cs b/dotnet/src/dotnetframework/GxClasses/ErrorHandling/GxADODataException.cs index 117c4ae61..1e6b26800 100644 --- a/dotnet/src/dotnetframework/GxClasses/ErrorHandling/GxADODataException.cs +++ b/dotnet/src/dotnetframework/GxClasses/ErrorHandling/GxADODataException.cs @@ -21,10 +21,6 @@ namespace GeneXus.Data [Serializable()] public class GxADODataException : Exception { - public GxADODataException(SerializationInfo info,StreamingContext ctx):base(info,ctx) - { - - } public GxADODataException(string mes, Exception ex) : base(mes, ex) { if (ex != null) diff --git a/dotnet/src/dotnetframework/GxClasses/ErrorHandling/GxNotImplementedException.cs b/dotnet/src/dotnetframework/GxClasses/ErrorHandling/GxNotImplementedException.cs index 5a872a533..6d0c4c3f3 100644 --- a/dotnet/src/dotnetframework/GxClasses/ErrorHandling/GxNotImplementedException.cs +++ b/dotnet/src/dotnetframework/GxClasses/ErrorHandling/GxNotImplementedException.cs @@ -8,10 +8,6 @@ namespace GeneXus.Data [Serializable()] public class GxNotImplementedException : Exception { - public GxNotImplementedException(SerializationInfo info, StreamingContext ctx) : base(info, ctx) - { - - } public GxNotImplementedException(string message) : base(message) { diff --git a/dotnet/src/dotnetframework/GxClasses/Printer/GxPrinter.cs b/dotnet/src/dotnetframework/GxClasses/Printer/GxPrinter.cs index 760e2320d..1fc0f752b 100644 --- a/dotnet/src/dotnetframework/GxClasses/Printer/GxPrinter.cs +++ b/dotnet/src/dotnetframework/GxClasses/Printer/GxPrinter.cs @@ -2147,11 +2147,6 @@ public void setOutputStream(object o) { } [Serializable()] public class ProcessInterruptedException: Exception { - public ProcessInterruptedException(SerializationInfo info, StreamingContext ctx) - : base(info, ctx) - { - - } public ProcessInterruptedException() { diff --git a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj b/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj index 90fa92d9a..ee77a03ba 100644 --- a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj +++ b/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj @@ -1,11 +1,12 @@ - net6.0 + net8.0 Exe v4 false GeneXus.Deploy.AzureFunctions.Handlers 1701;1702;NU1701 + $(TargetsForTfmSpecificContentInPackage);CustomContentTarget false @@ -92,16 +93,19 @@ Never - - - true - ./lib/net6.0/ - - - true - ./src/ - - + + + + ./lib/$(TargetFramework)/ + true + + + ./src/ + true + + + + diff --git a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.runtimeconfig.json b/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.runtimeconfig.json deleted file mode 100644 index 7c147f531..000000000 --- a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.runtimeconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "runtimeOptions": { - "tfm": "net6.0", - "frameworks": [ - { - "name": "Microsoft.NETCore.App", - "version": "6.0.0-rc.2.21480.5" - }, - { - "name": "Microsoft.AspNetCore.App", - "version": "6.0.0-rc.2.21480.10" - } - ] - } -} diff --git a/dotnet/src/extensions/Azure/test/AzureFunctionsTest/AzureFunctionsTest.csproj b/dotnet/src/extensions/Azure/test/AzureFunctionsTest/AzureFunctionsTest.csproj index 86add5f40..f47c0cc47 100644 --- a/dotnet/src/extensions/Azure/test/AzureFunctionsTest/AzureFunctionsTest.csproj +++ b/dotnet/src/extensions/Azure/test/AzureFunctionsTest/AzureFunctionsTest.csproj @@ -1,7 +1,7 @@ - net6.0 + net8.0 false diff --git a/dotnet/src/extensions/Azure/test/GeneXus.Programs.Common/GeneXus.Programs.Common.csproj b/dotnet/src/extensions/Azure/test/GeneXus.Programs.Common/GeneXus.Programs.Common.csproj index c445f203f..f9024993a 100644 --- a/dotnet/src/extensions/Azure/test/GeneXus.Programs.Common/GeneXus.Programs.Common.csproj +++ b/dotnet/src/extensions/Azure/test/GeneXus.Programs.Common/GeneXus.Programs.Common.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0 false diff --git a/dotnet/src/extensions/Azure/test/amyprocedurehandler/amyprochandler.csproj b/dotnet/src/extensions/Azure/test/amyprocedurehandler/amyprochandler.csproj index 7819ae015..9119547f2 100644 --- a/dotnet/src/extensions/Azure/test/amyprocedurehandler/amyprochandler.csproj +++ b/dotnet/src/extensions/Azure/test/amyprocedurehandler/amyprochandler.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0 amyprochandler false diff --git a/dotnet/src/extensions/Azure/test/apiattractions/apiattractions.csproj b/dotnet/src/extensions/Azure/test/apiattractions/apiattractions.csproj index bb8cc1893..5454ea407 100644 --- a/dotnet/src/extensions/Azure/test/apiattractions/apiattractions.csproj +++ b/dotnet/src/extensions/Azure/test/apiattractions/apiattractions.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0 enable enable false diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusCryptographyNetCore/GeneXusCryptographyNetCore.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusCryptographyNetCore/GeneXusCryptographyNetCore.csproj index a578b162d..15ab5514c 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusCryptographyNetCore/GeneXusCryptographyNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusCryptographyNetCore/GeneXusCryptographyNetCore.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0 GeneXusCryptographyNetCoreImpl 17.4.0 GeneXus.SecurityApi.Cryptography.Core diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusFtpsNetCore/GeneXusFtpsNetCore.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusFtpsNetCore/GeneXusFtpsNetCore.csproj index 71e11b8dc..7aebe6d39 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusFtpsNetCore/GeneXusFtpsNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusFtpsNetCore/GeneXusFtpsNetCore.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0 GeneXusFtpsNetCoreImpl 17.4.0 GeneXus.SecurityApi.Ftps.Core diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj index e5a0c4679..3ffbb4bec 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0 GeneXusJWTNetCoreImpl 17.4.0 GeneXus.SecurityApi.Jwt.Core diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusSftpNetCore/GeneXusSftpNetCore.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusSftpNetCore/GeneXusSftpNetCore.csproj index c65bd27a4..a3a002ff1 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusSftpNetCore/GeneXusSftpNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusSftpNetCore/GeneXusSftpNetCore.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0 GeneXusSftpNetCoreImpl 17.4.0 GeneXus.SecurityApi.Sftp.Core diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusXmlSignatureNetCore/GeneXusXmlSignatureNetCore.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusXmlSignatureNetCore/GeneXusXmlSignatureNetCore.csproj index 37d202758..fddff7894 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusXmlSignatureNetCore/GeneXusXmlSignatureNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusXmlSignatureNetCore/GeneXusXmlSignatureNetCore.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0 GeneXusXMLSignatureNetCoreImpl 17.4.0 GeneXus.SecurityApi.XmlSignature.Core diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/SecurityAPICommonsNetCore/SecurityAPICommonsNetCore.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/SecurityAPICommonsNetCore/SecurityAPICommonsNetCore.csproj index 387b02292..faba4af3b 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/SecurityAPICommonsNetCore/SecurityAPICommonsNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/SecurityAPICommonsNetCore/SecurityAPICommonsNetCore.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0 GeneXusSecurityAPICommonsNetCoreImpl 17.4.0 CA1031, CA1801, SYSLIB0027 diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusFtps/GeneXusFtps/FtpsClient.cs b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusFtps/GeneXusFtps/FtpsClient.cs index 99a798359..daa9b0d81 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusFtps/GeneXusFtps/FtpsClient.cs +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusFtps/GeneXusFtps/FtpsClient.cs @@ -353,6 +353,7 @@ private FtpDataType SetEncoding(FtpsOptions options) private SslProtocols SetProtocol(FtpsOptions options) { +#pragma warning disable SYSLIB0039 // Type or member is obsolete #pragma warning disable CA5397 // Do not use deprecated SslProtocols values switch (options.GetFtpsProtocol()) { @@ -372,6 +373,7 @@ private SslProtocols SetProtocol(FtpsOptions options) return SslProtocols.Tls; } #pragma warning restore CA5397 // Do not use deprecated SslProtocols values +#pragma warning restore SYSLIB0039 // Type or member is obsolete } private bool IsSameDir(String path1, String path2) diff --git a/dotnet/src/extensions/SecurityAPI/test/dotnetcore/SecurityAPITestNetCore/SecurityAPITestNetCore.csproj b/dotnet/src/extensions/SecurityAPI/test/dotnetcore/SecurityAPITestNetCore/SecurityAPITestNetCore.csproj index c95d421fe..afda7fe55 100644 --- a/dotnet/src/extensions/SecurityAPI/test/dotnetcore/SecurityAPITestNetCore/SecurityAPITestNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/test/dotnetcore/SecurityAPITestNetCore/SecurityAPITestNetCore.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0 false CS0618,CA1707 false diff --git a/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/SecurityAPICommons/commons/SecurityAPITestObject.cs b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/SecurityAPICommons/commons/SecurityAPITestObject.cs index 0b058627b..1c30ff47a 100644 --- a/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/SecurityAPICommons/commons/SecurityAPITestObject.cs +++ b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/SecurityAPICommons/commons/SecurityAPITestObject.cs @@ -29,7 +29,9 @@ public string TestContextParameter(string key) { static string GetStartupDirectory() { +#pragma warning disable SYSLIB0044 string dir = Assembly.GetCallingAssembly().GetName().CodeBase; +#pragma warning restore SYSLIB0044 Uri uri = new Uri(dir); return Path.GetDirectoryName(uri.LocalPath); } diff --git a/dotnet/src/extensions/mocking/test/TestMockDBAccess/TestMockDBAccess.csproj b/dotnet/src/extensions/mocking/test/TestMockDBAccess/TestMockDBAccess.csproj index 58c2e3d50..94877d3c3 100644 --- a/dotnet/src/extensions/mocking/test/TestMockDBAccess/TestMockDBAccess.csproj +++ b/dotnet/src/extensions/mocking/test/TestMockDBAccess/TestMockDBAccess.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0 false diff --git a/dotnet/test/DotNetCoreAttackMitigationTest/DotNetCoreAttackMitigationTest.csproj b/dotnet/test/DotNetCoreAttackMitigationTest/DotNetCoreAttackMitigationTest.csproj index 659f45156..fa3f01cd2 100644 --- a/dotnet/test/DotNetCoreAttackMitigationTest/DotNetCoreAttackMitigationTest.csproj +++ b/dotnet/test/DotNetCoreAttackMitigationTest/DotNetCoreAttackMitigationTest.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0 CS8032;1701;1702;NU1701 Major diff --git a/dotnet/test/DotNetCoreOpenTelemetryTest/DotNetCoreOpenTelemetryTest.csproj b/dotnet/test/DotNetCoreOpenTelemetryTest/DotNetCoreOpenTelemetryTest.csproj index 15d8fc2c6..03f844c27 100644 --- a/dotnet/test/DotNetCoreOpenTelemetryTest/DotNetCoreOpenTelemetryTest.csproj +++ b/dotnet/test/DotNetCoreOpenTelemetryTest/DotNetCoreOpenTelemetryTest.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0 CS8032;1701;1702;NU1701 Major diff --git a/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj b/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj index 88b4efc68..aa96f1c8b 100644 --- a/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj +++ b/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0 CS8032;1701;1702;NU1701 Major diff --git a/dotnet/test/DotNetCoreUnitTest/Serialization.cs b/dotnet/test/DotNetCoreUnitTest/Serialization.cs index 79b5872d5..e4b8fb591 100644 --- a/dotnet/test/DotNetCoreUnitTest/Serialization.cs +++ b/dotnet/test/DotNetCoreUnitTest/Serialization.cs @@ -19,15 +19,15 @@ public class CoreSerializationTest public async Task TestSessionRenew() { var httpContext = new DefaultHttpContext() { Session = new MockHttpSession() }; - var authMiddleware = new MyAuthMiddleware(next: (innerHttpContext) => Task.FromResult(0)); + var authMiddleware = new MyAuthMiddleware(); await authMiddleware.Invoke(httpContext); } [Fact] public async Task TestSessionCookieContainer() { - var httpContext = new DefaultHttpContext() { Session = new MockHttpSession() }; - var authMiddleware = new MyAuthMiddleware(next: (innerHttpContext) => Task.FromResult(0)); + DefaultHttpContext httpContext = new DefaultHttpContext() { Session = new MockHttpSession() }; + MyAuthMiddleware authMiddleware = new MyAuthMiddleware(); await authMiddleware.SessionCookieContainerSerialization(httpContext); } @@ -35,11 +35,8 @@ public async Task TestSessionCookieContainer() } public class MyAuthMiddleware { - private readonly RequestDelegate _next; - - public MyAuthMiddleware(RequestDelegate next) + public MyAuthMiddleware() { - _next = next; } public async Task SessionCookieContainerSerialization(HttpContext context) { @@ -55,7 +52,7 @@ public async Task SessionCookieContainerSerialization(HttpContext context) gxcontext.UpdateSessionCookieContainer(); container = gxcontext.GetCookieContainer(url, true); Assert.Equal(1, container.Count); - await _next(context); + await Task.CompletedTask; } public async Task Invoke(HttpContext context) @@ -76,7 +73,7 @@ public async Task Invoke(HttpContext context) throw; } Assert.Equal(InternalKeyAjaxEncryptionKey, gxcontext.ReadSessionKey(CryptoImpl.AJAX_ENCRYPTION_KEY)); - await _next(context); + await Task.CompletedTask; } } public class MockHttpSession : ISession diff --git a/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj b/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj index ee6046ce5..8dcbb4c25 100644 --- a/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj +++ b/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0 CS8032;1701;1702;NU1701 Major diff --git a/dotnet/test/DotNetPdfTest/DotNetPDFUnitTest.csproj b/dotnet/test/DotNetPdfTest/DotNetPDFUnitTest.csproj index c3f0531d3..43cbea27f 100644 --- a/dotnet/test/DotNetPdfTest/DotNetPDFUnitTest.csproj +++ b/dotnet/test/DotNetPdfTest/DotNetPDFUnitTest.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0 CS8032;1701;1702;NU1701 Major diff --git a/dotnet/test/DotNetRedisTest/DotNetRedisTest.csproj b/dotnet/test/DotNetRedisTest/DotNetRedisTest.csproj index e7a55e3de..c71055ece 100644 --- a/dotnet/test/DotNetRedisTest/DotNetRedisTest.csproj +++ b/dotnet/test/DotNetRedisTest/DotNetRedisTest.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0 diff --git a/dotnet/test/ProjectHealthTest/PackageVersionsConsistency.cs b/dotnet/test/ProjectHealthTest/PackageVersionsConsistency.cs index ad395603d..29be3c9ad 100644 --- a/dotnet/test/ProjectHealthTest/PackageVersionsConsistency.cs +++ b/dotnet/test/ProjectHealthTest/PackageVersionsConsistency.cs @@ -19,7 +19,7 @@ public class PackageVersionTest private const string PACKAGE_VERSION_ATTRIBUTE_NAME = "Version"; private const string TARGET_FRAMEWORK = "Project/PropertyGroup/TargetFramework"; private const string TARGET_FRAMEWORKS = "Project/PropertyGroup/TargetFrameworks"; - private const string NET6 = "net6.0"; + private const string NET8 = "net8.0"; private const string NET_FRAMEWORK = "net462"; private static HashSet ExcludedFromTransitiveDependenciesControl = new HashSet {"runtime"}; private static HashSet ProjectTemporaryExcludedFromDependenciesControl = new HashSet { "GeneXus.Deploy.AzureFunctions.Handlers.csproj", "AzureFunctionsTest.csproj" }; @@ -35,7 +35,7 @@ public class PackageVersionTest [Fact] public void TestPackageVersionConsistencyAcrossNETProjectsAndTransitives() { - TestPackageVersionConsistencyAcrossProjects(NET6, true); + TestPackageVersionConsistencyAcrossProjects(NET8, true); } /// /// Tests that all referenced packages have the same version by doing: @@ -47,7 +47,7 @@ public void TestPackageVersionConsistencyAcrossNETProjectsAndTransitives() [Fact] public void TestPackageVersionConsistencyAcrossNETProjects() { - TestPackageVersionConsistencyAcrossProjects(NET6, false); + TestPackageVersionConsistencyAcrossProjects(NET8, false); } [Fact] public void TestPackageVersionConsistencyAcrossNETFrameworkProjects() @@ -100,9 +100,9 @@ private void TestPackageVersionConsistencyAcrossProjects(string targetFramework, { XmlAttribute condition = packageNode.ParentNode.Attributes["Condition"]; if (condition != null) { - if (targetFramework == NET6 && condition.Value.Contains($"=='{NET_FRAMEWORK}'", StringComparison.OrdinalIgnoreCase)) + if (targetFramework == NET8 && condition.Value.Contains($"=='{NET_FRAMEWORK}'", StringComparison.OrdinalIgnoreCase)) continue; - else if (targetFramework == NET_FRAMEWORK && condition.Value.Contains($"=='{NET6}'", StringComparison.OrdinalIgnoreCase)) + else if (targetFramework == NET_FRAMEWORK && condition.Value.Contains($"=='{NET8}'", StringComparison.OrdinalIgnoreCase)) { continue; } diff --git a/dotnet/test/ProjectHealthTest/ProjectHealthTest.csproj b/dotnet/test/ProjectHealthTest/ProjectHealthTest.csproj index 011bd7245..a7952c809 100644 --- a/dotnet/test/ProjectHealthTest/ProjectHealthTest.csproj +++ b/dotnet/test/ProjectHealthTest/ProjectHealthTest.csproj @@ -1,13 +1,13 @@ - net6.0 + net6.0;net8.0 - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/dotnet/test/TestApp/TestApp.csproj b/dotnet/test/TestApp/TestApp.csproj index 6a0556c0d..59dd234ee 100644 --- a/dotnet/test/TestApp/TestApp.csproj +++ b/dotnet/test/TestApp/TestApp.csproj @@ -2,7 +2,7 @@ Library - net6.0 + net6.0;net8.0 enable enable $(ProjectDir)..\DotNetCoreOpenTelemetryTest\bin\$(Configuration) diff --git a/global.json b/global.json new file mode 100644 index 000000000..20dc84cd1 --- /dev/null +++ b/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "allowPrerelease": true + } +} \ No newline at end of file From 570544a42b4bbc458d6c78b8aa229234e3dccb2f Mon Sep 17 00:00:00 2001 From: Claudia Murialdo Date: Tue, 7 Nov 2023 09:37:02 -0300 Subject: [PATCH 060/164] Fix merge error Invalid combination of TargetFramework and AzureFunctionsVersion is set. [C:\Dev\DotNetClassesMast er\dotnet\src\extensions\Azure\Handlers\GeneXus.Deploy.AzureFunctions.Handlers.csproj --- .../Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj b/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj index ee77a03ba..609e2d6c2 100644 --- a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj +++ b/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj @@ -63,8 +63,8 @@ - - + + From 503e144fb3393f1cbd222c02e88c2ee7e4bea18e Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Thu, 9 Nov 2023 15:57:49 -0300 Subject: [PATCH 061/164] The 'GetURL' method of the external file did not take into consideration the URL (which has specific attributes such as expiration time) (#898) --- dotnet/src/dotnetframework/GxClasses/Domain/GXFileIO.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GXFileIO.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GXFileIO.cs index 09aeea02c..b9de5a5dc 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GXFileIO.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GXFileIO.cs @@ -585,7 +585,12 @@ public string AbsolutePath private string URL { get { - return _provider == null ? String.Empty : _provider.GetUrl(_name, _fileTypeAtt, 0); + if (_provider == null) + return string.Empty; + else if (!string.IsNullOrEmpty(_url)) + return _url; + else + return _provider.GetUrl(_name, _fileTypeAtt, 0); } } From a97a90a75c81c2ece2393231ea8484327a42de13 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Fri, 10 Nov 2023 16:14:34 -0300 Subject: [PATCH 062/164] Remove and organize using directives. (#903) Eliminate any unnecessary using statements, specifically the log4net ones that complement PR #871. --- .../Middleware/GXBCRestService.cs | 10 ++++---- .../GxClasses.Web/Middleware/GXRouting.cs | 3 --- .../Middleware/HandlerFactory.cs | 16 ++++++------ .../Notifications/WebSocket/WSHandler.cs | 15 ++++++----- .../GxClasses/Helpers/GXGeographyCore.cs | 1 - .../OpenTelemetry/OpenTelemetryService.cs | 1 - .../GxClasses/Services/ServiceSettings.cs | 1 - .../Services/Session/GXSessionFactory.cs | 1 - .../dotnetcore/GxNetCoreStartup/CsrfHelper.cs | 1 - .../dotnetcore/GxNetCoreStartup/Startup.cs | 4 --- .../GxPdfReportsCS/PDFReportItext8.cs | 2 -- .../Messaging/GXAmazonSQS/AWSQueue.cs | 5 ++-- .../GXAzureEventGrid/AzureEventGrid.cs | 1 - .../Messaging/GXAzureQueue/AzureQueue.cs | 2 -- .../GXAzureServiceBus/AzureServiceBus.cs | 1 - .../GXEventRouter/EventRouterBase.cs | 1 - .../GXEventRouter/EventRouterProvider.cs | 1 - .../GXEventRouter/EventRouterProviderBase.cs | 2 -- .../GXMessageBroker/MessageBrokerBase.cs | 1 - .../GXMessageBroker/MessageBrokerProvider.cs | 1 - .../Messaging/GXMessageBroker/MessageQueue.cs | 1 - .../GXMessageBroker/ServiceSettings.cs | 1 - .../Messaging/GXQueue/MessageQueueProvider.cs | 1 - .../Providers/Messaging/GXQueue/QueueBase.cs | 5 ---- .../Messaging/GXQueue/SimpleMessageQueue.cs | 3 --- .../LightstepProvider.cs | 5 +--- .../GxClasses.Win/Process/CommandLine.cs | 3 +-- .../Configuration/ExternalStorage.cs | 1 - .../Configuration/LogConfiguration.cs | 3 +-- .../GxClasses/Core/GXApplication.cs | 2 -- .../dotnetframework/GxClasses/Core/GXUtils.cs | 1 - .../GxClasses/Core/GXUtilsCommon.cs | 3 --- .../GxClasses/Core/Web/HttpAjaxContext.cs | 3 --- .../GxClasses/Cryptography/GXHashing.cs | 6 +---- .../GxClasses/Data/GXDataADO.cs | 21 +++++++--------- .../GxClasses/Data/GXDataDb2.cs | 1 - .../GxClasses/Data/GXDataDb2400.cs | 1 - .../GxClasses/Data/GXDataHana.cs | 1 - .../GxClasses/Data/GXDataInformix.cs | 8 +++--- .../GxClasses/Data/GXDataMysqlConnector.cs | 2 -- .../GxClasses/Data/GXDataMysqlDriverCS.cs | 9 +++---- .../GxClasses/Data/GXDataNTier.cs | 11 ++++---- .../GxClasses/Data/GXDataNTierADO.cs | 15 ++++++----- .../GxClasses/Data/GXDataNTierService.cs | 17 +++---------- .../GxClasses/Data/GXDataOracle.cs | 1 - .../GxClasses/Data/GXDataPostgreSQL.cs | 1 - .../GxClasses/Data/GXDataSqlite.cs | 1 - .../GxClasses/Diagnostics/GXDebugManager.cs | 3 +-- .../GxClasses/Dialog/IDialog.cs | 5 ++-- .../GxClasses/Dialog/IProcess.cs | 1 - .../GxClasses/Domain/ExpressionEvaluator.cs | 6 ++--- .../GxClasses/Domain/GXFileIO.cs | 1 - .../GxClasses/Domain/GXGeolocation.cs | 4 +-- .../GxClasses/Domain/GXLDAP.cs | 1 - .../GxClasses/Domain/GXXmlReadWrite.cs | 10 +++----- .../GxClasses/Domain/GxCollections.cs | 25 +++++++++---------- .../GxClasses/Domain/GxGenericCollections.cs | 8 +++--- .../GxClasses/Domain/GxHttpClient.cs | 1 - .../GxClasses/Domain/GxMessaging.cs | 1 - .../GxClasses/Domain/GxSession.cs | 5 +--- .../GxClasses/Domain/SD/SDApis.cs | 6 +---- .../GxClasses/Helpers/GXFileWatcher.cs | 2 -- .../GxClasses/Helpers/GXMetadata.cs | 1 - .../GxClasses/Helpers/GXRes.cs | 1 - .../GxClasses/Helpers/GXRestUtils.cs | 1 - .../GxClasses/Helpers/GXUtilsGeospatial.cs | 12 ++++----- .../GxClasses/Helpers/HttpHelper.cs | 1 - .../GxClasses/Helpers/JSONHelper.cs | 3 --- .../GxClasses/Helpers/ThemeHelper.cs | 5 ++-- .../GxClasses/Management/GXManagement.cs | 6 ++--- .../GxClasses/Management/GXPerformance.cs | 11 ++++---- .../GxClasses/Middleware/GXHttp.cs | 3 --- .../GxClasses/Middleware/GXHttpModules.cs | 21 ++++++++-------- .../GxClasses/Middleware/GXHttpServices.cs | 10 -------- .../GxClasses/Middleware/HandlerFactory.cs | 17 ++++++------- .../GxClasses/Model/GXBaseObject.cs | 1 - .../GxClasses/Model/GXSilentTrn.cs | 2 -- .../GxClasses/Model/GXWebProcedure.cs | 5 ---- .../GxClasses/Model/GxMockProvider.cs | 1 - .../dotnetframework/GxClasses/Model/gxproc.cs | 1 - .../WebSocket/GXWebSocketFactory.cs | 1 - .../GxClasses/Printer/GxPrinter.cs | 22 ++++++++-------- .../GxClasses/Reorg/GXReorg.cs | 17 ++++++------- .../GxClasses/Security/GxSecurityProvider.cs | 7 ++---- .../GxClasses/Security/WebSecurity.cs | 3 +-- .../GxClasses/Services/Caching/GxCache.cs | 3 +-- .../GxClasses/Services/GXRestServices.cs | 4 --- .../GxClasses/Services/GxRestWrapper.cs | 2 -- .../Services/Storage/ExternalProviderBase.cs | 1 - .../GxClasses/View/GXWebControls.cs | 5 +--- .../GXDataInitialization.cs | 14 ++++------- .../dotnetframework/GxExcel/GxExcelEPPlus.cs | 3 +-- .../src/dotnetframework/GxExcel/GxExcelI.cs | 8 +++--- .../dotnetframework/GxExcel/GxExcelLite.cs | 4 +-- .../GxMail/Exchange/ExchangeSession.cs | 5 ++-- .../GxMail/Exchange/Service.cs | 3 +-- .../GxMail/Exchange/TraceListener.cs | 7 +----- .../dotnetframework/GxMail/GXMailSession.cs | 3 +-- .../dotnetframework/GxMail/GXPOP3Session.cs | 5 ++-- .../dotnetframework/GxMail/GXSMTPSession.cs | 8 +++--- .../src/dotnetframework/GxMail/MAPISession.cs | 3 +-- .../src/dotnetframework/GxMail/MailMessage.cs | 7 +++--- .../GxMail/Mentalis/RFC822EndReader.cs | 1 - .../dotnetframework/GxMail/OutlookSession.cs | 6 ++--- .../src/dotnetframework/GxMail/POP3Session.cs | 12 ++++----- .../GxMail/POP3SessionOpenPop.cs | 13 +++++----- .../src/dotnetframework/GxMail/Pop3MailKit.cs | 7 +++--- .../dotnetframework/GxMail/Pop3SessionBase.cs | 1 - .../dotnetframework/GxMail/SMTP/SmtpHelper.cs | 4 +-- .../dotnetframework/GxMail/SMTPMailClient.cs | 7 +++--- .../src/dotnetframework/GxMail/SMTPMailKit.cs | 5 ++-- .../src/dotnetframework/GxMail/SMTPSession.cs | 15 ++++++----- .../GxOffice/ExcelSpreadsheetGXWrapper.cs | 1 - .../GxOffice/poi/xssf/ExcelCells.cs | 1 - .../GxPdfReportsCS/PDFReportCommon.cs | 25 ++++++++----------- .../GxPdfReportsCS/PDFReportItext4.cs | 1 - .../GxPdfReportsCS/PdfReportInterface.cs | 1 - .../GxSearch/DocumentHandler.cs | 16 +++++------- .../src/dotnetframework/GxSearch/Indexer.cs | 17 +++---------- .../src/dotnetframework/GxSearch/Searcher.cs | 14 +++-------- .../src/dotnetframework/GxSearch/Settings.cs | 2 -- .../dotnetframework/GxSearch/SpellChecker.cs | 3 --- .../dotnetframework/GxWebSocket/WSHandler.cs | 1 - .../StoreManager/Store/StoreManager.cs | 8 ++---- .../Providers/Cache/GxRedis/GxRedis.cs | 10 ++------ .../Storage/GXAmazonS3/ExternalProviderS3.cs | 10 +++----- .../HttpHandler/GXHttpAzureContextAccessor.cs | 2 -- 127 files changed, 222 insertions(+), 474 deletions(-) diff --git a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXBCRestService.cs b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXBCRestService.cs index 4b603f65b..e93c59ac1 100644 --- a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXBCRestService.cs +++ b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXBCRestService.cs @@ -43,10 +43,10 @@ public override Task Post() bool gxinsertorupdate = IsRestParameter(INSERT_OR_UPDATE_PARAMETER); GxSilentTrnSdt entity = (GxSilentTrnSdt)Activator.CreateInstance(_worker.GetType(), new Object[] { _gxContext }); - var entity_interface = MakeRestType(entity, false); + object entity_interface = MakeRestType(entity, false); entity_interface = ReadRequestBodySDTObj(entity_interface.GetType()); - var worker_interface = MakeRestType(_worker, false); + object worker_interface = MakeRestType(_worker, false); worker_interface.GetType().GetMethod("CopyFrom").Invoke(worker_interface, new object[] { entity_interface }); if (gxcheck) @@ -191,12 +191,12 @@ public override Task Put(object parameters) { bool gxcheck = IsRestParameter(CHECK_PARAMETER); GxSilentTrnSdt entity = (GxSilentTrnSdt)Activator.CreateInstance(_worker.GetType(), new Object[] { _gxContext }); - var entity_interface = MakeRestType(entity, false); + object entity_interface = MakeRestType(entity, false); entity_interface = ReadRequestBodySDTObj(entity_interface.GetType()); string entityHash = entity_interface.GetType().GetProperty("Hash").GetValue(entity_interface) as string; ReflectionHelper.CallBCMethod(_worker, LOAD_METHOD, key); - var worker_interface = MakeRestType(_worker, false); + object worker_interface = MakeRestType(_worker, false); string currentHash = worker_interface.GetType().GetProperty("Hash").GetValue(worker_interface) as string; if (entityHash == currentHash) { @@ -249,7 +249,7 @@ private object ReadRequestBodySDTObj(Type type) { using (var reader = new StreamReader(_httpContext.Request.Body)) { - var sdtData = reader.ReadToEnd(); + string sdtData = reader.ReadToEnd(); using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(sdtData))) { DataContractJsonSerializer serializer = new DataContractJsonSerializer(type); diff --git a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs index f6d88c57c..abdb7022f 100644 --- a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs +++ b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs @@ -15,13 +15,10 @@ using GeneXus.Http; using GeneXus.HttpHandlerFactory; using GeneXus.Metadata; -using GeneXus.Procedure; using GeneXus.Utils; -using log4net; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Net.Http.Headers; namespace GxClasses.Web.Middleware { diff --git a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/HandlerFactory.cs b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/HandlerFactory.cs index 5296ca8dd..d9eb0b14a 100644 --- a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/HandlerFactory.cs +++ b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/HandlerFactory.cs @@ -1,17 +1,15 @@ using System; +using System.Collections.Generic; +using System.IO; +using System.Net; using System.Reflection; +using System.Threading.Tasks; +using GeneXus.Application; using GeneXus.Configuration; -using log4net; +using GeneXus.Http; +using GeneXus.Mime; using GeneXus.Utils; using Microsoft.AspNetCore.Http; -using System.Threading.Tasks; -using Microsoft.Extensions.Options; -using System.Net; -using GeneXus.Mime; -using GeneXus.Http; -using System.Collections.Generic; -using GeneXus.Application; -using System.IO; namespace GeneXus.HttpHandlerFactory { diff --git a/dotnet/src/dotnetcore/GxClasses.Web/Notifications/WebSocket/WSHandler.cs b/dotnet/src/dotnetcore/GxClasses.Web/Notifications/WebSocket/WSHandler.cs index 92f15fc43..eea674266 100644 --- a/dotnet/src/dotnetcore/GxClasses.Web/Notifications/WebSocket/WSHandler.cs +++ b/dotnet/src/dotnetcore/GxClasses.Web/Notifications/WebSocket/WSHandler.cs @@ -1,11 +1,3 @@ -using GeneXus.Configuration; -using GeneXus.Metadata; -using GeneXus.Notifications.WebSocket; -using GeneXus.Procedure; -using GeneXus.Services; -using GeneXus.Utils; -using Jayrock.Json; -using log4net; using System; using System.Collections.Generic; using System.Linq; @@ -13,6 +5,13 @@ using System.Text; using System.Threading; using System.Threading.Tasks; +using GeneXus.Configuration; +using GeneXus.Metadata; +using GeneXus.Notifications.WebSocket; +using GeneXus.Procedure; +using GeneXus.Services; +using GeneXus.Utils; +using Jayrock.Json; namespace GeneXus.Http.WebSocket { diff --git a/dotnet/src/dotnetcore/GxClasses/Helpers/GXGeographyCore.cs b/dotnet/src/dotnetcore/GxClasses/Helpers/GXGeographyCore.cs index e33b0802d..80d80a9e7 100644 --- a/dotnet/src/dotnetcore/GxClasses/Helpers/GXGeographyCore.cs +++ b/dotnet/src/dotnetcore/GxClasses/Helpers/GXGeographyCore.cs @@ -4,7 +4,6 @@ using System.Runtime.Serialization; using Jayrock.Json; using GeographicLib; -using log4net; using NetTopologySuite.Geometries; using NetTopologySuite.IO; diff --git a/dotnet/src/dotnetcore/GxClasses/Services/OpenTelemetry/OpenTelemetryService.cs b/dotnet/src/dotnetcore/GxClasses/Services/OpenTelemetry/OpenTelemetryService.cs index 9e17ad7ce..3c8cacf39 100644 --- a/dotnet/src/dotnetcore/GxClasses/Services/OpenTelemetry/OpenTelemetryService.cs +++ b/dotnet/src/dotnetcore/GxClasses/Services/OpenTelemetry/OpenTelemetryService.cs @@ -1,6 +1,5 @@ using System; using GxClasses.Helpers; -using log4net; namespace GeneXus.Services.OpenTelemetry { diff --git a/dotnet/src/dotnetcore/GxClasses/Services/ServiceSettings.cs b/dotnet/src/dotnetcore/GxClasses/Services/ServiceSettings.cs index 05c398a7e..a9ab19878 100644 --- a/dotnet/src/dotnetcore/GxClasses/Services/ServiceSettings.cs +++ b/dotnet/src/dotnetcore/GxClasses/Services/ServiceSettings.cs @@ -1,6 +1,5 @@ using System; using GeneXus.Encryption; -using log4net; namespace GeneXus.Services.Common { diff --git a/dotnet/src/dotnetcore/GxClasses/Services/Session/GXSessionFactory.cs b/dotnet/src/dotnetcore/GxClasses/Services/Session/GXSessionFactory.cs index 022d21373..79a8b5827 100644 --- a/dotnet/src/dotnetcore/GxClasses/Services/Session/GXSessionFactory.cs +++ b/dotnet/src/dotnetcore/GxClasses/Services/Session/GXSessionFactory.cs @@ -5,7 +5,6 @@ using GeneXus.Data.ADO; using GeneXus.Encryption; using GxClasses.Helpers; -using log4net; namespace GeneXus.Services { diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/CsrfHelper.cs b/dotnet/src/dotnetcore/GxNetCoreStartup/CsrfHelper.cs index 4f6c15b71..2306f028e 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/CsrfHelper.cs +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/CsrfHelper.cs @@ -4,7 +4,6 @@ using System.Threading.Tasks; using GeneXus.Configuration; using GeneXus.Http; -using log4net; using Microsoft.AspNetCore.Antiforgery; using Microsoft.AspNetCore.Http; namespace GeneXus.Application diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs index fff6d6c6b..9a0116a6f 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs @@ -3,8 +3,6 @@ using System.IO; using System.Net; using System.Threading.Tasks; -using Azure.Identity; -using Azure.Monitor.OpenTelemetry.Exporter; using GeneXus.Configuration; using GeneXus.Http; using GeneXus.HttpHandlerFactory; @@ -29,8 +27,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Logging; -using OpenTelemetry.Logs; -using OpenTelemetry.Resources; using StackExchange.Redis; namespace GeneXus.Application diff --git a/dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportItext8.cs b/dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportItext8.cs index 04cda142a..bad1d5e68 100644 --- a/dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportItext8.cs +++ b/dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportItext8.cs @@ -24,9 +24,7 @@ using iText.Layout.Font; using iText.Layout.Layout; using iText.Layout.Properties; -using iText.Layout.Renderer; using iText.Layout.Splitting; -using log4net; using Path = System.IO.Path; namespace GeneXus.Printer diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs index 071ea69fc..47f31e184 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Reflection; +using System.Threading.Tasks; using Amazon; using Amazon.Runtime; using Amazon.SQS; @@ -7,9 +9,6 @@ using GeneXus.Messaging.Common; using GeneXus.Services; using GeneXus.Utils; -using log4net; -using System.Threading.Tasks; -using System.Reflection; namespace GeneXus.Messaging.Queue { diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/AzureEventGrid.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/AzureEventGrid.cs index f69a69466..821a7242a 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/AzureEventGrid.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/AzureEventGrid.cs @@ -10,7 +10,6 @@ using GeneXus.Messaging.Common; using GeneXus.Services; using GeneXus.Utils; -using log4net; namespace GeneXus.Messaging.GXAzureEventGrid { diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs index 519dce15a..ac8fb4c69 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs @@ -7,8 +7,6 @@ using GeneXus.Messaging.Common; using GeneXus.Services; using GeneXus.Utils; -using log4net; -using Microsoft.Extensions.Logging; namespace GeneXus.Messaging.Queue { diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/AzureServiceBus.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/AzureServiceBus.cs index 92e06e744..7981f96db 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/AzureServiceBus.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/AzureServiceBus.cs @@ -9,7 +9,6 @@ using GeneXus.Messaging.Common; using GeneXus.Services; using GeneXus.Utils; -using log4net; namespace GeneXus.Messaging.GXAzureServiceBus { diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterBase.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterBase.cs index 5b9e802fa..fb4d42cf5 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterBase.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterBase.cs @@ -1,6 +1,5 @@ using System; using GeneXus.Services; -using log4net; namespace GeneXus.Messaging.Common { diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterProvider.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterProvider.cs index f635107ec..a9cf3b0e7 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterProvider.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterProvider.cs @@ -4,7 +4,6 @@ using GeneXus.Services; using GeneXus.Utils; using GxClasses.Helpers; -using log4net; namespace GeneXus.Messaging.Common { diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterProviderBase.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterProviderBase.cs index 7514c6b04..25acbc4cf 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterProviderBase.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/EventRouterProviderBase.cs @@ -1,12 +1,10 @@ using System; using System.Collections; using System.Collections.Generic; -using System.IO; using System.Reflection; using GeneXus.Services; using GeneXus.Utils; using GxClasses.Helpers; -using log4net; namespace GeneXus.Messaging.Common { diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageBrokerBase.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageBrokerBase.cs index 7fbd6a18d..de6c1bece 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageBrokerBase.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageBrokerBase.cs @@ -1,6 +1,5 @@ using System; using GeneXus.Services; -using log4net; namespace GeneXus.Messaging.Common { diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageBrokerProvider.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageBrokerProvider.cs index 433a9a211..69179faa5 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageBrokerProvider.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageBrokerProvider.cs @@ -4,7 +4,6 @@ using GeneXus.Services; using GeneXus.Utils; using GxClasses.Helpers; -using log4net; namespace GeneXus.Messaging.Common { diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageQueue.cs index 2044de050..13f6c7702 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/MessageQueue.cs @@ -6,7 +6,6 @@ using GeneXus.Services; using GeneXus.Utils; using GxClasses.Helpers; -using log4net; namespace GeneXus.Messaging.Common { diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/ServiceSettings.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/ServiceSettings.cs index d29c55ab0..f718b6c4e 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/ServiceSettings.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/ServiceSettings.cs @@ -1,7 +1,6 @@ using System; using GeneXus.Encryption; using GeneXus.Services; -using log4net; namespace GeneXus.Messaging.Common { diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs index 93a4ba066..cf6077c65 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/MessageQueueProvider.cs @@ -4,7 +4,6 @@ using GeneXus.Services; using GeneXus.Utils; using GxClasses.Helpers; -using log4net; namespace GeneXus.Messaging.Common { diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/QueueBase.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/QueueBase.cs index b43c47b1b..6d0635494 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/QueueBase.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/QueueBase.cs @@ -1,10 +1,5 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using GeneXus.Services; -using log4net; namespace GeneXus.Messaging.Common { diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs index dd5d35031..18739ffda 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/SimpleMessageQueue.cs @@ -1,14 +1,11 @@ using System; using System.Collections; using System.Collections.Generic; -using System.IO; using System.Reflection; using System.Text; -using GeneXus.Application; using GeneXus.Services; using GeneXus.Utils; using GxClasses.Helpers; -using log4net; namespace GeneXus.Messaging.Common { diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryLightStep/LightstepProvider.cs b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryLightStep/LightstepProvider.cs index 8b4f5195a..8d251d1c8 100644 --- a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryLightStep/LightstepProvider.cs +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryLightStep/LightstepProvider.cs @@ -1,12 +1,9 @@ using System; +using GeneXus.Services; using GeneXus.Services.OpenTelemetry; using Microsoft.Extensions.DependencyInjection; -using OpenTelemetry; using OpenTelemetry.Trace; -using OpenTelemetry.Resources; -using log4net; -using GeneXus.Services; namespace GeneXus.OpenTelemetry.Lightstep { diff --git a/dotnet/src/dotnetframework/GxClasses.Win/Process/CommandLine.cs b/dotnet/src/dotnetframework/GxClasses.Win/Process/CommandLine.cs index fa2a5a55a..b43620759 100644 --- a/dotnet/src/dotnetframework/GxClasses.Win/Process/CommandLine.cs +++ b/dotnet/src/dotnetframework/GxClasses.Win/Process/CommandLine.cs @@ -1,8 +1,7 @@ -using GeneXus.Application; -using log4net; using System; using System.Diagnostics; using System.IO; +using GeneXus.Application; namespace GeneXus.Utils { diff --git a/dotnet/src/dotnetframework/GxClasses/Configuration/ExternalStorage.cs b/dotnet/src/dotnetframework/GxClasses/Configuration/ExternalStorage.cs index 41112ccd6..d30bdc160 100644 --- a/dotnet/src/dotnetframework/GxClasses/Configuration/ExternalStorage.cs +++ b/dotnet/src/dotnetframework/GxClasses/Configuration/ExternalStorage.cs @@ -3,7 +3,6 @@ using GeneXus.Attributes; using GeneXus.Utils; using GeneXus.Encryption; -using log4net; #if NETCORE using GxClasses.Helpers; #endif diff --git a/dotnet/src/dotnetframework/GxClasses/Configuration/LogConfiguration.cs b/dotnet/src/dotnetframework/GxClasses/Configuration/LogConfiguration.cs index 6a047d681..69428b857 100644 --- a/dotnet/src/dotnetframework/GxClasses/Configuration/LogConfiguration.cs +++ b/dotnet/src/dotnetframework/GxClasses/Configuration/LogConfiguration.cs @@ -1,11 +1,10 @@ using System; +using System.Linq; using log4net; using log4net.Appender; using log4net.Core; using log4net.Repository; using log4net.Repository.Hierarchy; -using System.Linq; -using log4net.Layout; namespace GeneXus.Configuration { diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs index 06c6000b2..08d94ef70 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs @@ -21,7 +21,6 @@ namespace GeneXus.Application #endif using GeneXus.Configuration; using GeneXus.Metadata; - using log4net; using Jayrock.Json; using GeneXus.Http; using System.Collections.Specialized; @@ -44,7 +43,6 @@ namespace GeneXus.Application using Microsoft.AspNetCore.Http.Features; #endif using NodaTime; - using NodaTime.TimeZones; using System.Threading; using System.Security.Claims; using System.Security; diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXUtils.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXUtils.cs index c5c616f58..db1162f17 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXUtils.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXUtils.cs @@ -11,7 +11,6 @@ namespace GeneXus.Utils using Cache; using GeneXus.Application; using GeneXus.Services; - using log4net; using TZ4Net; public class GxMail diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs index 6235c5785..d4bb6a16d 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs @@ -1,6 +1,5 @@ using GeneXus.Application; using GeneXus.Configuration; -using log4net; using System; using System.Collections; using System.Diagnostics; @@ -20,7 +19,6 @@ using System.Net; #endif using NodaTime; -using NodaTime.TimeZones; using NUglify; using NUglify.Html; using GeneXus.Web.Security; @@ -45,7 +43,6 @@ using GeneXus.Services; using GeneXus.Http; using System.Security; -using System.Threading.Tasks; using System.Drawing.Imaging; using System.Net.Http.Headers; using Image = System.Drawing.Image; diff --git a/dotnet/src/dotnetframework/GxClasses/Core/Web/HttpAjaxContext.cs b/dotnet/src/dotnetframework/GxClasses/Core/Web/HttpAjaxContext.cs index 2180ad8a4..4eebfe44d 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/Web/HttpAjaxContext.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/Web/HttpAjaxContext.cs @@ -1,7 +1,6 @@ namespace GeneXus.Http { using System; - using System.IO; using Jayrock.Json; using System.Web; using GeneXus.Application; @@ -17,9 +16,7 @@ namespace GeneXus.Http #else using Microsoft.AspNetCore.Http; #endif - using System.Diagnostics; using GeneXus.Configuration; - using log4net; public interface IHttpAjaxContext { diff --git a/dotnet/src/dotnetframework/GxClasses/Cryptography/GXHashing.cs b/dotnet/src/dotnetframework/GxClasses/Cryptography/GXHashing.cs index 59ee779a7..f3194e0cf 100644 --- a/dotnet/src/dotnetframework/GxClasses/Cryptography/GXHashing.cs +++ b/dotnet/src/dotnetframework/GxClasses/Cryptography/GXHashing.cs @@ -1,11 +1,7 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Text; -using System.Security.Cryptography; -using log4net; -using GeneXus.Cryptography.Hashing; using GeneXus.Cryptography.CryptoException; +using GeneXus.Cryptography.Hashing; namespace GeneXus.Cryptography { diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataADO.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataADO.cs index 4e72f295f..d907f94e7 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataADO.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataADO.cs @@ -1,26 +1,23 @@ +using System; +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.IO; +using System.Reflection; +using System.Threading; using GeneXus.Application; using GeneXus.Cache; using GeneXus.Configuration; using GeneXus.Data.NTier.ADO; -using GeneXus.Diagnostics; using GeneXus.Management; using GeneXus.Reorg; using GeneXus.Services; using GeneXus.Utils; using GeneXus.XML; using GxClasses.Helpers; -using log4net; -using log4net.Core; -using System; -using System.Collections; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Data; -using System.Data.Common; -using System.IO; -using System.Reflection; -using System.Threading; using TZ4Net; namespace GeneXus.Data.ADO { diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2.cs index ea570daad..9bc3da634 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2.cs @@ -9,7 +9,6 @@ using GeneXus.Metadata; using GeneXus.Utils; using GxClasses.Helpers; -using log4net; namespace GeneXus.Data { diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2400.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2400.cs index 6c2b40478..dddf16097 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2400.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2400.cs @@ -6,7 +6,6 @@ #if !NETCORE using Microsoft.HostIntegration.MsDb2Client; #endif -using log4net; using GeneXus.Application; using GeneXus.Cache; using GeneXus.Configuration; diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataHana.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataHana.cs index ad2cf1337..256bd7994 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataHana.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataHana.cs @@ -8,7 +8,6 @@ using GeneXus.Metadata; using GeneXus.Utils; using GxClasses.Helpers; -using log4net; namespace GeneXus.Data { diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataInformix.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataInformix.cs index 6b326f74b..1355285af 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataInformix.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataInformix.cs @@ -2,19 +2,17 @@ using System.Collections; using System.Data; using System.Data.Common; +using System.Globalization; +using System.IO; using System.Reflection; using System.Text; using System.Threading; - -using log4net; using GeneXus.Application; using GeneXus.Cache; using GeneXus.Configuration; -using GeneXus.Utils; -using System.Globalization; using GeneXus.Metadata; +using GeneXus.Utils; using GxClasses.Helpers; -using System.IO; namespace GeneXus.Data { diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlConnector.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlConnector.cs index 5d819d439..a804ae6c3 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlConnector.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlConnector.cs @@ -1,7 +1,6 @@ using System; using System.Data; using System.Data.Common; -using System.Linq; using System.Reflection; using System.Security; using System.Text; @@ -9,7 +8,6 @@ using GeneXus.Cache; using GeneXus.Utils; using GxClasses.Helpers; -using log4net; using MySQLCommand = MySqlConnector.MySqlCommand; using MySQLConnection = MySqlConnector.MySqlConnection; using MySQLDataAdapter = MySqlConnector.MySqlDataAdapter; diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlDriverCS.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlDriverCS.cs index df77b2082..a2688ea3b 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlDriverCS.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlDriverCS.cs @@ -1,12 +1,11 @@ -using GeneXus.Application; -using GeneXus.Cache; -using GeneXus.Utils; -using log4net; -using MySQLDriverCS; using System; using System.Data; using System.Data.Common; using System.Text; +using GeneXus.Application; +using GeneXus.Cache; +using GeneXus.Utils; +using MySQLDriverCS; namespace GeneXus.Data { diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTier.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTier.cs index 16e1d3ba6..fca522d83 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTier.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTier.cs @@ -1,15 +1,14 @@ using System; -using GeneXus.Application; +using System.Collections.Generic; using System.Data; +using System.Text; +using GeneXus.Application; using GeneXus.Configuration; +using GeneXus.Data.ADO; using GeneXus.Data.NTier.ADO; -using GeneXus.Reorg; using GeneXus.Performance; -using log4net; -using System.Collections.Generic; -using GeneXus.Data.ADO; +using GeneXus.Reorg; using GeneXus.Utils; -using System.Text; namespace GeneXus.Data.NTier { diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierADO.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierADO.cs index d838c3c1a..94b1b7e90 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierADO.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierADO.cs @@ -1,20 +1,19 @@ using System; -using System.Data; using System.Collections; -using GeneXus.Data.ADO; -using GeneXus.Configuration; -using GeneXus.Utils; +using System.Collections.Generic; +using System.Data; using System.IO; -using log4net; +using System.Net; using GeneXus.Application; -using System.Collections.Generic; +using GeneXus.Configuration; +using GeneXus.Data.ADO; using GeneXus.Services; -using System.Net; using GeneXus.Storage; +using GeneXus.Utils; namespace GeneXus.Data.NTier.ADO { - public class GXFatErrorFieldGetter : IFieldGetter + public class GXFatErrorFieldGetter : IFieldGetter { GxCommand _gxDbCommand; public GXFatErrorFieldGetter(GxCommand gxDbCommand) diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierService.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierService.cs index 817de09bd..47b1348b5 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierService.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierService.cs @@ -1,21 +1,12 @@ -using System.Text; - using System; using System.Data; -using System.Collections; -using GeneXus.Data.ADO; -using GeneXus.Configuration; +using System.Data.Common; +using System.Text; using GeneXus.Cache; -using GeneXus.Utils; -using System.IO; -using log4net; -using GeneXus.Application; -using System.Collections.Generic; using GeneXus.Data.NTier.ADO; -using System.Reflection; -using GeneXus.Metadata; -using System.Data.Common; using GeneXus.Helpers; +using GeneXus.Metadata; +using GeneXus.Utils; namespace GeneXus.Data.NTier { diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataOracle.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataOracle.cs index 2cb65dc02..bba71de26 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataOracle.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataOracle.cs @@ -9,7 +9,6 @@ using GeneXus.Configuration; using GeneXus.Metadata; using GeneXus.Utils; -using log4net; using System.IO; #if NETCORE using GxClasses.Helpers; diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataPostgreSQL.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataPostgreSQL.cs index 02dfcaeaa..21791af2d 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataPostgreSQL.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataPostgreSQL.cs @@ -1,6 +1,5 @@ using System; using System.Text; -using log4net; using System.Data; using System.Data.Common; using GeneXus.Utils; diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataSqlite.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataSqlite.cs index b7de8e9cf..966cfe46d 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataSqlite.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataSqlite.cs @@ -1,6 +1,5 @@ using GeneXus.Cache; using GeneXus.Utils; -using log4net; using System; using System.Text; using System.Data; diff --git a/dotnet/src/dotnetframework/GxClasses/Diagnostics/GXDebugManager.cs b/dotnet/src/dotnetframework/GxClasses/Diagnostics/GXDebugManager.cs index 55d95792d..dd51e8e90 100644 --- a/dotnet/src/dotnetframework/GxClasses/Diagnostics/GXDebugManager.cs +++ b/dotnet/src/dotnetframework/GxClasses/Diagnostics/GXDebugManager.cs @@ -5,11 +5,10 @@ using System.IO; using System.Threading; using GeneXus.Application; -using log4net; namespace GeneXus.Diagnostics { - + public class GXDebugManager { public const short GXDEBUG_VERSION = 2; diff --git a/dotnet/src/dotnetframework/GxClasses/Dialog/IDialog.cs b/dotnet/src/dotnetframework/GxClasses/Dialog/IDialog.cs index dedc44ff7..9d2362692 100644 --- a/dotnet/src/dotnetframework/GxClasses/Dialog/IDialog.cs +++ b/dotnet/src/dotnetframework/GxClasses/Dialog/IDialog.cs @@ -1,6 +1,5 @@ -using ConnectionBuilder; -using log4net; using System; +using ConnectionBuilder; namespace GeneXus.Utils { @@ -36,7 +35,7 @@ public static IConnectionDialogFactory DialogFactory } catch (Exception ex) { - var strErrorMsg = $"Error loading Dialogs provider. Check if {OsProviderAssembly}.dll exists "; + string strErrorMsg = $"Error loading Dialogs provider. Check if {OsProviderAssembly}.dll exists "; GXLogging.Debug(log, strErrorMsg, ex); throw new Exception(strErrorMsg, ex); } diff --git a/dotnet/src/dotnetframework/GxClasses/Dialog/IProcess.cs b/dotnet/src/dotnetframework/GxClasses/Dialog/IProcess.cs index 04265fe3a..bc03e868b 100644 --- a/dotnet/src/dotnetframework/GxClasses/Dialog/IProcess.cs +++ b/dotnet/src/dotnetframework/GxClasses/Dialog/IProcess.cs @@ -1,4 +1,3 @@ -using log4net; using System; using System.Diagnostics; diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/ExpressionEvaluator.cs b/dotnet/src/dotnetframework/GxClasses/Domain/ExpressionEvaluator.cs index 8b6a4c4d6..faf841598 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/ExpressionEvaluator.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/ExpressionEvaluator.cs @@ -1,10 +1,8 @@ using System; -using GeneXus.Metadata; +using System.Reflection; using GeneXus.Application; using GeneXus.Configuration; -using System.Reflection; -using log4net; -using System.Collections; +using GeneXus.Metadata; namespace GeneXus.Utils { diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GXFileIO.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GXFileIO.cs index b9de5a5dc..809321a32 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GXFileIO.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GXFileIO.cs @@ -3,7 +3,6 @@ using System.Collections; using GeneXus.Utils; using GeneXus.Application; -using log4net; using System.Runtime.CompilerServices; using GeneXus.Services; using System.Collections.Generic; diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GXGeolocation.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GXGeolocation.cs index 9998431c6..e6c8e6aa2 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GXGeolocation.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GXGeolocation.cs @@ -1,11 +1,9 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; using System.Net; using System.IO; using Jayrock.Json; -using log4net; using GeneXus.Utils; using System.Globalization; using GeneXus; @@ -16,7 +14,7 @@ namespace GX { - public class GXGeolocation + public class GXGeolocation { private const String MAPS_URI = "https://maps.google.com/maps/api/"; private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GXLDAP.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GXLDAP.cs index 0ef849ae7..510b08b9d 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GXLDAP.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GXLDAP.cs @@ -2,7 +2,6 @@ using System.Collections; using System.DirectoryServices; using System.Text; -using log4net; #if NETCORE using Novell.Directory.Ldap; #endif diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs index f34142d60..ce2e02ec0 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs @@ -1,19 +1,15 @@ using System; -using System.Xml; using System.Collections; using System.Collections.Specialized; -using System.Text; -using System.Net; using System.IO; +using System.Net; +using System.Text; +using System.Xml; using System.Xml.Schema; using GeneXus.Application; using GeneXus.Http.Client; using GeneXus.Http.Server; using GeneXus.Utils; -using log4net; - -using System.Xml.Xsl; -using System.Xml.XPath; namespace GeneXus.XML { diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs index 49d38c131..e14805a46 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs @@ -1,26 +1,25 @@ namespace GeneXus.Utils { using System; - using System.Collections.Specialized; using System.Collections; + using System.Collections.Concurrent; using System.Collections.Generic; - using GeneXus.XML; - using System.Reflection; - using System.Xml.Serialization; + using System.Collections.Specialized; + using System.ComponentModel; using System.Data; - using GeneXus.Application; - using System.Text; using System.Globalization; - using Jayrock.Json; - using log4net; - using System.ComponentModel; - using System.Xml; - using System.Runtime.Serialization; using System.Linq; - using GeneXus.Http; + using System.Reflection; + using System.Runtime.Serialization; + using System.Text; + using System.Xml; + using System.Xml.Serialization; + using GeneXus.Application; using GeneXus.Configuration; + using GeneXus.Http; using GeneXus.Metadata; - using System.Collections.Concurrent; + using GeneXus.XML; + using Jayrock.Json; public class GxParameterCollection : IDataParameterCollection { diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxGenericCollections.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxGenericCollections.cs index 577126aca..657b8feaa 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxGenericCollections.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxGenericCollections.cs @@ -1,13 +1,11 @@ -using GeneXus.Application; -using GeneXus.XML; -using Jayrock.Json; -using log4net; using System; using System.Collections; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Linq; using System.Xml.Serialization; +using GeneXus.Application; +using GeneXus.XML; +using Jayrock.Json; namespace GeneXus.Utils { diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs index 0115c7b6d..0f3b40e4a 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs @@ -19,7 +19,6 @@ namespace GeneXus.Http.Client using GeneXus.Application; using GeneXus.Configuration; using GeneXus.Utils; - using log4net; #if NETCORE using Microsoft.AspNetCore.WebUtilities; #endif diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxMessaging.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxMessaging.cs index 610bc3a8c..f05a85b98 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxMessaging.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxMessaging.cs @@ -8,7 +8,6 @@ using System.Text.RegularExpressions; using GeneXus.Configuration; using GeneXus.Application; -using log4net; using System.Security; namespace GeneXus.Utils diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxSession.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxSession.cs index 2cdfddb49..af89955f3 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxSession.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxSession.cs @@ -6,16 +6,13 @@ #else using Microsoft.AspNetCore.Http; #endif -using System.Threading; using GeneXus.Utils; using GeneXus.Encryption; using GeneXus.Application; -using log4net; -using System.Collections.Generic; namespace GeneXus.Http { - public interface IGxSession + public interface IGxSession { void Set(string key, string val); void Set(string key, T val) where T:class; diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/SD/SDApis.cs b/dotnet/src/dotnetframework/GxClasses/Domain/SD/SDApis.cs index fb6daed8f..9ce156ff8 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/SD/SDApis.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/SD/SDApis.cs @@ -1,11 +1,7 @@ +using System; using GeneXus; using GeneXus.Application; using GeneXus.Data; -using GeneXus.Utils; -using log4net; -using System; -using System.Collections; -using System.Collections.Generic; namespace GX { diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXFileWatcher.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXFileWatcher.cs index 6d91dac34..df785527a 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXFileWatcher.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXFileWatcher.cs @@ -4,7 +4,6 @@ namespace GeneXus.Application using System.Collections; using System.IO; using GeneXus.Configuration; - using log4net; using System.Collections.Generic; using System.Web; using System.Threading; @@ -14,7 +13,6 @@ namespace GeneXus.Application using System.Web.Configuration; #endif using System.Xml; - using GeneXus.Http; using System.Collections.Concurrent; public class GXFileWatcher : IDisposable diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXMetadata.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXMetadata.cs index eba8f33fc..9c83d6a8f 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXMetadata.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXMetadata.cs @@ -3,7 +3,6 @@ namespace GeneXus.Metadata using System; using System.Reflection; using System.Collections; - using log4net; using System.IO; using GeneXus.Utils; using GeneXus.Configuration; diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXRes.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXRes.cs index a59221c8b..d857504fb 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXRes.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXRes.cs @@ -7,7 +7,6 @@ namespace GeneXus.Resources using GeneXus.Configuration; using GeneXus.Utils; using System.IO; - using log4net; using GeneXus.Application; using System.Collections; using System.Text; diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestUtils.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestUtils.cs index e6e400f8e..27e7b1928 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestUtils.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestUtils.cs @@ -8,7 +8,6 @@ using System.Text.Json; using System.Text.Json.Serialization; #endif -using log4net; using System.IO; using Jayrock.Json; using GeneXus.Configuration; diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXUtilsGeospatial.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXUtilsGeospatial.cs index 42a1f2cf3..b760d64ee 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXUtilsGeospatial.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXUtilsGeospatial.cs @@ -1,19 +1,17 @@ using System; -using System.Globalization; -using System.Runtime.Serialization; using System.Collections; -using Jayrock.Json; -using log4net; +using System.Data.SqlTypes; +using System.Globalization; using System.Reflection; +using System.Runtime.Serialization; using GeneXus.Metadata; -using System.Data.SqlTypes; -using System.IO; +using Jayrock.Json; #if NETCORE using GxClasses.Helpers; #endif namespace GeneXus.Utils { - public interface IGeographicNative + public interface IGeographicNative { Object InnerValue diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs index 1f3d73ab4..0e19a76d5 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs @@ -1,7 +1,6 @@ using GeneXus.Application; using GeneXus.Configuration; using GeneXus.Utils; -using log4net; #if NETCORE using GxClasses.Helpers; using Microsoft.AspNetCore.Http; diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/JSONHelper.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/JSONHelper.cs index a638b3873..a857c3f27 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/JSONHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/JSONHelper.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; using System.IO; using System.Runtime.Serialization.Json; @@ -7,13 +6,11 @@ using Jayrock.Json; using System.Runtime.Serialization; using GeneXus.Configuration; -using System.Linq; #if NETCORE using System.Buffers.Text; using System.Text.Json; using System.Text.Json.Serialization; #endif -using log4net; namespace GeneXus.Utils { diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/ThemeHelper.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/ThemeHelper.cs index aa96d8b3a..d1d33d772 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/ThemeHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/ThemeHelper.cs @@ -1,10 +1,9 @@ -using GeneXus.Application; -using GeneXus.Utils; -using log4net; using System; using System.Collections.Concurrent; using System.IO; using System.Runtime.Serialization; +using GeneXus.Application; +using GeneXus.Utils; namespace GeneXus.Helpers { diff --git a/dotnet/src/dotnetframework/GxClasses/Management/GXManagement.cs b/dotnet/src/dotnetframework/GxClasses/Management/GXManagement.cs index 90f4fadec..3b2b69162 100644 --- a/dotnet/src/dotnetframework/GxClasses/Management/GXManagement.cs +++ b/dotnet/src/dotnetframework/GxClasses/Management/GXManagement.cs @@ -3,16 +3,14 @@ using System.ComponentModel; using System.Management.Instrumentation; using System.Reflection; +using System.Security; using GeneXus.Cache; using GeneXus.Configuration; using GeneXus.Data.ADO; using GeneXus.Utils; using GeneXus.XML; -using log4net; -using System.Security; -using System.Security.Permissions; -[assembly:Instrumented(@"root\GeneXus")] +[assembly: Instrumented(@"root\GeneXus")] namespace GeneXus.Management { [RunInstaller(true)] diff --git a/dotnet/src/dotnetframework/GxClasses/Management/GXPerformance.cs b/dotnet/src/dotnetframework/GxClasses/Management/GXPerformance.cs index 823738b4b..8d2f67e99 100644 --- a/dotnet/src/dotnetframework/GxClasses/Management/GXPerformance.cs +++ b/dotnet/src/dotnetframework/GxClasses/Management/GXPerformance.cs @@ -1,15 +1,14 @@ -using System.Management.Instrumentation; -using System.Collections; using System; +using System.Collections; +using System.Collections.Concurrent; +using System.Diagnostics; +using System.Management.Instrumentation; +using System.Security; using GeneXus.Data; using GeneXus.Data.ADO; using GeneXus.Data.NTier; using GeneXus.Data.NTier.ADO; using GeneXus.XML; -using System.Diagnostics; -using log4net; -using System.Security; -using System.Collections.Concurrent; namespace GeneXus.Performance { diff --git a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs index f5fe21520..a91181789 100644 --- a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs +++ b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs @@ -20,12 +20,9 @@ namespace GeneXus.Http using GeneXus.Utils; using GeneXus.XML; using GeneXus.WebControls; - - using log4net; using Jayrock.Json; using Helpers; using System.Collections.Concurrent; - using Microsoft.Net.Http.Headers; using System.Net.Http; #if NETCORE using Microsoft.AspNetCore.Http; diff --git a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpModules.cs b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpModules.cs index 89ab983df..f88ba3c46 100644 --- a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpModules.cs +++ b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpModules.cs @@ -1,20 +1,19 @@ using System; using System.Collections.Generic; -using GeneXus.Configuration; -using System.Web; using System.IO; -using GeneXus.Utils; +using System.Net.Http; +using System.Reflection; +using System.Security; +using System.Web; +using System.Web.Configuration; +using System.Web.Hosting; +using System.Web.SessionState; using GeneXus.Application; +using GeneXus.Configuration; +using GeneXus.Utils; using ManagedFusion.Rewriter; -using System.Web.Hosting; -using ManagedFusion.Rewriter.Rules; using ManagedFusion.Rewriter.Engines; -using System.Reflection; -using log4net; -using System.Web.SessionState; -using System.Web.Configuration; -using System.Security; -using System.Net.Http; +using ManagedFusion.Rewriter.Rules; namespace GeneXus.Http.HttpModules { diff --git a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpServices.cs b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpServices.cs index fd96e2a76..992631cde 100644 --- a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpServices.cs +++ b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpServices.cs @@ -1,28 +1,18 @@ namespace GeneXus.Http { using System; - using System.Collections; - using System.Collections.Specialized; using System.Collections.Generic; - using System.Globalization; using System.IO; using System.Reflection; using System.Text; - using System.Text.RegularExpressions; - using System.Threading; using GeneXus.Application; using GeneXus.Configuration; using GeneXus.Data.NTier; - using GeneXus.Encryption; using GeneXus.Metadata; using GeneXus.Mime; using GeneXus.Security; using GeneXus.Utils; - using GeneXus.XML; - using GeneXus.WebControls; - - using log4net; using Jayrock.Json; using System.Web.SessionState; using System.Web; diff --git a/dotnet/src/dotnetframework/GxClasses/Middleware/HandlerFactory.cs b/dotnet/src/dotnetframework/GxClasses/Middleware/HandlerFactory.cs index d35f14645..05c998433 100644 --- a/dotnet/src/dotnetframework/GxClasses/Middleware/HandlerFactory.cs +++ b/dotnet/src/dotnetframework/GxClasses/Middleware/HandlerFactory.cs @@ -1,18 +1,17 @@ using System; -using System.Web; -using System.Reflection; -using GeneXus.Configuration; using System.Collections.Generic; -using log4net; using System.IO; -using GeneXus.Application; -using GeneXus.Utils; -using GeneXus.Http.HttpModules; -using GeneXus.Metadata; using System.Net; -using System.Text.RegularExpressions; using System.Net.Http; +using System.Reflection; +using System.Text.RegularExpressions; +using System.Web; +using GeneXus.Application; +using GeneXus.Configuration; using GeneXus.Http; +using GeneXus.Http.HttpModules; +using GeneXus.Metadata; +using GeneXus.Utils; namespace GeneXus.HttpHandlerFactory { diff --git a/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs b/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs index 091060c9a..c6113f10d 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs @@ -4,7 +4,6 @@ using GeneXus.Mock; using GeneXus.Utils; using Jayrock.Json; -using log4net; #if NETCORE using Microsoft.AspNetCore.Http.Extensions; #endif diff --git a/dotnet/src/dotnetframework/GxClasses/Model/GXSilentTrn.cs b/dotnet/src/dotnetframework/GxClasses/Model/GXSilentTrn.cs index 56dd05080..5732587c2 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/GXSilentTrn.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/GXSilentTrn.cs @@ -10,14 +10,12 @@ namespace GeneXus.Utils using System.Text; using System.Security.Cryptography; using System.Reflection; - using log4net; using System.Runtime.Serialization; #if !NETCORE using System.ServiceModel; #endif using Configuration; using System.Globalization; - using GeneXus.Http; public interface IGxSilentTrn { diff --git a/dotnet/src/dotnetframework/GxClasses/Model/GXWebProcedure.cs b/dotnet/src/dotnetframework/GxClasses/Model/GXWebProcedure.cs index 43366566d..fc01e6f12 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/GXWebProcedure.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/GXWebProcedure.cs @@ -5,17 +5,12 @@ namespace GeneXus.Procedure using GeneXus.Printer; using System.Globalization; using GeneXus.Http; - using System.Threading; using GeneXus.Mime; - using GeneXus.Utils; #if NETCORE using Microsoft.AspNetCore.Http; #else using System.Web; #endif - using log4net; - using GeneXus.Application; - using GeneXus.Data.NTier; public class GXWebProcedure : GXHttpHandler { diff --git a/dotnet/src/dotnetframework/GxClasses/Model/GxMockProvider.cs b/dotnet/src/dotnetframework/GxClasses/Model/GxMockProvider.cs index 5ed03425b..0cd5b3c23 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/GxMockProvider.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/GxMockProvider.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using GeneXus.Application; -using log4net; namespace GeneXus.Mock { public interface IGxMock diff --git a/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs b/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs index 77fe03061..7098f3803 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs @@ -14,7 +14,6 @@ namespace GeneXus.Procedure using GeneXus.Printer; using GeneXus.Utils; using GeneXus.XML; - using log4net; public abstract class GXProcedure: GXBaseObject { diff --git a/dotnet/src/dotnetframework/GxClasses/Notifications/WebSocket/GXWebSocketFactory.cs b/dotnet/src/dotnetframework/GxClasses/Notifications/WebSocket/GXWebSocketFactory.cs index a0b36e7a8..16e075739 100644 --- a/dotnet/src/dotnetframework/GxClasses/Notifications/WebSocket/GXWebSocketFactory.cs +++ b/dotnet/src/dotnetframework/GxClasses/Notifications/WebSocket/GXWebSocketFactory.cs @@ -1,6 +1,5 @@ using System; using GeneXus.Http.WebSocket; -using log4net; namespace GeneXus.Notifications.WebSocket { diff --git a/dotnet/src/dotnetframework/GxClasses/Printer/GxPrinter.cs b/dotnet/src/dotnetframework/GxClasses/Printer/GxPrinter.cs index 1fc0f752b..e47f48096 100644 --- a/dotnet/src/dotnetframework/GxClasses/Printer/GxPrinter.cs +++ b/dotnet/src/dotnetframework/GxClasses/Printer/GxPrinter.cs @@ -1,24 +1,22 @@ namespace GeneXus.Printer { using System; - using System.Runtime.InteropServices; - using System.Runtime.CompilerServices; + using System.Collections; + using System.Collections.Generic; + using System.Collections.Specialized; using System.Drawing; - using System.Drawing.Printing; using System.Drawing.Imaging; + using System.Drawing.Printing; + using System.Globalization; using System.IO; + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + using System.Text; using System.Text.RegularExpressions; - using System.Collections.Specialized; - using System.Collections.Generic; - using System.Collections; using System.Threading; - using System.Globalization; - using System.Text; - using GeneXus.Configuration; - using GeneXus.XML; - using log4net; - using System.Runtime.Serialization; using System.Threading.Tasks; + using GeneXus.Configuration; + using GeneXus.XML; public interface IPrintHandler { diff --git a/dotnet/src/dotnetframework/GxClasses/Reorg/GXReorg.cs b/dotnet/src/dotnetframework/GxClasses/Reorg/GXReorg.cs index ac28d111c..e156745ad 100644 --- a/dotnet/src/dotnetframework/GxClasses/Reorg/GXReorg.cs +++ b/dotnet/src/dotnetframework/GxClasses/Reorg/GXReorg.cs @@ -1,21 +1,20 @@ -namespace GeneXus.Reorg +namespace GeneXus.Reorg { using System; - using System.IO; using System.Collections; - using GeneXus.Application; - using log4net; using System.Collections.Specialized; - using System.Runtime.CompilerServices; - using GeneXus.Metadata; + using System.IO; + using System.Reflection; + using System.Runtime.CompilerServices; using System.Threading; + using GeneXus.Application; using GeneXus.Configuration; - using GeneXus.Data.ADO; using GeneXus.Data; + using GeneXus.Data.ADO; + using GeneXus.Data.NTier; + using GeneXus.Metadata; using GeneXus.Resources; using GeneXus.Utils; - using GeneXus.Data.NTier; - using System.Reflection; public interface IReorgReader { diff --git a/dotnet/src/dotnetframework/GxClasses/Security/GxSecurityProvider.cs b/dotnet/src/dotnetframework/GxClasses/Security/GxSecurityProvider.cs index c7b59f95f..2f6b276a3 100644 --- a/dotnet/src/dotnetframework/GxClasses/Security/GxSecurityProvider.cs +++ b/dotnet/src/dotnetframework/GxClasses/Security/GxSecurityProvider.cs @@ -1,11 +1,8 @@ +using System; +using System.Collections.Generic; using GeneXus.Application; using GeneXus.Configuration; using GeneXus.Metadata; -using log4net; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; namespace GeneXus.Security { public class GxResult diff --git a/dotnet/src/dotnetframework/GxClasses/Security/WebSecurity.cs b/dotnet/src/dotnetframework/GxClasses/Security/WebSecurity.cs index ab50dd078..bb8c6a579 100644 --- a/dotnet/src/dotnetframework/GxClasses/Security/WebSecurity.cs +++ b/dotnet/src/dotnetframework/GxClasses/Security/WebSecurity.cs @@ -8,7 +8,6 @@ using GeneXus.Application; using GeneXus.Configuration; using GeneXus.Utils; -using log4net; using Microsoft.IdentityModel.Tokens; using static GeneXus.Web.Security.SecureTokenHelper; @@ -25,7 +24,7 @@ public static string StripInvalidChars(string input) { if (string.IsNullOrEmpty(input)) return input; - var output = new string(input.Where(c => !char.IsControl(c)).ToArray()); + string output = new string(input.Where(c => !char.IsControl(c)).ToArray()); return output.Trim(); } diff --git a/dotnet/src/dotnetframework/GxClasses/Services/Caching/GxCache.cs b/dotnet/src/dotnetframework/GxClasses/Services/Caching/GxCache.cs index bdb789012..1bda980fe 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/Caching/GxCache.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/Caching/GxCache.cs @@ -2,7 +2,6 @@ using System.Collections; using System.Collections.Specialized; using System.Xml; -using log4net; using System.Threading; using System.Globalization; using GeneXus.Management; @@ -21,7 +20,7 @@ #endif namespace GeneXus.Cache { - internal delegate void AddDataHandler(string key, + internal delegate void AddDataHandler(string key, ICacheItemExpiration expiration); [Obsolete("Not for public use. Replaced by ICacheService2", false)] diff --git a/dotnet/src/dotnetframework/GxClasses/Services/GXRestServices.cs b/dotnet/src/dotnetframework/GxClasses/Services/GXRestServices.cs index 65bcd4ce8..0d974268a 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/GXRestServices.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/GXRestServices.cs @@ -5,7 +5,6 @@ using System.IO; using System.Net; using System.Net.Http; -using System.Runtime.Serialization; using System.Runtime.Serialization.Json; using System.Security; using System.ServiceModel; @@ -16,7 +15,6 @@ using System.ServiceModel.Web; using System.Text; using System.Web; -using System.Web.Helpers; using System.Web.Mvc; using GeneXus.Application; using GeneXus.Configuration; @@ -24,8 +22,6 @@ using GeneXus.Http; using GeneXus.Metadata; using GeneXus.Security; -using log4net; -using Microsoft.IdentityModel.Tokens; using Microsoft.Net.Http.Headers; namespace GeneXus.Utils diff --git a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs index 8909d45d8..03fd8f122 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Text; -using log4net; #if NETCORE using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; @@ -26,7 +25,6 @@ using GeneXus.Security; using System.Collections; using Jayrock.Json; -using Microsoft.Net.Http.Headers; using System.Net.Http; using System.Diagnostics; using GeneXus.Diagnostics; diff --git a/dotnet/src/dotnetframework/GxClasses/Services/Storage/ExternalProviderBase.cs b/dotnet/src/dotnetframework/GxClasses/Services/Storage/ExternalProviderBase.cs index 6ce9055af..df8816b04 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/Storage/ExternalProviderBase.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/Storage/ExternalProviderBase.cs @@ -1,7 +1,6 @@ using System; using System.IO; using GeneXus.Encryption; -using log4net; #if NETCORE using GeneXus.Mime; #else diff --git a/dotnet/src/dotnetframework/GxClasses/View/GXWebControls.cs b/dotnet/src/dotnetframework/GxClasses/View/GXWebControls.cs index ff887b8a5..8985e6859 100644 --- a/dotnet/src/dotnetframework/GxClasses/View/GXWebControls.cs +++ b/dotnet/src/dotnetframework/GxClasses/View/GXWebControls.cs @@ -1,5 +1,4 @@ using System; -using System.Web; using System.Drawing; #if !NETCORE using System.Web.UI; @@ -15,14 +14,12 @@ using GeneXus.Utils; using System.Text.RegularExpressions; using Jayrock.Json; -using System.IO; using GeneXus.Configuration; using GeneXus.Application; -using log4net; namespace GeneXus.WebControls { - public class GXWebStdMethods + public class GXWebStdMethods { private static Type webStdType; diff --git a/dotnet/src/dotnetframework/GxDataInitialization/GXDataInitialization.cs b/dotnet/src/dotnetframework/GxDataInitialization/GXDataInitialization.cs index c90fb871e..19296078f 100644 --- a/dotnet/src/dotnetframework/GxDataInitialization/GXDataInitialization.cs +++ b/dotnet/src/dotnetframework/GxDataInitialization/GXDataInitialization.cs @@ -1,18 +1,14 @@ -using GeneXus.Application; -using GeneXus.Configuration; -using GeneXus.Data.NTier; -using GeneXus.Metadata; -using GeneXus.Procedure; -using GeneXus.Reorg; -using GeneXus.Resources; -using log4net; using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Reflection; using System.Text; using System.Xml.Serialization; +using GeneXus.Application; +using GeneXus.Configuration; +using GeneXus.Metadata; +using GeneXus.Procedure; +using GeneXus.Resources; namespace GeneXus.Utils { diff --git a/dotnet/src/dotnetframework/GxExcel/GxExcelEPPlus.cs b/dotnet/src/dotnetframework/GxExcel/GxExcelEPPlus.cs index 2ebb4d027..c833dea5a 100644 --- a/dotnet/src/dotnetframework/GxExcel/GxExcelEPPlus.cs +++ b/dotnet/src/dotnetframework/GxExcel/GxExcelEPPlus.cs @@ -1,9 +1,8 @@ using System; using System.IO; -using log4net; +using GeneXus.Office.Excel; using OfficeOpenXml; using OfficeOpenXml.Style; -using GeneXus.Office.Excel; namespace GeneXus.Office.ExcelGXEPPlus { diff --git a/dotnet/src/dotnetframework/GxExcel/GxExcelI.cs b/dotnet/src/dotnetframework/GxExcel/GxExcelI.cs index 14bdb537c..39be3b6f0 100644 --- a/dotnet/src/dotnetframework/GxExcel/GxExcelI.cs +++ b/dotnet/src/dotnetframework/GxExcel/GxExcelI.cs @@ -1,16 +1,14 @@ using System; -using System.Reflection; -using log4net; using System.Diagnostics; using System.IO; +using System.Reflection; using GeneXus.Application; -using GeneXus.Utils; -using GeneXus.Services; using GeneXus.Office.Excel; +using GeneXus.Services; namespace GeneXus.Office { - public class ExcelDocumentI + public class ExcelDocumentI { static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); diff --git a/dotnet/src/dotnetframework/GxExcel/GxExcelLite.cs b/dotnet/src/dotnetframework/GxExcel/GxExcelLite.cs index 258f9f879..7e76fe0a9 100644 --- a/dotnet/src/dotnetframework/GxExcel/GxExcelLite.cs +++ b/dotnet/src/dotnetframework/GxExcel/GxExcelLite.cs @@ -1,9 +1,7 @@ using System; -using GeneXus.Office; using System.Collections; -using System.Reflection; using System.IO; -using log4net; +using System.Reflection; using GeneXus.Application; using GeneXus.Office.Excel; using GxClasses.Helpers; diff --git a/dotnet/src/dotnetframework/GxMail/Exchange/ExchangeSession.cs b/dotnet/src/dotnetframework/GxMail/Exchange/ExchangeSession.cs index 079858e07..2127f7b3b 100644 --- a/dotnet/src/dotnetframework/GxMail/Exchange/ExchangeSession.cs +++ b/dotnet/src/dotnetframework/GxMail/Exchange/ExchangeSession.cs @@ -1,10 +1,9 @@ -using log4net; -using Microsoft.Exchange.WebServices.Data; -using Microsoft.Identity.Client; using System; using System.IO; using System.Linq; using System.Net; +using Microsoft.Exchange.WebServices.Data; +using Microsoft.Identity.Client; namespace GeneXus.Mail.Exchange { diff --git a/dotnet/src/dotnetframework/GxMail/Exchange/Service.cs b/dotnet/src/dotnetframework/GxMail/Exchange/Service.cs index a50ff52f4..1208ba985 100644 --- a/dotnet/src/dotnetframework/GxMail/Exchange/Service.cs +++ b/dotnet/src/dotnetframework/GxMail/Exchange/Service.cs @@ -2,11 +2,10 @@ using System.Net; using Microsoft.Exchange.WebServices.Data; -using log4net; namespace GeneXus.Mail.Exchange { - public static class Service + public static class Service { private static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); diff --git a/dotnet/src/dotnetframework/GxMail/Exchange/TraceListener.cs b/dotnet/src/dotnetframework/GxMail/Exchange/TraceListener.cs index a8ed7829e..5cbb39a09 100644 --- a/dotnet/src/dotnetframework/GxMail/Exchange/TraceListener.cs +++ b/dotnet/src/dotnetframework/GxMail/Exchange/TraceListener.cs @@ -1,13 +1,8 @@ -using log4net; using Microsoft.Exchange.WebServices.Data; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace GeneXus.Mail.Exchange { - public class TraceListener : ITraceListener + public class TraceListener : ITraceListener { private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public void Trace(string traceType, string traceMessage) diff --git a/dotnet/src/dotnetframework/GxMail/GXMailSession.cs b/dotnet/src/dotnetframework/GxMail/GXMailSession.cs index 8d8d2bd73..bdc7e236d 100644 --- a/dotnet/src/dotnetframework/GxMail/GXMailSession.cs +++ b/dotnet/src/dotnetframework/GxMail/GXMailSession.cs @@ -1,9 +1,8 @@ -using log4net; using System; namespace GeneXus.Mail { - + public abstract class GXMailSession { private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); diff --git a/dotnet/src/dotnetframework/GxMail/GXPOP3Session.cs b/dotnet/src/dotnetframework/GxMail/GXPOP3Session.cs index 2db01333e..aac24161e 100644 --- a/dotnet/src/dotnetframework/GxMail/GXPOP3Session.cs +++ b/dotnet/src/dotnetframework/GxMail/GXPOP3Session.cs @@ -1,11 +1,10 @@ using System; -using GeneXus.Mail.Internals; using GeneXus.Configuration; -using log4net; +using GeneXus.Mail.Internals; namespace GeneXus.Mail { - + public class GXPOP3Session : GXMailSession { private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); diff --git a/dotnet/src/dotnetframework/GxMail/GXSMTPSession.cs b/dotnet/src/dotnetframework/GxMail/GXSMTPSession.cs index 4938afd0e..42ec2cf4d 100644 --- a/dotnet/src/dotnetframework/GxMail/GXSMTPSession.cs +++ b/dotnet/src/dotnetframework/GxMail/GXSMTPSession.cs @@ -1,13 +1,11 @@ using System; -using GeneXus.Mail.Internals; -using GeneXus.Utils; using GeneXus.Configuration; -using log4net; +using GeneXus.Mail.Internals; namespace GeneXus.Mail { - - public class GXSMTPSession : GXMailSession + + public class GXSMTPSession : GXMailSession { static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private ISMTPSession session; diff --git a/dotnet/src/dotnetframework/GxMail/MAPISession.cs b/dotnet/src/dotnetframework/GxMail/MAPISession.cs index 62f201422..1211d92e7 100644 --- a/dotnet/src/dotnetframework/GxMail/MAPISession.cs +++ b/dotnet/src/dotnetframework/GxMail/MAPISession.cs @@ -1,11 +1,10 @@ using System; -using log4net; using GeneXus.Utils; using MAPI; namespace GeneXus.Mail.Internals { - + internal class MAPISession { private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); diff --git a/dotnet/src/dotnetframework/GxMail/MailMessage.cs b/dotnet/src/dotnetframework/GxMail/MailMessage.cs index e7afe0a91..c09eb4f1f 100644 --- a/dotnet/src/dotnetframework/GxMail/MailMessage.cs +++ b/dotnet/src/dotnetframework/GxMail/MailMessage.cs @@ -1,17 +1,16 @@ using System; using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; using System.IO; using System.Text; using System.Text.RegularExpressions; -using log4net; using System.Threading; using GeneXus.Utils; -using System.Collections.Generic; -using System.Collections.Concurrent; namespace GeneXus.Mail.Internals.Pop3 { - + internal class MailMessage { private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); diff --git a/dotnet/src/dotnetframework/GxMail/Mentalis/RFC822EndReader.cs b/dotnet/src/dotnetframework/GxMail/Mentalis/RFC822EndReader.cs index 052f93e51..c15ee788f 100644 --- a/dotnet/src/dotnetframework/GxMail/Mentalis/RFC822EndReader.cs +++ b/dotnet/src/dotnetframework/GxMail/Mentalis/RFC822EndReader.cs @@ -1,7 +1,6 @@ using System; using System.IO; using System.Text; -using log4net; namespace GeneXus.Mail.Internals.Pop3 { diff --git a/dotnet/src/dotnetframework/GxMail/OutlookSession.cs b/dotnet/src/dotnetframework/GxMail/OutlookSession.cs index fc6d1aaf8..061ca6a41 100644 --- a/dotnet/src/dotnetframework/GxMail/OutlookSession.cs +++ b/dotnet/src/dotnetframework/GxMail/OutlookSession.cs @@ -1,13 +1,11 @@ using System; using System.IO; -using System.Collections; -using log4net; -using Outlook; using GeneXus.Utils; +using Outlook; namespace GeneXus.Mail.Internals { - + internal class OutlookSession { private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); diff --git a/dotnet/src/dotnetframework/GxMail/POP3Session.cs b/dotnet/src/dotnetframework/GxMail/POP3Session.cs index f8e878428..cfc767353 100644 --- a/dotnet/src/dotnetframework/GxMail/POP3Session.cs +++ b/dotnet/src/dotnetframework/GxMail/POP3Session.cs @@ -1,19 +1,17 @@ using System; using System.IO; -using System.Text; +using System.Linq; using System.Net; using System.Net.Sockets; -using System.Threading; -using log4net; +using System.Text; using GeneXus.Mail.Internals.Pop3; -using Org.Mentalis.Security.Ssl; using Org.Mentalis.Security.Certificates; -using System.Linq; +using Org.Mentalis.Security.Ssl; namespace GeneXus.Mail.Internals { - - internal class POP3Session : Pop3SessionBase + + internal class POP3Session : Pop3SessionBase { private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private const string CRLF = "\r\n"; diff --git a/dotnet/src/dotnetframework/GxMail/POP3SessionOpenPop.cs b/dotnet/src/dotnetframework/GxMail/POP3SessionOpenPop.cs index 3545ddfb7..55894e69d 100644 --- a/dotnet/src/dotnetframework/GxMail/POP3SessionOpenPop.cs +++ b/dotnet/src/dotnetframework/GxMail/POP3SessionOpenPop.cs @@ -1,17 +1,16 @@ using System; using System.Collections.Generic; -using OpenPop.Pop3; -using OpenPop.Pop3.Exceptions; -using log4net; -using OpenPop.Mime; -using System.Net.Mail; using System.IO; -using GeneXus.Utils; +using System.Net.Mail; using System.Reflection; +using GeneXus.Utils; +using OpenPop.Mime; +using OpenPop.Pop3; +using OpenPop.Pop3.Exceptions; namespace GeneXus.Mail { - internal class POP3SessionOpenPop : Pop3SessionBase + internal class POP3SessionOpenPop : Pop3SessionBase { static readonly IGXLogger log = GXLoggerFactory.GetLogger(); diff --git a/dotnet/src/dotnetframework/GxMail/Pop3MailKit.cs b/dotnet/src/dotnetframework/GxMail/Pop3MailKit.cs index a7e9fd364..e2df4bcb3 100644 --- a/dotnet/src/dotnetframework/GxMail/Pop3MailKit.cs +++ b/dotnet/src/dotnetframework/GxMail/Pop3MailKit.cs @@ -1,13 +1,12 @@ using System; using System.Collections.Generic; +using System.IO; using System.Security.Authentication; -using log4net; +using GeneXus.Utils; using MailKit; -using MailKit.Security; using MailKit.Net.Pop3; +using MailKit.Security; using MimeKit; -using GeneXus.Utils; -using System.IO; namespace GeneXus.Mail { diff --git a/dotnet/src/dotnetframework/GxMail/Pop3SessionBase.cs b/dotnet/src/dotnetframework/GxMail/Pop3SessionBase.cs index 619d7d45e..50cb7ea6a 100644 --- a/dotnet/src/dotnetframework/GxMail/Pop3SessionBase.cs +++ b/dotnet/src/dotnetframework/GxMail/Pop3SessionBase.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.IO; using System.Text.RegularExpressions; -using log4net; namespace GeneXus.Mail { diff --git a/dotnet/src/dotnetframework/GxMail/SMTP/SmtpHelper.cs b/dotnet/src/dotnetframework/GxMail/SMTP/SmtpHelper.cs index 23642d907..93dacac98 100644 --- a/dotnet/src/dotnetframework/GxMail/SMTP/SmtpHelper.cs +++ b/dotnet/src/dotnetframework/GxMail/SMTP/SmtpHelper.cs @@ -1,5 +1,3 @@ -using GeneXus.Metadata; -using log4net; using System; using System.Net; using System.Net.Mail; @@ -34,7 +32,7 @@ public static bool ValidateConnection(SmtpClient smtp, string senderAddress, boo { senderAddress = (string.IsNullOrEmpty(senderAddress)) ? "test@gmail.com" : senderAddress; SmtpGetConnection(smtpTransportType, SmtpTransport, smtp); - var connection = SmtpConnectionField(SmtpTransport); + object connection = SmtpConnectionField(SmtpTransport); if (checkUnicodeSupport) { Type mailCommandType = ass.GetType(SMTP_MAIL_COMMAND_TYPE); diff --git a/dotnet/src/dotnetframework/GxMail/SMTPMailClient.cs b/dotnet/src/dotnetframework/GxMail/SMTPMailClient.cs index 6a2acfa79..8c1086aac 100644 --- a/dotnet/src/dotnetframework/GxMail/SMTPMailClient.cs +++ b/dotnet/src/dotnetframework/GxMail/SMTPMailClient.cs @@ -1,13 +1,12 @@ using System; -using System.Text; -using System.Net.Mail; using System.IO; -using log4net; +using System.Net.Mail; +using System.Text; using GeneXus.Mail.Smtp; namespace GeneXus.Mail { - internal class SMTPMailClient : ISMTPSession + internal class SMTPMailClient : ISMTPSession { private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); diff --git a/dotnet/src/dotnetframework/GxMail/SMTPMailKit.cs b/dotnet/src/dotnetframework/GxMail/SMTPMailKit.cs index d1b710e15..651601626 100644 --- a/dotnet/src/dotnetframework/GxMail/SMTPMailKit.cs +++ b/dotnet/src/dotnetframework/GxMail/SMTPMailKit.cs @@ -1,11 +1,10 @@ using System; using System.IO; -using log4net; -using MimeKit; +using System.Net.Sockets; using MailKit; using MailKit.Net.Smtp; using MailKit.Security; -using System.Net.Sockets; +using MimeKit; namespace GeneXus.Mail { diff --git a/dotnet/src/dotnetframework/GxMail/SMTPSession.cs b/dotnet/src/dotnetframework/GxMail/SMTPSession.cs index 02de5d996..5201a4ec3 100644 --- a/dotnet/src/dotnetframework/GxMail/SMTPSession.cs +++ b/dotnet/src/dotnetframework/GxMail/SMTPSession.cs @@ -1,20 +1,19 @@ using System; +using System.Collections.Generic; +using System.Globalization; using System.IO; -using System.Text; using System.Net; using System.Net.Sockets; -using System.Globalization; -using log4net; -using GeneXus.Utils; +using System.Text; using GeneXus.Mail.Internals.Smtp; -using Org.Mentalis.Security.Ssl; +using GeneXus.Utils; using Org.Mentalis.Security.Certificates; -using System.Collections.Generic; +using Org.Mentalis.Security.Ssl; namespace GeneXus.Mail.Internals { - - internal class SMTPSession: ISMTPSession + + internal class SMTPSession: ISMTPSession { private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); #region Mail Constants diff --git a/dotnet/src/dotnetframework/GxOffice/ExcelSpreadsheetGXWrapper.cs b/dotnet/src/dotnetframework/GxOffice/ExcelSpreadsheetGXWrapper.cs index cc839e38c..dd65d8849 100644 --- a/dotnet/src/dotnetframework/GxOffice/ExcelSpreadsheetGXWrapper.cs +++ b/dotnet/src/dotnetframework/GxOffice/ExcelSpreadsheetGXWrapper.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using GeneXus.MSOffice.Excel.Poi.Xssf; -using log4net; namespace GeneXus.MSOffice.Excel { diff --git a/dotnet/src/dotnetframework/GxOffice/poi/xssf/ExcelCells.cs b/dotnet/src/dotnetframework/GxOffice/poi/xssf/ExcelCells.cs index 135a5d14d..019fc95e7 100644 --- a/dotnet/src/dotnetframework/GxOffice/poi/xssf/ExcelCells.cs +++ b/dotnet/src/dotnetframework/GxOffice/poi/xssf/ExcelCells.cs @@ -2,7 +2,6 @@ using System; using GeneXus.MSOffice.Excel.Style; using GeneXus.Utils; -using log4net; using NPOI.OpenXmlFormats.Spreadsheet; using NPOI.SS.UserModel; using NPOI.SS.Util; diff --git a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs index a0cee76a1..0bb0a83c8 100644 --- a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs +++ b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs @@ -1,25 +1,20 @@ using System; - -using System.IO; using System.Collections; -using System.Threading; -using System.Text; -using Microsoft.Win32; -using System.Runtime.InteropServices; -using System.Globalization; - -using System.util; -using System.Diagnostics; -using log4net; - -using GeneXus.Printer; using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; using System.Security; +using System.Text; +using System.Threading; +using System.util; using GeneXus; +using GeneXus.Printer; using GeneXus.Utils; -using System.Reflection; -using GeneXus.Metadata; +using Microsoft.Win32; namespace com.genexus.reports { diff --git a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext4.cs b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext4.cs index 8e183e247..c84601f6b 100644 --- a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext4.cs +++ b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext4.cs @@ -10,7 +10,6 @@ using iTextSharp.text; using iTextSharp.text.html.simpleparser; using iTextSharp.text.pdf; -using log4net; namespace com.genexus.reports { diff --git a/dotnet/src/dotnetframework/GxPdfReportsCS/PdfReportInterface.cs b/dotnet/src/dotnetframework/GxPdfReportsCS/PdfReportInterface.cs index 5c677d48d..d7c71c5d2 100644 --- a/dotnet/src/dotnetframework/GxPdfReportsCS/PdfReportInterface.cs +++ b/dotnet/src/dotnetframework/GxPdfReportsCS/PdfReportInterface.cs @@ -1,5 +1,4 @@ using System.IO; -using log4net; namespace GeneXus.Printer { diff --git a/dotnet/src/dotnetframework/GxSearch/DocumentHandler.cs b/dotnet/src/dotnetframework/GxSearch/DocumentHandler.cs index a80904a8a..616d1d203 100644 --- a/dotnet/src/dotnetframework/GxSearch/DocumentHandler.cs +++ b/dotnet/src/dotnetframework/GxSearch/DocumentHandler.cs @@ -1,25 +1,21 @@ using System; using System.Collections; +using System.Collections.Concurrent; using System.IO; +using System.Reflection; +using System.Runtime.CompilerServices; using System.Text; - +using GeneXus.Search; using Lucene.Net.Analysis; using Lucene.Net.Analysis.Standard; -using Lucene.Net.Search.Highlight; using Lucene.Net.Index; using Lucene.Net.QueryParsers; using Lucene.Net.Search; - -using log4net; -using GeneXus.Search; -using System.Runtime.CompilerServices; -using System.Reflection; -using System.Collections.Concurrent; - +using Lucene.Net.Search.Highlight; using NUglify; using NUglify.Html; -using UglyToad.PdfPig.Content; using UglyToad.PdfPig; +using UglyToad.PdfPig.Content; namespace GeneXus.Utils { diff --git a/dotnet/src/dotnetframework/GxSearch/Indexer.cs b/dotnet/src/dotnetframework/GxSearch/Indexer.cs index 41bb64752..320db4629 100644 --- a/dotnet/src/dotnetframework/GxSearch/Indexer.cs +++ b/dotnet/src/dotnetframework/GxSearch/Indexer.cs @@ -1,23 +1,14 @@ using System; using System.Collections; using System.Collections.Generic; -using System.ComponentModel; using System.IO; -using System.Text; +using System.Security; using System.Threading; - +using GeneXus.Utils; +using Lucene.Net.Analysis; using Lucene.Net.Analysis.Standard; using Lucene.Net.Documents; using Lucene.Net.Index; -using Lucene.Net.Search; -using Lucene.Net.Store; - -using log4net; - -using GeneXus.Utils; -using Lucene.Net.Analysis; -using System.Globalization; -using System.Security; namespace GeneXus.Search { @@ -34,7 +25,7 @@ public sealed class Indexer private Thread worker; private Indexer() { - var folder = Settings.Instance.IndexFolder; + string folder = Settings.Instance.IndexFolder; GXLogging.Debug(log,"LUCENE_INDEX_DIRECTORY: " + folder); worker = new Thread(new ThreadStart(BackgroundIndexer)); worker.Start(); diff --git a/dotnet/src/dotnetframework/GxSearch/Searcher.cs b/dotnet/src/dotnetframework/GxSearch/Searcher.cs index 2013f428e..0352267dc 100644 --- a/dotnet/src/dotnetframework/GxSearch/Searcher.cs +++ b/dotnet/src/dotnetframework/GxSearch/Searcher.cs @@ -1,17 +1,9 @@ using System; -using System.Collections.Generic; -using System.Text; -using System.Text.RegularExpressions; - -using Lucene.Net.Analysis.Standard; -using Lucene.Net.QueryParsers; -using Lucene.Net.Search; - -using log4net; - +using System.Security; using GeneXus.Application; using Lucene.Net.Analysis; -using System.Security; +using Lucene.Net.QueryParsers; +using Lucene.Net.Search; namespace GeneXus.Search { diff --git a/dotnet/src/dotnetframework/GxSearch/Settings.cs b/dotnet/src/dotnetframework/GxSearch/Settings.cs index 85f049cbf..8c53915ac 100644 --- a/dotnet/src/dotnetframework/GxSearch/Settings.cs +++ b/dotnet/src/dotnetframework/GxSearch/Settings.cs @@ -3,8 +3,6 @@ using System.Security; using GeneXus.Configuration; -using log4net; - namespace GeneXus.Search { diff --git a/dotnet/src/dotnetframework/GxSearch/SpellChecker.cs b/dotnet/src/dotnetframework/GxSearch/SpellChecker.cs index db3cc170f..7b6e541d8 100644 --- a/dotnet/src/dotnetframework/GxSearch/SpellChecker.cs +++ b/dotnet/src/dotnetframework/GxSearch/SpellChecker.cs @@ -2,10 +2,7 @@ using System.IO; using System.Text; -using log4net; - using Lucene.Net.Index; -using Lucene.Net.Store; using SpellChecker.Net.Search.Spell; namespace GeneXus.Search diff --git a/dotnet/src/dotnetframework/GxWebSocket/WSHandler.cs b/dotnet/src/dotnetframework/GxWebSocket/WSHandler.cs index bb81262c5..ddf4f9fe4 100644 --- a/dotnet/src/dotnetframework/GxWebSocket/WSHandler.cs +++ b/dotnet/src/dotnetframework/GxWebSocket/WSHandler.cs @@ -9,7 +9,6 @@ using GeneXus.Services; using GeneXus.Utils; using Jayrock.Json; -using log4net; using Microsoft.Web.WebSockets; namespace GeneXus.Http.WebSocket diff --git a/dotnet/src/dotnetframework/Projects/StoreManager/Store/StoreManager.cs b/dotnet/src/dotnetframework/Projects/StoreManager/Store/StoreManager.cs index 87f7a08d9..ff8279c6d 100644 --- a/dotnet/src/dotnetframework/Projects/StoreManager/Store/StoreManager.cs +++ b/dotnet/src/dotnetframework/Projects/StoreManager/Store/StoreManager.cs @@ -1,13 +1,9 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using GeneXus.Utils; -using Jayrock.Json; -using GeneXus; -using log4net; using GeneXus.SD.Store.Model; using GeneXus.SD.Store.Platforms; +using GeneXus.Utils; +using Jayrock.Json; namespace GeneXus.SD.Store { diff --git a/dotnet/src/dotnetframework/Providers/Cache/GxRedis/GxRedis.cs b/dotnet/src/dotnetframework/Providers/Cache/GxRedis/GxRedis.cs index f15c789e9..7007d736a 100644 --- a/dotnet/src/dotnetframework/Providers/Cache/GxRedis/GxRedis.cs +++ b/dotnet/src/dotnetframework/Providers/Cache/GxRedis/GxRedis.cs @@ -1,17 +1,11 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Text.Json.Serialization; using System.Text.Json; -using System.Runtime.Serialization.Formatters.Binary; +using System.Threading.Tasks; using GeneXus.Services; using GeneXus.Utils; -using log4net; using StackExchange.Redis; -using System.Reflection; -using System.Security; -using System.Threading.Tasks; namespace GeneXus.Cache { @@ -213,7 +207,7 @@ private string Key(string cacheid, string key) } private IEnumerable Key(string cacheid, IEnumerable key) { - var prefix = KeyPrefix(cacheid); + long? prefix = KeyPrefix(cacheid); return key.Select(k => new RedisKey().Append(FormatKey(cacheid, k, prefix))); } private string FormatKey(string cacheid, string key, Nullable prefix) diff --git a/dotnet/src/dotnetframework/Providers/Storage/GXAmazonS3/ExternalProviderS3.cs b/dotnet/src/dotnetframework/Providers/Storage/GXAmazonS3/ExternalProviderS3.cs index 2a1dbe829..d31d262d9 100644 --- a/dotnet/src/dotnetframework/Providers/Storage/GXAmazonS3/ExternalProviderS3.cs +++ b/dotnet/src/dotnetframework/Providers/Storage/GXAmazonS3/ExternalProviderS3.cs @@ -1,16 +1,14 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading; using Amazon.Runtime; using Amazon.S3; using Amazon.S3.IO; using Amazon.S3.Model; - using Amazon.S3.Transfer; using GeneXus.Services; using GeneXus.Utils; -using log4net; -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading; namespace GeneXus.Storage.GXAmazonS3 diff --git a/dotnet/src/extensions/Azure/Handlers/HttpHandler/GXHttpAzureContextAccessor.cs b/dotnet/src/extensions/Azure/Handlers/HttpHandler/GXHttpAzureContextAccessor.cs index 2a9e3c97a..1c3285d3f 100644 --- a/dotnet/src/extensions/Azure/Handlers/HttpHandler/GXHttpAzureContextAccessor.cs +++ b/dotnet/src/extensions/Azure/Handlers/HttpHandler/GXHttpAzureContextAccessor.cs @@ -6,13 +6,11 @@ using System.IO.Pipelines; using System.Linq; using System.Security.Claims; -using System.Text; using System.Text.Json.Nodes; using System.Threading; using System.Threading.Tasks; using GeneXus.Cache; using GeneXus.Utils; -using log4net; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using Microsoft.Azure.Functions.Worker.Http; From e24f91b5f1b3b8756070281bf054f03b6f9e2361 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Sexenian?= <99925035+tomas-sexenian@users.noreply.github.com> Date: Mon, 13 Nov 2023 13:29:13 -0300 Subject: [PATCH 063/164] Send manipulated images to temp media directory (#874) * Send manipulated images to temp media directory Issue: 104803 * Remove debugger call and use temp media path as gxfile destination * Manipulated image wasn't being created in external storage --- .../GxClasses/Core/GXUtilsCommon.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs index d4bb6a16d..9f2919a80 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs @@ -5782,7 +5782,7 @@ private static Bitmap BitmapCreateFromStream(string filePathOrUrl) { try { - byte[] data = httpClient.GetByteArrayAsync(filePathOrUrl).Result; + byte[] data = httpClient.GetByteArrayAsync(uri).Result; using (MemoryStream mem = new MemoryStream(data)) { return new Bitmap(mem); @@ -5814,7 +5814,7 @@ private static Image ImageCreateFromStream(string filePathOrUrl) { try { - byte[] data = httpClient.GetByteArrayAsync(filePathOrUrl).Result; + byte[] data = httpClient.GetByteArrayAsync(uri).Result; using (MemoryStream mem = new MemoryStream(data)) { return Image.FromStream(mem); @@ -6077,12 +6077,15 @@ public static string Save(Image bitmap, string imageFile, ImageFormat format) Uri uri = new Uri(imageFile); imageFile = Path.GetFileName(uri.AbsolutePath); } - GxFile sourceImage = new GxFile(GxContext.StaticPhysicalPath(), imageFile); - string destinationImageName = FileUtil.getTempFileName(sourceImage.GetDirectory().GetAbsoluteName(), Path.GetFileNameWithoutExtension(sourceImage.GetName()), sourceImage.GetExtension()); - GxFile destinationImage = new GxFile(GxContext.StaticPhysicalPath(), destinationImageName); + string destinationImageName = FileUtil.getTempFileName( + "", + Path.GetFileNameWithoutExtension(imageFile), + Path.GetExtension(imageFile).TrimStart('.') + ); + GxFile destinationImage = new GxFile(Preferences.getTMP_MEDIA_PATH(), destinationImageName, GxFileType.PrivateAttribute); destinationImage.Create(ms); destinationImage.Close(); - destinationImagePath = destinationImage.GetAbsoluteName(); + destinationImagePath = destinationImage.GetURI(); } catch (Exception ex) { From a48f991762c40f86fa5f88ed110c726b11ea32a6 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Mon, 13 Nov 2023 13:55:02 -0300 Subject: [PATCH 064/164] Filter requests accessing TMPMEDIA_DIR folder. (#905) * Filter requests accessing TMPMEDIA_DIR folder. * Filter access to private dir. --- .../dotnetcore/GxClasses.Web/Middleware/GXRouting.cs | 2 +- dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs index abdb7022f..8ffe0c2de 100644 --- a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs +++ b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs @@ -44,7 +44,7 @@ internal class GXRouting : IGXRouting static Regex SDSVC_PATTERN = new Regex("([^/]+/)*(sdsvc_[^/]+/[^/]+)(\\?.*)*"); - const string PRIVATE_DIR = "private"; + internal const string PRIVATE_DIR = "private"; public Dictionary servicesPathUrl = new Dictionary(); public Dictionary> servicesMap = new Dictionary>(); public Dictionary, String>> servicesMapData = new Dictionary, string>>(); diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs index 9a0116a6f..5cda19ae5 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs @@ -370,14 +370,22 @@ public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHos if (File.Exists(rewriteFile)) AddRewrite(app, rewriteFile, baseVirtualPath); + string tempMediaDir = string.Empty; + if (Config.GetValueOf("TMPMEDIA_DIR", out string mediaPath) && !PathUtil.IsAbsoluteUrlOrAnyScheme(mediaPath)) + { + tempMediaDir = mediaPath; + } app.UseStaticFiles(new StaticFileOptions() { FileProvider = new PhysicalFileProvider(LocalPath), RequestPath = new PathString($"{baseVirtualPath}"), OnPrepareResponse = s => { - var path = s.Context.Request.Path; - if (path.HasValue && path.Value.IndexOf($"/{APP_SETTINGS}", StringComparison.OrdinalIgnoreCase)>=0) + PathString path = s.Context.Request.Path; + bool appSettingsPath = path.HasValue && path.Value.IndexOf($"/{APP_SETTINGS}", StringComparison.OrdinalIgnoreCase) >= 0; + bool tempMediaPath = path.StartsWithSegments($"{baseVirtualPath}/{tempMediaDir}", StringComparison.OrdinalIgnoreCase); + bool privatePath = path.StartsWithSegments($"{baseVirtualPath}/{GXRouting.PRIVATE_DIR}", StringComparison.OrdinalIgnoreCase); + if (appSettingsPath || tempMediaPath || privatePath) { s.Context.Response.StatusCode = 401; s.Context.Response.Body = Stream.Null; From cef723732060275bbeee76c30f429e24b2ef6eb6 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 14 Nov 2023 10:18:01 -0300 Subject: [PATCH 065/164] Directory PrivateTempStorage should only be created when necessary (#906) * Directory PrivateTempStorage should only be created when necessary * Separate ProcedureTest.cs into a different project to ensure that PrivateTempStorage is not initialized. --- dotnet/DotNetStandardClasses.sln | 8 + .../GxClasses/Data/GXDataADO.cs | 9 +- .../DotNetCoreCmdTest/Domain/ProcedureTest.cs | 152 ++++++++++++++++++ .../DotNetCoreCmdTest.csproj | 43 +++++ .../FileIO/FileSystemTest.cs | 17 ++ .../test/DotNetCoreCmdTest/appsettings.json | 64 ++++++++ 6 files changed, 291 insertions(+), 2 deletions(-) create mode 100644 dotnet/test/DotNetCoreCmdTest/Domain/ProcedureTest.cs create mode 100644 dotnet/test/DotNetCoreCmdTest/DotNetCoreCmdTest.csproj create mode 100644 dotnet/test/DotNetCoreCmdTest/FileIO/FileSystemTest.cs create mode 100644 dotnet/test/DotNetCoreCmdTest/appsettings.json diff --git a/dotnet/DotNetStandardClasses.sln b/dotnet/DotNetStandardClasses.sln index bbd55c51d..e159f7a5d 100644 --- a/dotnet/DotNetStandardClasses.sln +++ b/dotnet/DotNetStandardClasses.sln @@ -250,8 +250,11 @@ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetCoreAttackMitigationTest", "test\DotNetCoreAttackMitigationTest\DotNetCoreAttackMitigationTest.csproj", "{2D615969-53E2-4B77-9A9A-75C33865CF76}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetCoreChunkedTest", "test\DotNetCoreChunkedTest\DotNetCoreChunkedTest.csproj", "{5D2B1299-479F-430A-8D72-34D44FB299FD}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetPDFUnitTest", "test\DotNetPdfTest\DotNetPDFUnitTest.csproj", "{0FCFB078-5584-469F-92CC-61B0A6216D0D}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetCoreCmdTest", "test\DotNetCoreCmdTest\DotNetCoreCmdTest.csproj", "{956402BD-AC8C-426E-961B-B77B3F3EDAEB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -614,6 +617,10 @@ Global {0FCFB078-5584-469F-92CC-61B0A6216D0D}.Debug|Any CPU.Build.0 = Debug|Any CPU {0FCFB078-5584-469F-92CC-61B0A6216D0D}.Release|Any CPU.ActiveCfg = Release|Any CPU {0FCFB078-5584-469F-92CC-61B0A6216D0D}.Release|Any CPU.Build.0 = Release|Any CPU + {956402BD-AC8C-426E-961B-B77B3F3EDAEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {956402BD-AC8C-426E-961B-B77B3F3EDAEB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {956402BD-AC8C-426E-961B-B77B3F3EDAEB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {956402BD-AC8C-426E-961B-B77B3F3EDAEB}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -735,6 +742,7 @@ Global {2D615969-53E2-4B77-9A9A-75C33865CF76} = {1D6F1776-FF4B-46C2-9B3D-BC46CCF049DC} {5D2B1299-479F-430A-8D72-34D44FB299FD} = {1D6F1776-FF4B-46C2-9B3D-BC46CCF049DC} {0FCFB078-5584-469F-92CC-61B0A6216D0D} = {1D6F1776-FF4B-46C2-9B3D-BC46CCF049DC} + {956402BD-AC8C-426E-961B-B77B3F3EDAEB} = {1D6F1776-FF4B-46C2-9B3D-BC46CCF049DC} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E18684C9-7D76-45CD-BF24-E3944B7F174C} diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataADO.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataADO.cs index d907f94e7..22938b4ad 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataADO.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataADO.cs @@ -1152,7 +1152,13 @@ public string DSVersion } public string BlobPath { - get {return blobPath;} + get { + if (blobPath == null) + { + blobPath = Preferences.getBLOB_PATH(); + } + return blobPath; + } set {blobPath=value;} } public string MultimediaPath @@ -2631,7 +2637,6 @@ private void Initialize(IGxDataRecord db, string id, int hnd, IGxContext context if ( ! cfg) connection.ConnectionString = connectionString; - connection.BlobPath = Preferences.getBLOB_PATH(); string strCache; connection.Cache=((Config.GetValueOf("CACHING",out strCache) && strCache.Equals("1")) || CacheFactory.ForceHighestTimetoLive) && ! GxContext.isReorganization; connection.DataStore = this; diff --git a/dotnet/test/DotNetCoreCmdTest/Domain/ProcedureTest.cs b/dotnet/test/DotNetCoreCmdTest/Domain/ProcedureTest.cs new file mode 100644 index 000000000..dc15abd95 --- /dev/null +++ b/dotnet/test/DotNetCoreCmdTest/Domain/ProcedureTest.cs @@ -0,0 +1,152 @@ +using System; +using System.IO; +using GeneXus.Application; +using GeneXus.Configuration; +using GeneXus.Data; +using GeneXus.Data.NTier; +using GeneXus.Data.NTier.ADO; +using GeneXus.Procedure; +using UnitTesting; +using Xunit; + +namespace DotNetCoreUnitTest.Domain +{ + public class ProcedureInitializationTest : FileSystemTest + { + [Fact] + public void PublicTempStorageNotCreated() + { + bool isKey = Config.GetValueOf("CS_BLOB_PATH", out string blobPath); + Assert.True(isKey); + string path = Path.Combine(BaseDir, blobPath); + aprocedure1 aprocedure1 = new aprocedure1(); + aprocedure1.execute(); + Assert.False(Directory.Exists(path), $"The directory {blobPath} should only be created when necessary."); + + isKey = Config.GetValueOf("TMPMEDIA_DIR", out string tempMediaDir); + Assert.True(isKey); + path = Path.Combine(BaseDir, tempMediaDir); + Assert.False(Directory.Exists(path), $"The directory {tempMediaDir} should only be created when necessary."); + } + } + public class aprocedure1 : GXProcedure + { + + public int executeCmdLine(string[] args) + { + return ExecuteCmdLine(args); ; + } + + protected override int ExecuteCmdLine(string[] args) + { + execute(); + return GX.GXRuntime.ExitCode; + } + + public aprocedure1() + { + context = new GxContext(); + DataStoreUtil.LoadDataStores(context); + IsMain = true; + context.SetDefaultTheme("CmdLine", true); + } + + public aprocedure1(IGxContext context) + { + this.context = context; + IsMain = false; + } + + public void execute() + { + initialize(); + try + { + ExecutePrivate(); + } + catch (ReturnInErrorHandlerException) + { + this.cleanup(); + return; + } + } + + public void executeSubmit() + { + SubmitImpl(); + } + + protected override void ExecutePrivate() + { + /* GeneXus formulas */ + /* Output device settings */ + pr_default.close(0); + this.cleanup(); + } + + public override void cleanup() + { + CloseCursors(); + if (IsMain) + { + context.CloseConnections(); + } + ExitApp(); + } + + public override void initialize() + { + P000D2_A1GXM01_CtlName = new string[] { "" }; + pr_default = new DataStoreProvider(context, new aprocedure1__default(), + new Object[][] { + new Object[] { + P000D2_A1GXM01_CtlName + } + } + ); + /* GeneXus formulas. */ + } + + private IDataStoreProvider pr_default; + private string[] P000D2_A1GXM01_CtlName; + } + + public class aprocedure1__default : DataStoreHelperBase, IDataStoreHelper + { + public ICursor[] getCursors() + { + cursorDefinitions(); + return new Cursor[] { + new ForEachCursor(def[0]) + }; + } + + private static CursorDef[] def; + private void cursorDefinitions() + { + if (def == null) + { + Object[] prmP000D2; + prmP000D2 = new Object[] { + }; + def = new CursorDef[] { + new CursorDef("P000D2", "SELECT TOP 1 [GXM01_CtlName] FROM [GXM01] WHERE [GXM01_CtlName] = 'FCA010_DL_Name' ORDER BY [GXM01_CtlName] ",false, GxErrorMask.GX_NOMASK | GxErrorMask.GX_MASKLOOPLOCK, false, this,prmP000D2,1, GxCacheFrequency.OFF ,false,true ) + }; + } + } + + public void getResults(int cursor, + IFieldGetter rslt, + Object[] buf) + { + switch (cursor) + { + case 0: + ((string[])buf[0])[0] = rslt.getVarchar(1); + return; + } + } + + } + +} diff --git a/dotnet/test/DotNetCoreCmdTest/DotNetCoreCmdTest.csproj b/dotnet/test/DotNetCoreCmdTest/DotNetCoreCmdTest.csproj new file mode 100644 index 000000000..7d3f1be7d --- /dev/null +++ b/dotnet/test/DotNetCoreCmdTest/DotNetCoreCmdTest.csproj @@ -0,0 +1,43 @@ + + + net6.0;net8.0 + CS8032;1701;1702;NU1701 + Major + + + TRACE;NETCORE + + + DEBUG;TRACE;NETCORE + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + + PreserveNewest + + + + + + + + + + diff --git a/dotnet/test/DotNetCoreCmdTest/FileIO/FileSystemTest.cs b/dotnet/test/DotNetCoreCmdTest/FileIO/FileSystemTest.cs new file mode 100644 index 000000000..cb831da63 --- /dev/null +++ b/dotnet/test/DotNetCoreCmdTest/FileIO/FileSystemTest.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using GeneXus.Utils; + +namespace UnitTesting +{ + public class FileSystemTest + { +#pragma warning disable CA2211 // Non-constant fields should not be visible + protected static string BaseDir = FileUtil.GetStartupDirectory(); +#pragma warning restore CA2211 // Non-constant fields should not be visible + } + +} diff --git a/dotnet/test/DotNetCoreCmdTest/appsettings.json b/dotnet/test/DotNetCoreCmdTest/appsettings.json new file mode 100644 index 000000000..31bce50e5 --- /dev/null +++ b/dotnet/test/DotNetCoreCmdTest/appsettings.json @@ -0,0 +1,64 @@ +{ + "appSettings": { + "AppMainNamespace": "GeneXus.Programs", + "DataStore1": "Default", + "DataStore-Count": "1", + "DataStore-Default": "Default", + "Connection-Default-DBMS": "sqlserver", + "Connection-Default-Port": "", + "Connection-Default-LockTimeout": "0", + "Connection-Default-LockRetryCount": "10", + "Connection-Default-IsolationLevel": "CR", + "Connection-Default-Datasource": "", + "Connection-Default-User": "", + "Connection-Default-Password": "", + "Connection-Default-DB": "", + "Connection-Default-Schema": "", + "Connection-Default-Opts": "", + "Connection-Default-TrnInt": "1", + "DateFormat": "MDY", + "YearLimit": "1940", + "TimeAmPmFormat": "12", + "VER_STAMP": "20210602.093942", + "CS_BLOB_PATH": "PublicTempStorage", + "TMPMEDIA_DIR": "PrivateTempStorage", + "PRINT_LAYOUT_METADATA_DIR": "LayoutMetadata", + "StorageTimeZone": "1", + "LOGIN_AS_USERID": "0", + "LANGUAGE": "eng", + "LANG_NAME": "English", + "DECIMAL_POINT": ".", + "DATE_FMT": "MDY", + "CTOD_DATE_FMT": "L", + "Culture": "en-US", + "Theme": "Carmine", + "UseNamedParameters": "1", + "EnableIntegratedSecurity": "0", + "MAX_CURSOR": "100", + "STATIC_CONTENT": "", + "GX_BUILD_NUMBER": "11103481", + "CACHE_CONTENT_EXPIRATION": "36", + "ENABLE_MANAGEMENT": "0", + "COMPRESS_HTML": "1", + "IE_COMPATIBILITY_VIEW": "EmulateIE7", + "DocumentType": "HTML5", + "EXPOSE_METADATA": "0", + "SMART_CACHING": "0", + "wcf:serviceHostingEnvironment:useClassicReadEntityBodyMode": "true", + "HTTP_PROTOCOL": "Unsecure", + "SAMESITE_COOKIE": "Lax", + "CACHE_INVALIDATION_TOKEN": "20216211291931", + "CORS_ALLOW_ORIGIN": "https://normal-website.com", + "MY_CUSTOM_PTY": "DEFAULT_VALUE" + }, + "languages": { + "English": { + "code": "eng", + "culture": "en-US", + "date_fmt": "MDY", + "decimal_point": ".", + "thousand_sep": ",", + "time_fmt": "12" + } + } +} \ No newline at end of file From 1419a5c12999ed9a7de7ccefa3c958779391076a Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Tue, 14 Nov 2023 19:35:47 -0300 Subject: [PATCH 066/164] Support Spans for opentelemetry (#902) --- dotnet/DotNetStandardClasses.sln | 9 ++ .../src/dotnetcore/GxClasses/GxClasses.csproj | 3 +- .../GxClasses/Properties/AssemblyInfo.cs | 3 +- .../GxNetCoreStartup/GxNetCoreStartup.csproj | 2 +- .../GXOtel.Diagnostics.csproj | 23 ++++ .../GXOtel.Diagnostics/OtelSpan.cs | 112 ++++++++++++++++++ .../GXOtel.Diagnostics/OtelTracer.cs | 35 ++++++ .../GxClasses/Model/GXBaseObject.cs | 42 ++++++- .../GxClasses/Model/GXSilentTrn.cs | 104 ++++++++++++++-- .../GxClasses/Reorg/GXReorg.cs | 6 +- 10 files changed, 322 insertions(+), 17 deletions(-) create mode 100644 dotnet/src/dotnetcore/Providers/OpenTelemetry/Diagnostics/GXOtel.Diagnostics/GXOtel.Diagnostics.csproj create mode 100644 dotnet/src/dotnetcore/Providers/OpenTelemetry/Diagnostics/GXOtel.Diagnostics/OtelSpan.cs create mode 100644 dotnet/src/dotnetcore/Providers/OpenTelemetry/Diagnostics/GXOtel.Diagnostics/OtelTracer.cs diff --git a/dotnet/DotNetStandardClasses.sln b/dotnet/DotNetStandardClasses.sln index e159f7a5d..16834f162 100644 --- a/dotnet/DotNetStandardClasses.sln +++ b/dotnet/DotNetStandardClasses.sln @@ -253,6 +253,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetCoreChunkedTest", "te EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetPDFUnitTest", "test\DotNetPdfTest\DotNetPDFUnitTest.csproj", "{0FCFB078-5584-469F-92CC-61B0A6216D0D}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GXOtel.Diagnostics", "src\dotnetcore\Providers\OpenTelemetry\Diagnostics\GXOtel.Diagnostics\GXOtel.Diagnostics.csproj", "{A42066E8-DDB9-4767-AEFA-E6D13EFF051A}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetCoreCmdTest", "test\DotNetCoreCmdTest\DotNetCoreCmdTest.csproj", "{956402BD-AC8C-426E-961B-B77B3F3EDAEB}" EndProject Global @@ -617,10 +619,15 @@ Global {0FCFB078-5584-469F-92CC-61B0A6216D0D}.Debug|Any CPU.Build.0 = Debug|Any CPU {0FCFB078-5584-469F-92CC-61B0A6216D0D}.Release|Any CPU.ActiveCfg = Release|Any CPU {0FCFB078-5584-469F-92CC-61B0A6216D0D}.Release|Any CPU.Build.0 = Release|Any CPU + {A42066E8-DDB9-4767-AEFA-E6D13EFF051A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A42066E8-DDB9-4767-AEFA-E6D13EFF051A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A42066E8-DDB9-4767-AEFA-E6D13EFF051A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A42066E8-DDB9-4767-AEFA-E6D13EFF051A}.Release|Any CPU.Build.0 = Release|Any CPU {956402BD-AC8C-426E-961B-B77B3F3EDAEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {956402BD-AC8C-426E-961B-B77B3F3EDAEB}.Debug|Any CPU.Build.0 = Debug|Any CPU {956402BD-AC8C-426E-961B-B77B3F3EDAEB}.Release|Any CPU.ActiveCfg = Release|Any CPU {956402BD-AC8C-426E-961B-B77B3F3EDAEB}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -742,7 +749,9 @@ Global {2D615969-53E2-4B77-9A9A-75C33865CF76} = {1D6F1776-FF4B-46C2-9B3D-BC46CCF049DC} {5D2B1299-479F-430A-8D72-34D44FB299FD} = {1D6F1776-FF4B-46C2-9B3D-BC46CCF049DC} {0FCFB078-5584-469F-92CC-61B0A6216D0D} = {1D6F1776-FF4B-46C2-9B3D-BC46CCF049DC} + {A42066E8-DDB9-4767-AEFA-E6D13EFF051A} = {BBE020D4-C0FF-41A9-9EB1-D1EE12CC4BB8} {956402BD-AC8C-426E-961B-B77B3F3EDAEB} = {1D6F1776-FF4B-46C2-9B3D-BC46CCF049DC} + EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E18684C9-7D76-45CD-BF24-E3944B7F174C} diff --git a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj index f2cba9c17..43b211dc5 100644 --- a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj +++ b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj @@ -120,7 +120,6 @@ - @@ -163,7 +162,7 @@ - + diff --git a/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs b/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs index ee4196dbb..1eeded06b 100644 --- a/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs +++ b/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs @@ -14,4 +14,5 @@ [assembly: InternalsVisibleTo("GeneXus.Deploy.AzureFunctions.Handlers")] [assembly: InternalsVisibleTo("AzureFunctionsTest")] [assembly: InternalsVisibleTo("GXMessageBroker")] -[assembly: InternalsVisibleTo("DotNetCoreChunkedTest")] \ No newline at end of file +[assembly: InternalsVisibleTo("DotNetCoreChunkedTest")] +[assembly: InternalsVisibleTo("GeneXus.OpenTelemetry.Diagnostics")] \ No newline at end of file diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj b/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj index ebd33f667..9b0bd19a9 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj @@ -16,7 +16,7 @@ - + diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/Diagnostics/GXOtel.Diagnostics/GXOtel.Diagnostics.csproj b/dotnet/src/dotnetcore/Providers/OpenTelemetry/Diagnostics/GXOtel.Diagnostics/GXOtel.Diagnostics.csproj new file mode 100644 index 000000000..8c6a62190 --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/Diagnostics/GXOtel.Diagnostics/GXOtel.Diagnostics.csproj @@ -0,0 +1,23 @@ + + + + net8.0 + NETCORE; + Properties + false + GeneXus.OpenTelemetry.Diagnostics + OpenTelemetry Diagnostics + GeneXus.OpenTelemetry.Diagnostics + NU1605 + + + + + + + + + + + + diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/Diagnostics/GXOtel.Diagnostics/OtelSpan.cs b/dotnet/src/dotnetcore/Providers/OpenTelemetry/Diagnostics/GXOtel.Diagnostics/OtelSpan.cs new file mode 100644 index 000000000..4b35201d4 --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/Diagnostics/GXOtel.Diagnostics/OtelSpan.cs @@ -0,0 +1,112 @@ +using System; +using System.Diagnostics; +using GeneXus.Application; +using OpenTelemetry.Trace; +using static GeneXus.OpenTelemetry.Diagnostics.OtelTracer; + +namespace GeneXus.OpenTelemetry.Diagnostics +{ + public class OtelSpan + { + private Activity _activity; + + public enum SpanStatusCode + { + Unset, + Ok, + Error + } + public string Id + { get => _activity?.Id; } + + public bool IsAllDataRequested + { + get + { + if (_activity != null) + return _activity.IsAllDataRequested; + return false; + } + } + + public bool IsStopped + { get + { + if (_activity != null ) + return _activity.IsStopped; + return false; + } + } + + public short Kind + { get => (short)_activity?.Kind; } + + public string ParentId + { get => _activity?.ParentId; } + + public string ParentSpanId + { get => _activity?.ParentSpanId.ToString(); } + + public string TraceId + { get => _activity?.TraceId.ToString(); } + + public short Status + { get => (short)_activity?.Status; } + + internal OtelSpan(Activity activity) + { + _activity = activity; + } + + public OtelSpan() + { + _activity = Activity.Current; + } + public void Start() + { + _activity?.Start(); + } + + public void Stop() + { + _activity?.Stop(); + } + public void RecordException(string message) + { + _activity.RecordException(new Exception(message)); + } + + public void SetTag(string property, string value) + { + _activity.SetTag(property, value); + } + public string GetTagItem(string property) + { + return _activity.GetTagItem(property).ToString(); + } + public void AddBaggage(string property, string value) + { + _activity.AddBaggage(property, value); + } + public string GetBaggageItem(string property) + { + return _activity.GetBaggageItem(property).ToString(); + } + public void SetStatus(SpanStatusCode spanStatusCode, string message) + { + _activity.SetStatus((ActivityStatusCode)spanStatusCode, message); + } + + public SpanStatusCode GetStatus() + { + return (SpanStatusCode)_activity.GetStatus().StatusCode; + } + + //ToDO + //public void AddEvent() + //{ + + //} + + } +} diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/Diagnostics/GXOtel.Diagnostics/OtelTracer.cs b/dotnet/src/dotnetcore/Providers/OpenTelemetry/Diagnostics/GXOtel.Diagnostics/OtelTracer.cs new file mode 100644 index 000000000..8ce722bef --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/Diagnostics/GXOtel.Diagnostics/OtelTracer.cs @@ -0,0 +1,35 @@ +using System.Diagnostics; +using GeneXus.Application; +using GeneXus.Attributes; + +namespace GeneXus.OpenTelemetry.Diagnostics +{ + [GXApi] + public class OtelTracer + { + public enum SpanType + { + Client, + Consumer, + Internal, + Producer, + Server + } + + public OtelSpan CreateSpan(string name, SpanType kind) + { + Activity activity = GXBaseObject.ActivitySource.StartActivity(name, (ActivityKind)kind); + return new OtelSpan(activity); + } + + public OtelSpan GetCurrent() + { + return new OtelSpan(Activity.Current); + } + + public bool HasListeners() + { + return GXBaseObject.ActivitySource.HasListeners(); + } + } +} diff --git a/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs b/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs index c6113f10d..6bd6a2911 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs @@ -2,6 +2,9 @@ using GeneXus.Encryption; using GeneXus.Http; using GeneXus.Mock; +#if NETCORE +using GeneXus.Services.OpenTelemetry; +#endif using GeneXus.Utils; using Jayrock.Json; #if NETCORE @@ -9,6 +12,7 @@ #endif using System; using System.Collections.Generic; +using System.Diagnostics; using System.Reflection; using System.Threading; @@ -23,10 +27,24 @@ public class GXBaseObject { static readonly IGXLogger log = GXLoggerFactory.GetLogger(); +#if NETCORE + internal static ActivitySource activitySource; +#endif private Dictionary callTargetsByObject = new Dictionary(); protected IGxContext _Context; bool _isMain; protected bool _isApi; +#if NETCORE + internal static ActivitySource ActivitySource { + get { + if (activitySource == null) + activitySource = new(OpenTelemetryService.GX_ACTIVITY_SOURCE_NAME); + return activitySource; + } + } +#endif + protected virtual bool GenOtelSpanEnabled() { return false; } + protected virtual void ExecuteEx() { if (GxMockProvider.Provider != null) @@ -35,11 +53,31 @@ protected virtual void ExecuteEx() if (GxMockProvider.Provider.Handle(_Context, this, parmInfo)) return; } - ExecutePrivate(); + ExecuteImpl(); } protected virtual void ExecutePrivate() { - + + } +#if NETCORE + private void ExecuteUsingSpanCode() + { + using (Activity activity = ActivitySource.StartActivity($"{this.GetType().FullName}.execute")) + { + ExecutePrivate(); + } + } +#endif + protected virtual void ExecuteImpl() + { +#if NETCORE + if (GenOtelSpanEnabled()) + ExecuteUsingSpanCode(); + else + ExecutePrivate(); +#else + ExecutePrivate(); +#endif } protected virtual void ExecutePrivateCatch(object stateInfo) { diff --git a/dotnet/src/dotnetframework/GxClasses/Model/GXSilentTrn.cs b/dotnet/src/dotnetframework/GxClasses/Model/GXSilentTrn.cs index 5732587c2..ceaf3ce9d 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/GXSilentTrn.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/GXSilentTrn.cs @@ -16,6 +16,8 @@ namespace GeneXus.Utils #endif using Configuration; using System.Globalization; + using GeneXus.Http; + using System.Diagnostics; public interface IGxSilentTrn { @@ -158,6 +160,7 @@ public IGxSilentTrn Transaction get {return trn;} set {trn = value;} } + public IGxSilentTrn getTransaction() { return trn; @@ -167,30 +170,105 @@ public void setTransaction(IGxSilentTrn t) dirties.Clear(); trn = t; } +#if NETCORE + protected virtual bool GenOtelSpanEnabled() { return false; } + private Activity StartSpan(string methodName) + { + if (GenOtelSpanEnabled()) + { + return InitializeSpan(methodName); + } + return null; + } + private void EndSpan(Activity activity) + { + if (GenOtelSpanEnabled()) + { + activity?.Stop(); + } + } + private Activity InitializeSpan(string methodName) + { + if (GenOtelSpanEnabled()) + { + return GXBaseObject.ActivitySource.StartActivity($"{this.GetType().FullName}.{methodName}"); + } + return null; + } +#endif public virtual void Save() { - if( Transaction != null) + if (Transaction != null) + { +#if NETCORE + Activity activity = StartSpan("Save"); +#endif Transaction.Save(); +#if NETCORE + EndSpan(activity); +#endif + } } public virtual bool Insert() { - if (Transaction != null) - return Transaction.Insert(); - return false; + if (Transaction != null) + { +#if NETCORE + Activity activity = StartSpan("Insert"); +#endif + try + { + return Transaction.Insert(); + } + finally + { +#if NETCORE + EndSpan(activity); + +#endif + } + } + return false; } public virtual bool Update() { if (Transaction != null) - return Transaction.Update(); - return false; + { +#if NETCORE + Activity activity = StartSpan("Update"); +#endif + try + { + return Transaction.Update(); + } + finally { +#if NETCORE + EndSpan(activity); +#endif + } + } + return false; } - public virtual bool InsertOrUpdate() - { - if (Transaction != null) - return Transaction.InsertOrUpdate(); + public virtual bool InsertOrUpdate() + { + if (Transaction != null) + { +#if NETCORE + Activity activity = StartSpan("InsertOrUpdate"); +#endif + try + { + return Transaction.InsertOrUpdate(); + } + finally { +#if NETCORE + EndSpan(activity); +#endif + } + } return false; } @@ -203,8 +281,14 @@ public virtual void Delete( ) { if( Transaction != null) { +#if NETCORE + Activity activity = StartSpan("Delete"); +#endif Transaction.SetMode("DLT") ; Transaction.Save(); +#if NETCORE + EndSpan(activity); +#endif } } public virtual bool Success() diff --git a/dotnet/src/dotnetframework/GxClasses/Reorg/GXReorg.cs b/dotnet/src/dotnetframework/GxClasses/Reorg/GXReorg.cs index e156745ad..1fa54132c 100644 --- a/dotnet/src/dotnetframework/GxClasses/Reorg/GXReorg.cs +++ b/dotnet/src/dotnetframework/GxClasses/Reorg/GXReorg.cs @@ -57,7 +57,11 @@ protected virtual void ExecutePrivate() { } - public IGxContext context + protected virtual void ExecuteImpl() + { + ExecutePrivate(); + } + public IGxContext context { get { return _Context; } set { _Context = value; } From 745cac6d8587a5d8cf7354ed7feb6ca746f989fb Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Thu, 16 Nov 2023 09:50:29 -0300 Subject: [PATCH 067/164] Upgrade from .NET 8 Preview to .NET 8 Release. (#907) * Upgrade from .NET 8 Preview to .NET 8 Release. * Update README.md. --- .github/workflows/Build.yml | 2 +- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/fortify-net-framework.yml | 2 +- .github/workflows/fortify.yml | 2 +- README.md | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/Build.yml b/.github/workflows/Build.yml index 7466e8623..edfb8415f 100644 --- a/.github/workflows/Build.yml +++ b/.github/workflows/Build.yml @@ -48,7 +48,7 @@ jobs: - name: Install .NET 8 uses: actions/setup-dotnet@v3 with: - dotnet-version: '8.0.100-rc.1.23455.8' + dotnet-version: '8.0.100' - name: Calculate environment variables id: buildVariables diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index ed0cd3f68..70b0c49ec 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -58,7 +58,7 @@ jobs: - name: Install .NET 8 uses: actions/setup-dotnet@v3 with: - dotnet-version: '8.0.100-rc.1.23455.8' + dotnet-version: '8.0.100' - name: Create temporary solution run: | diff --git a/.github/workflows/fortify-net-framework.yml b/.github/workflows/fortify-net-framework.yml index d1c37d84c..8d4a1ce26 100644 --- a/.github/workflows/fortify-net-framework.yml +++ b/.github/workflows/fortify-net-framework.yml @@ -41,7 +41,7 @@ jobs: - name: Install .NET 8 uses: actions/setup-dotnet@v3 with: - dotnet-version: '8.0.100-preview.3.23178.7' + dotnet-version: '8.0.100' - name: Create temporal solution run: | diff --git a/.github/workflows/fortify.yml b/.github/workflows/fortify.yml index 946f6482d..b2f08d3b8 100644 --- a/.github/workflows/fortify.yml +++ b/.github/workflows/fortify.yml @@ -41,7 +41,7 @@ jobs: - name: Install .NET 8 uses: actions/setup-dotnet@v3 with: - dotnet-version: '8.0.100-preview.3.23178.7' + dotnet-version: '8.0.100' - name: Create temporal solution run: | diff --git a/README.md b/README.md index 9324fe365..04de49d5b 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ This repository contains projects for .NET and .NET Framework. It is organized a # How to build ## Requirements -- Visual Studio 2022 (17.6.1 if using .NET 8 up to preview 3 or 17.7 if using .NET 8 last preview). +- Visual Studio 2022 (17.8 or higher). - .NET 6 & .NET 8 - .NET Framework 4.7 DevPack From b11154794e236fbf23103ac157fe3beaa29c3ef6 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Thu, 16 Nov 2023 15:34:44 -0300 Subject: [PATCH 068/164] Include defensive programming to handle unclosed tags (#900) * Include defensive programming to handle unclosed tags when the 'WriteElement' method receives a null value * Add the same defensive programming to handle unclosed tags on .NET. --- .../GxClasses/Domain/GXXmlReadWrite.cs | 6 ++- .../GxClasses/Domain/GXXmlReadWrite.cs | 6 ++- .../DotNetUnitTest/Domain/XMLWriterTest.cs | 49 +++++++++++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 dotnet/test/DotNetUnitTest/Domain/XMLWriterTest.cs diff --git a/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs b/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs index aa04926c8..2c5fe2630 100644 --- a/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs +++ b/dotnet/src/dotnetcore/GxClasses/Domain/GXXmlReadWrite.cs @@ -1132,7 +1132,7 @@ internal void AppendNode(GXSOAPContext ctx, Node node, int extent) char[] trimChars = { '\t', ' ' }; - if (node.NodeType != ElementType) return; + if (node==null || node.NodeType != ElementType) return; switch (node.NodeType) { case ElementType: @@ -2131,6 +2131,10 @@ string removeUnallowedChars( string s) public short WriteElement (string Name, string Value) { WriteStartElement(Name); + if (Value==null) + { + Value = string.Empty; + } valueBuffer = Value; return 0; } diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs index ce2e02ec0..a194195ae 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GXXmlReadWrite.cs @@ -2137,6 +2137,10 @@ string removeUnallowedChars( string s) public short WriteElement (string Name, string Value) { WriteStartElement(Name); + if (Value==null) + { + Value = string.Empty; + } valueBuffer = Value; return 0; } @@ -2150,7 +2154,7 @@ public short WriteElement (string Name, object Value) public short WriteElement (string Name) { - WriteElement (Name, ""); + WriteElement (Name, string.Empty); return 0; } diff --git a/dotnet/test/DotNetUnitTest/Domain/XMLWriterTest.cs b/dotnet/test/DotNetUnitTest/Domain/XMLWriterTest.cs new file mode 100644 index 000000000..b3e1ce1b0 --- /dev/null +++ b/dotnet/test/DotNetUnitTest/Domain/XMLWriterTest.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using GeneXus.Application; +using GeneXus.XML; +using Xunit; + +namespace UnitTesting +{ + public class XMLWriterTest : FileSystemTest + { + [Fact] + public void dfwpnumNullElementTest() + { + string content = dfwpnumTest(null, false); + Assert.Contains("", content, StringComparison.OrdinalIgnoreCase); + } + [Fact] + public void dfwpnumEmptyElementWithoutEndTest() + { + string content = dfwpnumTest("validValue", false); + Assert.Contains("validValue", content, StringComparison.OrdinalIgnoreCase); + } + internal string dfwpnumTest(string varcharValue, bool closeElements) + { + GxContext context = new GxContext(); + string fileName = Path.Combine(BaseDir, "dfwpnumTest.txt"); + GXXMLWriter GXSoapXMLWriter = new GXXMLWriter(context.GetPhysicalPath()); + GXSoapXMLWriter.Open(fileName); + GXSoapXMLWriter.WriteStartDocument("utf-8", 0); + GXSoapXMLWriter.WriteStartElement("SOAP-ENV:Envelope"); + GXSoapXMLWriter.WriteElement("varchar", varcharValue); + GXSoapXMLWriter.WriteAttribute("xmlns", "StorageExpiration"); + string sDateCnv = "0000-00-00"; + GXSoapXMLWriter.WriteElement("date", sDateCnv); + GXSoapXMLWriter.WriteAttribute("xmlns", "StorageExpiration"); + if (closeElements) + { + GXSoapXMLWriter.WriteEndElement(); + } + GXSoapXMLWriter.Close(); + return File.ReadAllText(fileName); + } + + } +} From cdf2e224c3f41468a02c6100b11e691c8b65bee3 Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Tue, 21 Nov 2023 15:17:11 -0300 Subject: [PATCH 069/164] Remove namespace from Otel span name. (#908) --- .../GxClasses.Web/Middleware/GXRouting.cs | 3 +-- .../Notifications/WebSocket/WSHandler.cs | 3 +-- .../OpenTelemetry/GeneXus.OpenTelemetry.csproj | 17 ++++++++--------- .../dotnetframework/GxClasses/Core/gxconfig.cs | 8 ++++++++ .../GxClasses/Model/GXBaseObject.cs | 11 ++++++++++- .../GxClasses/Model/GXSilentTrn.cs | 3 ++- 6 files changed, 30 insertions(+), 15 deletions(-) diff --git a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs index 8ffe0c2de..078fb58a5 100644 --- a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs +++ b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs @@ -377,8 +377,7 @@ public GxRestWrapper GetController(HttpContext context, ControllerInfo controlle GxContext gxContext = GxContext.CreateDefaultInstance(); gxContext.HttpContext = context; context.NewSessionCheck(); - string nspace; - Config.GetValueOf("AppMainNamespace", out nspace); + string nspace = Preferences.AppMainNamespace; String tmpController = controller; String addNspace = string.Empty; diff --git a/dotnet/src/dotnetcore/GxClasses.Web/Notifications/WebSocket/WSHandler.cs b/dotnet/src/dotnetcore/GxClasses.Web/Notifications/WebSocket/WSHandler.cs index eea674266..3a65e45bc 100644 --- a/dotnet/src/dotnetcore/GxClasses.Web/Notifications/WebSocket/WSHandler.cs +++ b/dotnet/src/dotnetcore/GxClasses.Web/Notifications/WebSocket/WSHandler.cs @@ -119,8 +119,7 @@ private bool ExecuteHandler(HandlerType type, Object[] parameters) { try { - string nSpace = string.Empty; - Config.GetValueOf("AppMainNamespace", out nSpace); + string nSpace = Preferences.AppMainNamespace; GXProcedure obj = null; try { diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/GeneXus.OpenTelemetry.csproj b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/GeneXus.OpenTelemetry.csproj index 6c23dac29..9ecede1d6 100644 --- a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/GeneXus.OpenTelemetry.csproj +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/GeneXus.OpenTelemetry.csproj @@ -1,14 +1,13 @@ - - net6.0;net8.0 - enable - enable - GeneXus.OpenTelemetry - OpenTelemetry GeneXus DotNet - GeneXus.OpenTelemetry.OpenTelemetry - NU1605 - + + net6.0;net8.0 + enable + GeneXus.OpenTelemetry + OpenTelemetry GeneXus DotNet + GeneXus.OpenTelemetry.OpenTelemetry + NU1605 + diff --git a/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs b/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs index 6a3789eaf..945975237 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs @@ -826,6 +826,14 @@ public class Preferences const string DEFAULT_DS = "Default"; static int httpclient_max_per_route = -1; static int sessionTimeout = -1; + internal static string AppMainNamespace + { + get + { + Config.GetValueOf("AppMainNamespace", out string nameSpace); + return nameSpace; + } + } internal static string DefaultDatastore { get diff --git a/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs b/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs index 6bd6a2911..17bd377bc 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs @@ -1,3 +1,4 @@ +using GeneXus.Configuration; using GeneXus.Data.NTier; using GeneXus.Encryption; using GeneXus.Http; @@ -60,9 +61,17 @@ protected virtual void ExecutePrivate() } #if NETCORE + internal static string GetObjectNameWithoutNamespace(string gxObjFullName) + { + string mainNamespace = Preferences.AppMainNamespace; + if (gxObjFullName.StartsWith(mainNamespace)) + gxObjFullName = gxObjFullName.Remove(0, mainNamespace.Length + 1); + return gxObjFullName; + } private void ExecuteUsingSpanCode() { - using (Activity activity = ActivitySource.StartActivity($"{this.GetType().FullName}.execute")) + string gxObjFullName = GetObjectNameWithoutNamespace(GetType().FullName); + using (Activity activity = ActivitySource.StartActivity($"{gxObjFullName}.execute")) { ExecutePrivate(); } diff --git a/dotnet/src/dotnetframework/GxClasses/Model/GXSilentTrn.cs b/dotnet/src/dotnetframework/GxClasses/Model/GXSilentTrn.cs index ceaf3ce9d..cb76d4193 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/GXSilentTrn.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/GXSilentTrn.cs @@ -191,7 +191,8 @@ private Activity InitializeSpan(string methodName) { if (GenOtelSpanEnabled()) { - return GXBaseObject.ActivitySource.StartActivity($"{this.GetType().FullName}.{methodName}"); + string gxObjFullName = GXBaseObject.GetObjectNameWithoutNamespace(GetType().FullName); + return GXBaseObject.ActivitySource.StartActivity($"{gxObjFullName}.{methodName}"); } return null; } From 9039c5fe74639c1180a687c46c5838e7dcc141b8 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Fri, 1 Dec 2023 06:54:42 -0300 Subject: [PATCH 070/164] Support the maximum precision for decimals at dfwpnum. (#899) * Support the maximum precision for decimals at dfwpnum. * Fix error in test. --- .../src/dotnetframework/GxClasses/Core/GXUtils.cs | 3 ++- dotnet/test/DotNetUnitTest/FileIO/DfrgFunctions.cs | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXUtils.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXUtils.cs index db1162f17..7b029ad64 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXUtils.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXUtils.cs @@ -771,6 +771,7 @@ public short dfwnext() return GX_ASCDEL_WRITEERROR; } } + const int MAX_DECIMAL_PRECISION = 29; public short dfwpnum(decimal num, int dec) { if (_writeStatus == FileIOStatus.Closed) @@ -778,7 +779,7 @@ public short dfwpnum(decimal num, int dec) GXLogging.Error(log, "Error ADF0004"); return GX_ASCDEL_INVALIDSEQUENCE; } - appendFld(StringUtil.Str(num, 18, dec).TrimStart(null)); + appendFld(StringUtil.Str(num, MAX_DECIMAL_PRECISION, dec).TrimStart(null)); return GX_ASCDEL_SUCCESS; } public short dfwptxt(string s, int len) diff --git a/dotnet/test/DotNetUnitTest/FileIO/DfrgFunctions.cs b/dotnet/test/DotNetUnitTest/FileIO/DfrgFunctions.cs index 855ddbd6b..97d67bdab 100644 --- a/dotnet/test/DotNetUnitTest/FileIO/DfrgFunctions.cs +++ b/dotnet/test/DotNetUnitTest/FileIO/DfrgFunctions.cs @@ -10,6 +10,20 @@ public class DfrgFunctions : FileSystemTest const string APPLICATIONS_CONTENT = "[ { \"Id\": \"4caaaed5-1160-4132-b54f-0191e527a84a\", \"Type\": 1, \"EnvironmentGUID\": \"b3730606-0f2a-4e8a-b395-d8fdf226def8\", \"IsNew\": false }]"; const string DOCUMENT_CONTENT = "Line 1Line 2Line 3"; const string MS923_CONTENT = "1234567890123"; + + [Fact] + public void dfwpnumTest() + { + GxContext context = new GxContext(); + string fileName = Path.Combine(BaseDir, "dfwpnumTest.txt"); + context.FileIOInstance.dfwopen(fileName, ",", "\"", 0, "UTF-8"); + context.FileIOInstance.dfwpnum(99999999999999999.5M, 5); + context.FileIOInstance.dfwnext(); + context.FileIOInstance.dfwclose(); + + string content = File.ReadAllText(fileName); + Assert.Contains("99999999999999999.5", content, StringComparison.OrdinalIgnoreCase); + } [Fact] public void dfrgtxtANSITest() { From 96717c31b8144c6e7212e49c2eeb3d10504b8ff0 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 6 Dec 2023 09:29:41 -0300 Subject: [PATCH 071/164] Conversion functions involving time must include the context parameter (#911) * Load service files during startup to better handle a request storm at the startup of kestrel. Conversion functions involving time must now include the context parameter. The use of GxContext.Current is deprecated and should be avoided. * Minor typo in message. --- .../GxClasses.Web/Middleware/GXRouting.cs | 40 +++++++---- .../GxClasses/Core/GXUtilsCommon.cs | 68 ++++++++++++++++--- .../GxClasses/Services/ReflectionHelper.cs | 2 +- 3 files changed, 85 insertions(+), 25 deletions(-) diff --git a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs index 078fb58a5..bd3ae4a37 100644 --- a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs +++ b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs @@ -58,6 +58,7 @@ public GXRouting(string baseURL) ServicesGroupSetting(); ServicesFunctionsMetadata(); GetAzureDeploy(); + SvcFiles(); } static public List GetRouteController(Dictionary apiPaths, @@ -396,7 +397,7 @@ public GxRestWrapper GetController(HttpContext context, ControllerInfo controlle bool privateDirExists = Directory.Exists(privateDir); GXLogging.Debug(log, $"PrivateDir:{privateDir} asssemblycontroller:{asssemblycontroller}"); - + string svcFile=null; if (privateDirExists && File.Exists(Path.Combine(privateDir, $"{asssemblycontroller.ToLower()}.grp.json"))) { controller = tmpController; @@ -411,9 +412,7 @@ public GxRestWrapper GetController(HttpContext context, ControllerInfo controlle else { string controllerLower = controller.ToLower(); - string svcFile = SvcFile($"{controller}{SvcExtension}"); - if (svcFile==null) - svcFile = SvcFile($"{controllerLower}{SvcExtension}"); + svcFile = SvcFile($"{controller}{SvcExtension}"); if (File.Exists(svcFile)) { string[] controllerAssemblyQualifiedName = new string(File.ReadLines(svcFile).First().SkipWhile(c => c != '"') @@ -445,22 +444,26 @@ public GxRestWrapper GetController(HttpContext context, ControllerInfo controlle GXLogging.Warn(log, $"Controller was not found"); return null; } - string SvcFile(string controller) + + private void SvcFiles() { - if (svcFiles == null) + svcFiles = new HashSet(new CaseInsensitiveStringEqualityComparer()); + foreach (string file in Directory.GetFiles(ContentRootPath, SvcExtensionPattern, SearchOption.AllDirectories)) { - svcFiles = new HashSet(); - foreach (string file in Directory.GetFiles(ContentRootPath, SvcExtensionPattern, SearchOption.AllDirectories)) - { - svcFiles.Add(file); - } + svcFiles.Add(file); } + } + string SvcFile(string controller) + { string fileName; - string controllerFullName = Path.Combine(ContentRootPath, controller); - if (svcFiles.TryGetValue(new FileInfo(controllerFullName).FullName, out fileName)) + string controllerFullName = new FileInfo(Path.Combine(ContentRootPath, controller)).FullName; + if (svcFiles.TryGetValue(controllerFullName, out fileName)) return fileName; else + { + GXLogging.Warn(log, "Service file not found:" + controllerFullName); return null; + } } public void ServicesGroupSetting() @@ -600,7 +603,18 @@ public string GAM } + internal class CaseInsensitiveStringEqualityComparer : IEqualityComparer + { + public bool Equals(string x, string y) + { + return string.Equals(x, y, StringComparison.OrdinalIgnoreCase); + } + public int GetHashCode(string obj) + { + return obj.ToLower().GetHashCode(); + } + } public static class AzureFeature { public const string AzureServerless = "AzureServerless"; diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs index 9f2919a80..94e679faa 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs @@ -2656,18 +2656,18 @@ public static DateTime CToD2(string value) } return nullDate; } - internal static DateTime CToDT2(string jsonDate) { + internal static DateTime CToDT2(string jsonDate, IGxContext context) { if (!string.IsNullOrEmpty(jsonDate) && (jsonDate.Contains(ISO_8601_TIME_SEPARATOR) || jsonDate.Contains(ISO_8601_TIME_SEPARATOR_1))) { - return CToT2(jsonDate); + return CToT2(jsonDate, context); } else { return CToD2(jsonDate); } } - public static DateTime CToT2(string value) + public static DateTime CToT2(string value, IGxContext context) { if (isNullJsonDate(value)) return nullDate; @@ -2684,38 +2684,76 @@ public static DateTime CToT2(string value) } } if (Preferences.useTimezoneFix()) - ret = fromUniversalTime(ret); + { + if (context==null) + ret = fromUniversalTime(ret); + else + ret = fromUniversalTime(ret, context); + } return ret; } } + //[Obsolete("CToT2 is deprecated, use CToT2(string, IGxContext) instead", false)] + public static DateTime CToT2(string value) + { + return CToT2(value, null); + } + //[Obsolete("TToC2 is deprecated, use TToC2(DateTime, IGxContext) instead", false)] public static string TToC2(DateTime dt) { return TToC2(dt, true); } + public static string TToC2(DateTime dt, IGxContext context) + { + return TToC2(dt, true, context); + } + //[Obsolete("TToC2 is deprecated, use TToC2(DateTime, bool, IGxContext) instead", false)] public static string TToC2(DateTime dt, bool toUTC) { - return TToCRest(dt, "0000-00-00T00:00:00", JsonDateFormat, toUTC); + return TToCRest(dt, "0000-00-00T00:00:00", JsonDateFormat, null, toUTC); + } + internal static string TToC2(DateTime dt, bool toUTC, IGxContext context) + { + return TToCRest(dt, "0000-00-00T00:00:00", JsonDateFormat, context, toUTC); } + //[Obsolete("TToC3 is deprecated, use TToC3(DateTime, IGxContext) instead", false)] public static string TToC3(DateTime dt) { return TToC3(dt, true); } + public static string TToC3(DateTime dt, IGxContext context) + { + return TToC3(dt, true, context); + } internal const string JsonDateFormatMillis = "yyyy-MM-ddTHH:mm:ss.fff"; internal const string JsonDateFormat = "yyyy-MM-ddTHH:mm:ss"; - + + //[Obsolete("TToC3 is deprecated, use TToC3(DateTime, bool, IGxContext) instead", false)] public static string TToC3(DateTime dt, bool toUTC) { - return TToCRest(dt, "0000-00-00T00:00:00.000", JsonDateFormatMillis, toUTC); + return TToCRest(dt, "0000-00-00T00:00:00.000", JsonDateFormatMillis, null, toUTC); + } + internal static string TToC3(DateTime dt, bool toUTC, IGxContext context) + { + return TToCRest(dt, "0000-00-00T00:00:00.000", JsonDateFormatMillis, context, toUTC); } - static string TToCRest(DateTime dt, String nullString, String formatStr, bool toUTC=true) + static string TToCRest(DateTime dt, String nullString, String formatStr, IGxContext context, bool toUTC=true) { if (dt == nullDate) return FormatEmptyDate(nullString); else { - DateTime ret = Preferences.useTimezoneFix() ? (toUTC ? toUniversalTime(dt) : dt) : dt; + DateTime ret; + if (context != null) + { + ret = Preferences.useTimezoneFix() ? (toUTC ? toUniversalTime(dt, context) : dt) : dt; + } + else + { + ret = Preferences.useTimezoneFix() ? (toUTC ? toUniversalTime(dt) : dt) : dt; + } return ret.ToString(formatStr, CultureInfo.InvariantCulture); } } @@ -3536,7 +3574,7 @@ static private bool isNullDateCompatible(DateTime dt) else return isNullDate(dt); } - + //[Obsolete("fromUniversalTime is deprecated, use fromUniversalTime(DateTime, IGxContext) instead", false)] static public DateTime fromUniversalTime(DateTime dt) { #if NODATIME @@ -3545,7 +3583,15 @@ static public DateTime fromUniversalTime(DateTime dt) return isNullDateCompatible(dt) ? dt : fromUniversalTime(dt, GxContext.Current.GetOlsonTimeZone()); #endif } - + static public DateTime fromUniversalTime(DateTime dt, IGxContext context) + { +#if NODATIME + return isNullDateCompatible(dt) ? dt : fromUniversalTime(dt, context.GetTimeZone()); +#else + return isNullDateCompatible(dt) ? dt : fromUniversalTime(dt, context.GetOlsonTimeZone()); +#endif + } + //[Obsolete("toUniversalTime is deprecated, use toUniversalTime(DateTime, IGxContext) instead", false)] static public DateTime toUniversalTime(DateTime dt) { #if NODATIME diff --git a/dotnet/src/dotnetframework/GxClasses/Services/ReflectionHelper.cs b/dotnet/src/dotnetframework/GxClasses/Services/ReflectionHelper.cs index a7a9a1b34..80c093834 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/ReflectionHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/ReflectionHelper.cs @@ -150,7 +150,7 @@ private static object ConvertSingleJsonItem(object value, Type newType, IGxConte else if (newType == typeof(DateTime)) { string jsonDate = value as string; - return DateTimeUtil.CToDT2(jsonDate); + return DateTimeUtil.CToDT2(jsonDate, context); } else if (newType == typeof(Geospatial)) { From 6126928233bae182660d0b208213efa1cccb9fcc Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 6 Dec 2023 09:31:53 -0300 Subject: [PATCH 072/164] Bump version to 1.28 after creating branch for v18u7 --- dotnet/Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/Directory.Build.props b/dotnet/Directory.Build.props index 03e14d90e..b1007160e 100644 --- a/dotnet/Directory.Build.props +++ b/dotnet/Directory.Build.props @@ -3,7 +3,7 @@ 11.0.0.0 1 $([MSBuild]::Add($(MajorFileVersion), 100)) - 27 + 28 $(COMMIT_NUMBER) 0 $(MajorFileVersion).$(MinorFileVersion).$(PatchFileVersion) From b397e6ff822bdd4acf79c83045fae81fc596e0aa Mon Sep 17 00:00:00 2001 From: sgrampone <30872877+sgrampone@users.noreply.github.com> Date: Wed, 6 Dec 2023 15:16:58 -0300 Subject: [PATCH 073/164] Update BouncyCastle dependency on SecurityApi modules (#904) * Fix JWT wrongly failing test * Change Portable.BouncyCastle to BouncyCastle.Cryptography version 2.2.1 (latest) Delete VMPC Stream encryption algorithm beacuse of a bug on BouncyCastle --- .../GeneXusCryptography.csproj | 6 ++--- .../Symmetric/SymmetricStreamCipher.cs | 3 --- .../SymmetricStreamAlgorithm.cs | 12 +--------- .../GeneXusJWT/GeneXusJWT.csproj | 2 +- .../GeneXusXmlSignature.csproj | 4 +++- .../SecurityAPICommons.csproj | 2 +- .../Symmetric/TestStreamEncryption.cs | 24 +------------------ .../SecurityAPITest/SecurityAPITest.csproj | 2 +- 8 files changed, 11 insertions(+), 44 deletions(-) diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/GeneXusCryptography.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/GeneXusCryptography.csproj index f97230852..e5f90a379 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/GeneXusCryptography.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/GeneXusCryptography.csproj @@ -6,10 +6,10 @@ CA1031, CA1801, CA1724 GeneXus.SecurityApi.Cryptography + + + - - - \ No newline at end of file diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/Symmetric/SymmetricStreamCipher.cs b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/Symmetric/SymmetricStreamCipher.cs index faabdcd93..55b5a09e3 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/Symmetric/SymmetricStreamCipher.cs +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/Symmetric/SymmetricStreamCipher.cs @@ -152,9 +152,6 @@ private IStreamCipher getCipherEngine(SymmetricStreamAlgorithm algorithm) case SymmetricStreamAlgorithm.ISAAC: engine = new IsaacEngine(); break; - case SymmetricStreamAlgorithm.VMPC: - engine = new VmpcEngine(); - break; default: this.GetError().setError("SS005", "Cipher " + algorithm + " not recognised."); break; diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/SymmetricUtils/SymmetricStreamAlgorithm.cs b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/SymmetricUtils/SymmetricStreamAlgorithm.cs index 203be27da..b1e2c99e4 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/SymmetricUtils/SymmetricStreamAlgorithm.cs +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/SymmetricUtils/SymmetricStreamAlgorithm.cs @@ -15,7 +15,7 @@ namespace GeneXusCryptography.SymmetricUtils public enum SymmetricStreamAlgorithm { #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member - NONE, RC4, HC128, HC256, CHACHA20, SALSA20, XSALSA20, ISAAC, VMPC + NONE, RC4, HC128, HC256, CHACHA20, SALSA20, XSALSA20, ISAAC #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member } @@ -56,8 +56,6 @@ public static SymmetricStreamAlgorithm getSymmetricStreamAlgorithm(String symmet return SymmetricStreamAlgorithm.XSALSA20; case "ISAAC": return SymmetricStreamAlgorithm.ISAAC; - case "VMPC": - return SymmetricStreamAlgorithm.VMPC; default: error.setError("SSA01", "Unrecognized SymmetricStreamAlgorithm"); return SymmetricStreamAlgorithm.NONE; @@ -88,8 +86,6 @@ public static String valueOf(SymmetricStreamAlgorithm symmetrcStreamAlgorithm, E return "XSALSA20"; case SymmetricStreamAlgorithm.ISAAC: return "ISAAC"; - case SymmetricStreamAlgorithm.VMPC: - return "VMPC"; default: error.setError("SSA02", "Unrecognized SymmetricStreamAlgorithm"); return "Unrecognized algorithm"; @@ -133,11 +129,6 @@ public static int[] getKeySize(SymmetricStreamAlgorithm algorithm, Error error) keySize[1] = 32; keySize[2] = 8192; break; - case SymmetricStreamAlgorithm.VMPC: - keySize[0] = 0; - keySize[1] = 8; - keySize[2] = 6144; - break; default: error.setError("SSA03", "Unrecognized SymmetricStreamAlgorithm"); break; @@ -164,7 +155,6 @@ internal static bool usesIV(SymmetricStreamAlgorithm algorithm, Error error) case SymmetricStreamAlgorithm.SALSA20: case SymmetricStreamAlgorithm.CHACHA20: case SymmetricStreamAlgorithm.XSALSA20: - case SymmetricStreamAlgorithm.VMPC: return true; default: error.setError("SSA04", "Unrecognized SymmetricStreamAlgorithm"); diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusJWT/GeneXusJWT.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusJWT/GeneXusJWT.csproj index 02dd37267..598e1ce0f 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusJWT/GeneXusJWT.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusJWT/GeneXusJWT.csproj @@ -16,11 +16,11 @@ + - diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusXmlSignature/GeneXusXmlSignature.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusXmlSignature/GeneXusXmlSignature.csproj index 5cff1ade1..80c197f05 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusXmlSignature/GeneXusXmlSignature.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusXmlSignature/GeneXusXmlSignature.csproj @@ -6,9 +6,11 @@ CA1031 GeneXus.SecurityApi.XmlSignature + + + - diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/SecurityAPICommons.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/SecurityAPICommons.csproj index dcc841d69..3b984fcf5 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/SecurityAPICommons.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/SecurityAPICommons.csproj @@ -7,7 +7,7 @@ - + diff --git a/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Cryptography/Symmetric/TestStreamEncryption.cs b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Cryptography/Symmetric/TestStreamEncryption.cs index 29c007d9a..e90e28551 100644 --- a/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Cryptography/Symmetric/TestStreamEncryption.cs +++ b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Cryptography/Symmetric/TestStreamEncryption.cs @@ -1,4 +1,4 @@ -using SecurityAPITest.SecurityAPICommons.commons; +using SecurityAPITest.SecurityAPICommons.commons; using NUnit.Framework; using SecurityAPICommons.Config; using SecurityAPICommons.Keys; @@ -118,28 +118,6 @@ public void TestISAAC() testBulkAlgorithms("ISAAC", key8192, ""); } - [Test] - public void TestVMPC() - { - // key 8 o 6144, nonce 1...6144 bits - testBulkAlgorithms("VMPC", key8, IV64); - testBulkAlgorithms("VMPC", key8, IV128); - testBulkAlgorithms("VMPC", key8, IV192); - testBulkAlgorithms("VMPC", key8, IV256); - testBulkAlgorithms("VMPC", key8, IV512); - testBulkAlgorithms("VMPC", key8, IV1024); - testBulkAlgorithms("VMPC", key8, IV6144); - - testBulkAlgorithms("VMPC", key6144, IV64); - testBulkAlgorithms("VMPC", key6144, IV128); - testBulkAlgorithms("VMPC", key6144, IV192); - testBulkAlgorithms("VMPC", key6144, IV256); - testBulkAlgorithms("VMPC", key6144, IV512); - testBulkAlgorithms("VMPC", key6144, IV1024); - testBulkAlgorithms("VMPC", key6144, IV6144); - - } - private void testBulkAlgorithms(string algorithm, string key, string IV) { for (int i = 0; i < encodings.Length; i++) diff --git a/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/SecurityAPITest.csproj b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/SecurityAPITest.csproj index c8be949f4..c9262da04 100644 --- a/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/SecurityAPITest.csproj +++ b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/SecurityAPITest.csproj @@ -369,7 +369,7 @@ PreserveNewest - + PreserveNewest From 7c61fef91d550a3cfcfe6a1713041b1bbfb25217 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Fri, 8 Dec 2023 17:29:08 -0300 Subject: [PATCH 074/164] Enhance the performance of Log API methods (#912) * Remove unused configurationLoaded field. The configLoaded flag was not updated at the appropriate moment. * Enhance the performance of Log API methods * Remove unneeded reflection for GXLoggerFactory.GetLogger. * Enable test on DEBUG. * Temporarily disabling test. * Eliminate overhead in the Log API when logging is disabled. * Remove more unneeded reflection when creating logger instance. * Remove overhead at TraceRow method when log is turned off. * Improve GXLoggerLog4Net.TraceEnabled() method performance. * Performance improvement at methods GXLoggerLog4Net.Debug and GXLoggerLog4Net.Trace --- dotnet/DotNetStandardClasses.sln | 12 +- .../OpenTelemetry/OpenTelemetryService.cs | 2 +- .../Configuration/ExternalStorage.cs | 2 +- .../GxClasses/Core/GXApplication.cs | 1 - .../GxClasses/Core/GXUtilsCommon.cs | 4 +- .../GxClasses/Core/gxconfig.cs | 12 +- .../GxClasses/Data/GXDataCommon.cs | 4 +- .../GxClasses/Data/GXDataDb2.cs | 4 +- .../GxClasses/Data/GXDataDb2400.cs | 8 +- .../GxClasses/Data/GXDataHana.cs | 4 +- .../GxClasses/Data/GXDataInformix.cs | 4 +- .../GxClasses/Data/GXDataMysqlConnector.cs | 5 +- .../GxClasses/Data/GXDataMysqlDriverCS.cs | 5 +- .../GxClasses/Data/GXDataNTierADO.cs | 48 ++++---- .../GxClasses/Data/GXDataNTierService.cs | 6 +- .../GxClasses/Data/GXDataOracle.cs | 2 +- .../GxClasses/Data/GXDataPostgreSQL.cs | 4 +- .../GxClasses/Diagnostics/Log.cs | 112 +++++++++--------- .../GxClasses/Domain/GXLDAP.cs | 4 +- .../GxClasses/Domain/GxCollections.cs | 5 +- .../GxClasses/Helpers/GXLogging.cs | 31 ++++- .../GxClasses/Middleware/HandlerFactory.cs | 2 +- .../dotnetframework/GxClasses/Model/gxproc.cs | 2 +- .../GxClasses/Security/WebSecurity.cs | 4 +- .../GxClasses/Services/Caching/GxCache.cs | 8 +- .../dotnetframework/GxExcel/GxExcelEPPlus.cs | 4 +- .../src/dotnetframework/GxExcel/GxExcelI.cs | 14 +-- .../dotnetframework/GxExcel/GxExcelLite.cs | 4 +- .../GxMail/Exchange/Service.cs | 2 +- .../GxPdfReportsCS/PDFReportCommon.cs | 8 +- .../GxPdfReportsCS/PdfReportInterface.cs | 2 +- dotnet/test/benchmarks/LogTest/LogTest.cs | 53 +++++++++ dotnet/test/benchmarks/LogTest/LogTest.csproj | 36 ++++++ .../test/benchmarks/LogTest/appsettings.json | 64 ++++++++++ .../benchmarks/LogTest/log.console.config | 37 ++++++ 35 files changed, 376 insertions(+), 143 deletions(-) create mode 100644 dotnet/test/benchmarks/LogTest/LogTest.cs create mode 100644 dotnet/test/benchmarks/LogTest/LogTest.csproj create mode 100644 dotnet/test/benchmarks/LogTest/appsettings.json create mode 100644 dotnet/test/benchmarks/LogTest/log.console.config diff --git a/dotnet/DotNetStandardClasses.sln b/dotnet/DotNetStandardClasses.sln index 16834f162..bad8eab6d 100644 --- a/dotnet/DotNetStandardClasses.sln +++ b/dotnet/DotNetStandardClasses.sln @@ -257,6 +257,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GXOtel.Diagnostics", "src\d EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetCoreCmdTest", "test\DotNetCoreCmdTest\DotNetCoreCmdTest.csproj", "{956402BD-AC8C-426E-961B-B77B3F3EDAEB}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarks", "benchmarks", "{46DAAFD1-FAF5-4904-8EC5-406BE04E5538}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LogTest", "test\benchmarks\LogTest\LogTest.csproj", "{A1DBDCE0-4F09-445F-A202-9B260CDD46CF}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -627,7 +631,10 @@ Global {956402BD-AC8C-426E-961B-B77B3F3EDAEB}.Debug|Any CPU.Build.0 = Debug|Any CPU {956402BD-AC8C-426E-961B-B77B3F3EDAEB}.Release|Any CPU.ActiveCfg = Release|Any CPU {956402BD-AC8C-426E-961B-B77B3F3EDAEB}.Release|Any CPU.Build.0 = Release|Any CPU - + {A1DBDCE0-4F09-445F-A202-9B260CDD46CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A1DBDCE0-4F09-445F-A202-9B260CDD46CF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A1DBDCE0-4F09-445F-A202-9B260CDD46CF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A1DBDCE0-4F09-445F-A202-9B260CDD46CF}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -751,7 +758,8 @@ Global {0FCFB078-5584-469F-92CC-61B0A6216D0D} = {1D6F1776-FF4B-46C2-9B3D-BC46CCF049DC} {A42066E8-DDB9-4767-AEFA-E6D13EFF051A} = {BBE020D4-C0FF-41A9-9EB1-D1EE12CC4BB8} {956402BD-AC8C-426E-961B-B77B3F3EDAEB} = {1D6F1776-FF4B-46C2-9B3D-BC46CCF049DC} - + {46DAAFD1-FAF5-4904-8EC5-406BE04E5538} = {1D6F1776-FF4B-46C2-9B3D-BC46CCF049DC} + {A1DBDCE0-4F09-445F-A202-9B260CDD46CF} = {46DAAFD1-FAF5-4904-8EC5-406BE04E5538} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E18684C9-7D76-45CD-BF24-E3944B7F174C} diff --git a/dotnet/src/dotnetcore/GxClasses/Services/OpenTelemetry/OpenTelemetryService.cs b/dotnet/src/dotnetcore/GxClasses/Services/OpenTelemetry/OpenTelemetryService.cs index 3c8cacf39..3741c9a79 100644 --- a/dotnet/src/dotnetcore/GxClasses/Services/OpenTelemetry/OpenTelemetryService.cs +++ b/dotnet/src/dotnetcore/GxClasses/Services/OpenTelemetry/OpenTelemetryService.cs @@ -10,7 +10,7 @@ public interface IOpenTelemetryProvider public static class OpenTelemetryService { - private static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(typeof(OpenTelemetryService).FullName); private static string OPENTELEMETRY_SERVICE = "Observability"; public static string GX_ACTIVITY_SOURCE_NAME = "GeneXus.Tracing"; diff --git a/dotnet/src/dotnetframework/GxClasses/Configuration/ExternalStorage.cs b/dotnet/src/dotnetframework/GxClasses/Configuration/ExternalStorage.cs index d30bdc160..6357186e2 100644 --- a/dotnet/src/dotnetframework/GxClasses/Configuration/ExternalStorage.cs +++ b/dotnet/src/dotnetframework/GxClasses/Configuration/ExternalStorage.cs @@ -15,7 +15,7 @@ public class ExternalStorage : GxStorageProvider private GXService providerService; - static readonly IGXLogger logger = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger logger = GXLoggerFactory.GetLogger(); public ExternalStorage() { diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs index 08d94ef70..37d1e67c6 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs @@ -320,7 +320,6 @@ internal class GxApplication public class GxContext : IGxContext { private static IGXLogger log = null; - internal static bool configurationLoaded = Config.configLoaded; internal static string GX_SPA_REQUEST_HEADER = "X-SPA-REQUEST"; internal static string GX_SPA_REDIRECT_URL = "X-SPA-REDIRECT-URL"; internal const string GXLanguage = "GXLanguage"; diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs index 94e679faa..5b4ccb661 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs @@ -5597,7 +5597,7 @@ public string IniReadValue(string Section, string Key) #endif public static class GXDbFile { - static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(typeof(GXDbFile).FullName); private static Regex schemeRegex = new Regex("^" + Scheme + ":", RegexOptions.Compiled); @@ -5818,7 +5818,7 @@ public static string PathToUrl(string path, bool absUrl, IGxContext context = nu public static class GxImageUtil { - static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(typeof(GxImageUtil).FullName); private static Bitmap BitmapCreateFromStream(string filePathOrUrl) { Uri uri; diff --git a/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs b/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs index 945975237..a57cd234b 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs @@ -533,14 +533,15 @@ static NameValueCollection config { loadedConfigFile = configFileName; _config = loadConfig(configFileName, out logConfigSource); + configLoaded = true; if (!string.IsNullOrEmpty(logConfigSource)) logConfig(logConfigSource, out configuredFilename); else logConfig(configFileName, out configuredFilename); } +#if !NETCORE else { -#if !NETCORE if (GxContext.IsHttpContext && File.Exists(Path.Combine(GxContext.StaticPhysicalPath(), "web.config"))) { @@ -576,10 +577,13 @@ static NameValueCollection config logConfig(logFile, out configuredFilename); loadedConfigFile = Path.GetFullPath(file); _config = loadConfig(file); - } - + configLoaded = true; + } #else + else + { + string basePath = FileUtil.GetBasePath(); string currentDir = Directory.GetCurrentDirectory(); string startupDir = FileUtil.GetStartupDirectory(); @@ -635,8 +639,8 @@ static NameValueCollection config { //"Could not register encoding provider"; } -#endif } +#endif } } log = GXLoggerFactory.GetLogger(); diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs index 362374b08..58a261c3e 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs @@ -2174,7 +2174,7 @@ public class GxDataReader: IDataReader protected string stmt; protected GxConnectionCache cache; protected IGxConnection con; - protected GxArrayList block; + protected List block; protected string key; protected int pos; protected bool cached; @@ -2208,7 +2208,7 @@ public GxDataReader( IGxConnectionManager connManager, GxDataRecord dr, IGxConne reader=dr.GetCommand(con,stmt,parameters).ExecuteReader(); cache.SetAvailableCommand(stmt, false, dynStmt); open=true; - block=new GxArrayList(fetchSize); + block= new List(fetchSize); pos=-1; if (cached) { diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2.cs index 9bc3da634..a52b846f0 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2.cs @@ -115,7 +115,7 @@ protected override string BuildConnectionString(string datasourceName, string us public class GxDb2 : GxDataRecord { - private static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public static string SQL_NULL_DATE_10="0000-00-00"; public static string SQL_NULL_DATE_8="00000000"; @@ -523,7 +523,7 @@ sealed internal class Db2ConnectionWrapper : GxAbstractConnectionWrapper private static int changeConnState=-1; private static int changeConnStateExecuting = -1; private int openDataReaders; - static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public Db2ConnectionWrapper() { try diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2400.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2400.cs index dddf16097..b7397cd27 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2400.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2400.cs @@ -44,7 +44,7 @@ public override object GetValue(int i) } sealed internal class Db2ISeriesConnectionWrapper : GxAbstractConnectionWrapper { - static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public Db2ISeriesConnectionWrapper() { try @@ -120,7 +120,7 @@ public override DbDataAdapter CreateDataAdapter() public class GxDb2ISeries : GxDataRecord { - static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private bool m_UseCharInDate; public static string SQL_NULL_DATE="00000000"; private string m_InitialCatalog; @@ -767,7 +767,7 @@ public override string ToDbmsConstant(DateTime Value) } sealed internal class Db2ISeriesHISConnectionWrapper : GxAbstractConnectionWrapper { - static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public Db2ISeriesHISConnectionWrapper() : base(new MsDb2Connection()) { } @@ -826,7 +826,7 @@ public override DbDataAdapter CreateDataAdapter() public class GxISeriesHIS : GxDataRecord { - static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private bool m_UseCharInDate; private string m_InitialCatalog; private string m_SqlPackage; diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataHana.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataHana.cs index 256bd7994..967c738eb 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataHana.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataHana.cs @@ -13,7 +13,7 @@ namespace GeneXus.Data { public class GxHana : GxDataRecord { - static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); static Assembly _hanaAssembly; const string HanaDbTypeEnum = "Sap.Data.Hana.HanaDbType"; #if NETCORE @@ -320,7 +320,7 @@ sealed internal class HanaConnectionWrapper : GxAbstractConnectionWrapper { const string HanaIsolationEnum = "Sap.Data.Hana.HanaIsolationLevel"; - static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public HanaConnectionWrapper() { try diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataInformix.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataInformix.cs index 1355285af..8a731512f 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataInformix.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataInformix.cs @@ -18,7 +18,7 @@ namespace GeneXus.Data { public class GxInformix : GxDataRecord { - static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); static Assembly _ifxAssembly; #if NETCORE internal static string InformixAssemblyName = "Informix.Net.Core"; @@ -584,7 +584,7 @@ sealed internal class InformixConnectionWrapper : GxAbstractConnectionWrapper { private static int changeConnState = -1; private int openDataReaders; - static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public InformixConnectionWrapper() { try diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlConnector.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlConnector.cs index a804ae6c3..56d6684c2 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlConnector.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlConnector.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Data; using System.Data.Common; using System.Reflection; @@ -570,7 +571,7 @@ public GxMySQLConnectorDataReader(IGxConnectionManager connManager, GxDataRecord reader = cmd.ExecuteReader(); cache.SetAvailableCommand(stmt, false, dynStmt); open = true; - block = new GxArrayList(fetchSize); + block = new List(fetchSize); pos = -1; if (cached) { @@ -622,7 +623,7 @@ public GxMySQLConnectorCursorDataReader(IGxConnectionManager connManager, GxData reader = cmd.ExecuteReader(); cache.SetAvailableCommand(stmt, false, dynStmt); open = true; - block = new GxArrayList(fetchSize); + block = new List(fetchSize); pos = -1; if (cached) { diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlDriverCS.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlDriverCS.cs index a2688ea3b..956b7c011 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlDriverCS.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataMysqlDriverCS.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Data; using System.Data.Common; using System.Text; @@ -497,7 +498,7 @@ public GxMySQLDriverCSDataReader(IGxConnectionManager connManager, GxDataRecord reader = cmd.ExecuteReader(); cache.SetAvailableCommand(stmt, false, dynStmt); open = true; - block = new GxArrayList(fetchSize); + block = new List(fetchSize); pos = -1; if (cached) { @@ -542,7 +543,7 @@ public GxMySQLDriverCSCursorDataReader(IGxConnectionManager connManager, GxDataR reader = cmd.ExecuteReader(); cache.SetAvailableCommand(stmt, false, dynStmt); open = true; - block = new GxArrayList(fetchSize); + block = new List(fetchSize); pos = -1; if (cached) { diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierADO.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierADO.cs index 94b1b7e90..bb448e76e 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierADO.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierADO.cs @@ -210,11 +210,11 @@ public GXFatFieldGetter(GxCommand gxDbCommand) { _gxDbCommand = gxDbCommand; } - void TraceRow(params string[] list) + void TraceRow(Func buildMsg) { - if (_gxDbCommand.HasMoreRows) + if (GXLogging.TraceEnabled(log) && _gxDbCommand.HasMoreRows) { - GXLogging.Trace(log, list); + GXLogging.Trace(log, buildMsg); } } public IDataReader DataReader @@ -225,57 +225,57 @@ public IDataReader DataReader public short getShort(int id) { short value = _gxDbCommand.Db.GetShort(_gxDbCommand, _DR, id - 1); - TraceRow("getShort - index : ", id.ToString(), " value:", value.ToString()); + TraceRow(()=> $"getShort - index : {id} value:{value}"); return value; } public int getInt(int id) { int value = _gxDbCommand.Db.GetInt(_gxDbCommand, _DR, id - 1); - TraceRow("getInt - index : ", id.ToString(), " value:", value.ToString()); + TraceRow(() => $"getInt - index : {id} value:{value}"); return value; } public bool getBool(int id) { bool value = _gxDbCommand.Db.GetBoolean(_gxDbCommand, _DR, id - 1); - TraceRow("getBool - index : ", id.ToString(), " value:", value.ToString()); + TraceRow(() => $"getBool - index : {id} value:{value}"); return value; } public Guid getGuid(int id) { Guid value = _gxDbCommand.Db.GetGuid(_gxDbCommand, _DR, id - 1); - TraceRow("getGuid - index : ", id.ToString(), " value:", value.ToString()); + TraceRow(() => $"getGuid - index : {id} value:{value}"); return value; } public long getLong(int id) { long value = _gxDbCommand.Db.GetLong(_gxDbCommand, _DR, id - 1); - TraceRow("getLong - index : ", id.ToString(), " value:", value.ToString()); + TraceRow(() => $"getLong - index : {id} value:{value}"); return value; } public double getDouble(int id) { double value= _gxDbCommand.Db.GetDouble(_gxDbCommand, _DR, id - 1); - TraceRow("getDouble - index : ", id.ToString(), " value:", value.ToString()); + TraceRow(() => $"getDouble - index : {id} value:{value}"); return value; } public Decimal getDecimal(int id) { Decimal value= _gxDbCommand.Db.GetDecimal(_gxDbCommand, _DR, id - 1); - TraceRow("getDecimal - index : ", id.ToString(), " value:", value.ToString()); + TraceRow(() => $"getDecimal - index : {id} value:{value}"); return value; } public string getString(int id, int size) { String value = _gxDbCommand.Db.GetString(_gxDbCommand, _DR, id - 1, size); - TraceRow("getString - index : ", id.ToString(), " value:", (value!=null ? value.ToString(): string.Empty)); + TraceRow(() => $"getString - index : {id} value:{(value!=null ? value.ToString(): string.Empty)}"); return value; } public DateTime getDateTime(int id) { DateTime value = _gxDbCommand.Db.GetDateTime(_gxDbCommand, _DR, id - 1); - TraceRow("getDateTime - index : ", id.ToString(), " value:", value.ToString()); + TraceRow(() => $"getDateTime - index : {id} value:{value}"); return value; } public DateTime getDateTime(int id, Boolean precision) @@ -287,19 +287,19 @@ public DateTime getDateTime(int id, Boolean precision) else { value = _gxDbCommand.Db.GetDateTime(_gxDbCommand, _DR, id - 1); } - TraceRow("getDateTime - index : ", id.ToString(), " value:", value.ToString()); + TraceRow(() => $"getDateTime - index : {id} value:{value}"); return value; } public DateTime getDate(int id) { DateTime value = _gxDbCommand.Db.GetDate(_gxDbCommand, _DR, id - 1); - TraceRow("getDate - index : ", id.ToString(), " value:", value.ToString()); + TraceRow(() => $"getDate - index : {id} value:{value}"); return value; } public string getLongVarchar(int id) { string value = _gxDbCommand.Db.GetString(_gxDbCommand, _DR, id - 1); - TraceRow("getLongVarchar - index : ", id.ToString(), " value:", (value!=null ? value.ToString(): string.Empty)); + TraceRow(() => $"getLongVarchar - index : {id} value:{(value != null ? value.ToString() : string.Empty)}"); return value; } public DateTime getGXDateTime(int id, Boolean precision) @@ -309,7 +309,7 @@ public DateTime getGXDateTime(int id, Boolean precision) #else DateTime value = DateTimeUtil.DBserver2local(getDateTime(id, precision), _gxDbCommand.Conn.ClientTimeZone); #endif - TraceRow("getDateTime - index : ", id.ToString(), " value:", value.ToString()); + TraceRow(() => $"getDateTime - index : {id} value:{value}"); return value; } public DateTime getGXDateTime(int id) @@ -319,19 +319,19 @@ public DateTime getGXDateTime(int id) #else DateTime value = DateTimeUtil.DBserver2local(getDateTime(id, false), _gxDbCommand.Conn.ClientTimeZone); #endif - TraceRow("getGXDateTime - index : ", id.ToString(), " value:", value.ToString()); + TraceRow(() => $"getGXDateTime - index : {id} value:{value.ToString()}"); return value; } public DateTime getGXDate(int id) { DateTime value = getDate(id); - TraceRow("getGXDate - index : ", id.ToString(), " value:", value.ToString()); + TraceRow(() => $"getGXDate - index : {id} value:{value.ToString()}"); return value; } public string getBLOBFile(int id) { string value= getBLOBFile(id, "tmp", ""); - TraceRow("getBLOBFile - index : ", id.ToString(), " value:", (value!=null ? value.ToString() : string.Empty)); + TraceRow(() => $"getBLOBFile - index : {id} value:{(value != null ? value.ToString() : string.Empty)}"); return value; } @@ -339,7 +339,7 @@ public string getBLOBFile(int id, string extension, string name) { string fileName = FileUtil.getTempFileName(_gxDbCommand.Conn.BlobPath, name, extension, GxFileType.Private); String value = getBLOBFile(id, extension, name, fileName, true); - TraceRow("getBLOBFile - index : ", id.ToString(), " value:", (value!=null ? value.ToString() : string.Empty)); + TraceRow(() => $"getBLOBFile - index : {id} value:{(value != null ? value.ToString() : string.Empty)}"); return value; } @@ -389,7 +389,7 @@ private string getBLOBFile(int id, string extension, string name, string fileNam } streamClosed = true; - TraceRow("GetBlobFile fileName:" + fileName + ", retval bytes:" + retval); + TraceRow(() => $"GetBlobFile fileName:{fileName}, retval bytes:{retval}"); if (temporary) GXFileWatcher.Instance.AddTemporaryFile(file, _gxDbCommand.Conn.DataStore.Context); @@ -473,20 +473,20 @@ public string getMultimediaUri(int id, bool absUrl) public string getVarchar(int id) { string value = _gxDbCommand.Db.GetString(_gxDbCommand, _DR, id - 1); - TraceRow("getVarchar - index : ", id.ToString(), " value:", (value != null ? value.ToString() : string.Empty)); + TraceRow(() => $"getVarchar - index : {id} value:{(value != null ? value.ToString() : string.Empty)}"); return value; } public decimal getBigDecimal(int id, int dec) { decimal value =_gxDbCommand.Db.GetDecimal(_gxDbCommand, _DR, id - 1); - TraceRow("getBigDecimal - index : ", id.ToString(), " value:", value.ToString()); + TraceRow(() => $"getBigDecimal - index : {id} value:{value.ToString()}"); return value; } public IGeographicNative getGeospatial(int id) { IGeographicNative value = _gxDbCommand.Db.GetGeospatial(_gxDbCommand, _DR, id - 1); - TraceRow("getGeospatial - index : ", id.ToString(), " value:", (value != null ? value.ToString() : string.Empty)); + TraceRow(() => $"getGeospatial - index : {id} value:{(value != null ? value.ToString() : string.Empty)}"); return value; } diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierService.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierService.cs index 47b1348b5..570c47873 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierService.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierService.cs @@ -56,7 +56,7 @@ public ServiceCursorDef(string name, object query, GxErrorMask nmask, Object[] p public class GxServiceFactory { - protected static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + protected static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public static GxService Create(string id, string providerId, string serviceClass) { @@ -66,7 +66,7 @@ public static GxService Create(string id, string providerId, string serviceClass public class GxService : GxDataRecord { - protected static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + protected static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private Type m_ServiceType; private CursorDef m_CursorDef; @@ -307,7 +307,7 @@ public interface IServiceCommand sealed public class ServiceConnectionWrapper : GxAbstractConnectionWrapper { - static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public ServiceConnectionWrapper(Type runtimeClassType, String connectionString, GxConnectionCache connCache, IsolationLevel isolationLevel, String dataSource) { try diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataOracle.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataOracle.cs index bba71de26..a7fb9acdd 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataOracle.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataOracle.cs @@ -1436,7 +1436,7 @@ public override decimal GetDecimal(int i) #if !NETCORE sealed internal class MSOracleConnectionWrapper : GxAbstractConnectionWrapper { - static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); int oracle8 = -1; public MSOracleConnectionWrapper() : base(new MSOracleProvider.OracleConnection()) { diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataPostgreSQL.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataPostgreSQL.cs index 21791af2d..d61eedaf5 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataPostgreSQL.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataPostgreSQL.cs @@ -19,7 +19,7 @@ namespace GeneXus.Data { public class GxPostgreSql : GxDataRecord { - static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); const string ConnectionStringEncoding = "encoding"; private byte[] _buffer; static Assembly _npgsqlAssembly; @@ -586,7 +586,7 @@ public override string ConcatOp(int pos) } sealed internal class PostgresqlConnectionWrapper : GxAbstractConnectionWrapper { - static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public PostgresqlConnectionWrapper() { _connection = (IDbConnection)ClassLoader.CreateInstance(GxPostgreSql.NpgsqlAssembly, "Npgsql.NpgsqlConnection"); diff --git a/dotnet/src/dotnetframework/GxClasses/Diagnostics/Log.cs b/dotnet/src/dotnetframework/GxClasses/Diagnostics/Log.cs index d1947ed42..96b430062 100644 --- a/dotnet/src/dotnetframework/GxClasses/Diagnostics/Log.cs +++ b/dotnet/src/dotnetframework/GxClasses/Diagnostics/Log.cs @@ -1,6 +1,8 @@ using GeneXus.Attributes; using GeneXus.Configuration; using log4net; +using System.Collections.Concurrent; + #if NETCORE using GeneXus.Services.Log; using Microsoft.Extensions.Logging; @@ -21,103 +23,97 @@ private enum LogLevel Error = 20, Fatal = 30 } -#if NETCORE - static ILoggerFactory _instance = GXLogService.GetLogFactory(); -#endif - + + private const string LoggerPrefix = "$"; + private static readonly string DefaultRepository = LogManager.GetRepository().Name; + private static readonly string DefaultUserLogNamespace = Config.GetValueOf("USER_LOG_NAMESPACE", LogConfiguration.USER_LOG_TOPIC); + private static readonly IGXLogger GlobalLog = new GXLoggerLog4Net(LogManager.GetLogger(DefaultRepository, DefaultUserLogNamespace)); + private static ConcurrentDictionary LoggerDictionary = new ConcurrentDictionary() { [string.Empty] = GlobalLog }; internal static IGXLogger GetLogger(string topic) { - string defaultUserLogNamespace = Configuration.Config.GetValueOf("USER_LOG_NAMESPACE", LogConfiguration.USER_LOG_TOPIC); - string loggerName = defaultUserLogNamespace; - if (!string.IsNullOrEmpty(topic)) + if (LoggerDictionary.TryGetValue(topic, out IGXLogger logger)) { - loggerName = topic.StartsWith("$") ? topic.Substring(1) : string.Format("{0}.{1}", defaultUserLogNamespace, topic.Trim()); + return logger; } -#if NETCORE - if (_instance != null) + else { - return new GXLoggerMsExtensions(_instance.CreateLogger(loggerName)); + string loggerName = topic.StartsWith(LoggerPrefix) ? topic.Substring(1) : $"{DefaultUserLogNamespace}.{topic.Trim()}"; + logger = GXLoggerFactory.GetLogger(loggerName); + LoggerDictionary.TryAdd(topic, logger); + return logger; } - string defaultRepository = LogManager.GetRepository(System.Reflection.Assembly.GetEntryAssembly()).Name; -#else - string defaultRepository = LogManager.GetRepository().Name; -#endif - return new GXLoggerLog4Net(log4net.LogManager.GetLogger(defaultRepository, loggerName)); - } public static void Write(int logLevel, string message, string topic) { Write(message, topic, logLevel); } - public static void Write(string message, string topic, int logLevel) { - IGXLogger log = GetLogger(topic); LogLevel logLvl = (LogLevel)logLevel; + WriteImp(message, topic, logLvl); + } - switch (logLvl) + private static void WriteImp(string message, string topic, LogLevel logLvl) + { + if (logLvl != LogLevel.Off) { - case LogLevel.Off: - break; - case LogLevel.Trace: - GXLogging.Trace(log, message); - break; - case LogLevel.Debug: - GXLogging.Debug(log, message); - break; - case LogLevel.Info: - GXLogging.Info(log, message); - break; - case LogLevel.Warn: - GXLogging.Warn(log, message); - break; - case LogLevel.Error: - GXLogging.Error(log, message); - break; - case LogLevel.Fatal: - GXLogging.Critical(log, message); - break; - default: - GXLogging.Debug(log, message); - break; - } + IGXLogger log = GetLogger(topic); + switch (logLvl) + { + case LogLevel.Trace: + GXLogging.Trace(log, message); + break; + case LogLevel.Debug: + GXLogging.Debug(log, message); + break; + case LogLevel.Info: + GXLogging.Info(log, message); + break; + case LogLevel.Warn: + GXLogging.Warn(log, message); + break; + case LogLevel.Error: + GXLogging.Error(log, message); + break; + case LogLevel.Fatal: + GXLogging.Critical(log, message); + break; + default: + GXLogging.Debug(log, message); + break; + } + } } - + public static void Write(string message, string topic = "") { - IGXLogger log = GetLogger(topic); - GXLogging.Debug(log, message); + WriteImp(message, topic, LogLevel.Debug); } - + public static void Fatal(string message, string topic = "") { - IGXLogger log = GetLogger(topic); - GXLogging.Critical(log, message); + WriteImp(message, topic, LogLevel.Fatal); } public static void Error(string message, string topic = "") { - IGXLogger log = GetLogger(topic); - GXLogging.Error(log, message); + WriteImp(message, topic, LogLevel.Error); } public static void Warning(string message, string topic = "") { - IGXLogger log = GetLogger(topic); - GXLogging.Warn(log, message); + WriteImp(message, topic, LogLevel.Warn); } public static void Info(string message, string topic = "") { - IGXLogger log = GetLogger(topic); - GXLogging.Info(log, message); + WriteImp(message, topic, LogLevel.Info); } public static void Debug(string message, string topic = "") { - IGXLogger log = GetLogger(topic); - GXLogging.Debug(log, message); + WriteImp(message, topic, LogLevel.Debug); } } } diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GXLDAP.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GXLDAP.cs index 510b08b9d..c1238f28d 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GXLDAP.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GXLDAP.cs @@ -2,6 +2,8 @@ using System.Collections; using System.DirectoryServices; using System.Text; +using GeneXus.Data; + #if NETCORE using Novell.Directory.Ldap; #endif @@ -10,7 +12,7 @@ namespace GeneXus.Utils { public class GXLDAPClient { - static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); string _server; int _port; diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs index e14805a46..6a69c2d9e 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs @@ -2044,6 +2044,10 @@ public GxArrayList(int capacity) { innerArray = new List(capacity); } + internal GxArrayList(List list) + { + innerArray = list; + } public GxArrayList() { innerArray = new List(); @@ -2076,7 +2080,6 @@ public object Item(int index, int i) return innerArray[index][i]; } } - [CollectionDataContract(Name = "GxUnknownObjectCollection")] [KnownType(typeof(GxSimpleCollection))] [KnownType(typeof(GxStringCollection))] diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXLogging.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXLogging.cs index 0cfa76acf..97a9a1685 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXLogging.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXLogging.cs @@ -185,11 +185,15 @@ internal class GXLoggerLog4Net : IGXLogger const string ThreadNameNet6 = ".NET ThreadPool Worker"; const string ThreadId = "threadid"; #endif + private bool _traceEnabled = false; + private bool _debugEnabled = false; internal ILog log { get; set; } internal GXLoggerLog4Net(ILog logInstance) { log = logInstance; + _traceEnabled = log.Logger.IsEnabledFor(Level.Trace); + _debugEnabled = log.IsDebugEnabled; } void SetThreadIdForLogging() { @@ -216,15 +220,15 @@ void SetThreadIdForLogging() } #endif } - public bool IsTraceEnabled { get => TraceEnabled(); } + public bool IsTraceEnabled { get => _traceEnabled; } public bool IsErrorEnabled { get => ErrorEnabled(); } public bool IsWarningEnabled { get => WarningEnabled(); } - public bool IsDebugEnabled { get => DebugEnabled(); } + public bool IsDebugEnabled { get => _debugEnabled; } public bool IsInfoEnabled { get => InfoEnabled(); } public bool IsCriticalEnabled { get => CriticalEnabled(); } public bool TraceEnabled() { - return log.Logger.IsEnabledFor(Level.Trace); + return _traceEnabled; } public bool ErrorEnabled() { @@ -236,7 +240,7 @@ public bool WarningEnabled() } public bool DebugEnabled() { - return log.IsDebugEnabled; + return _debugEnabled; } public bool InfoEnabled() { @@ -506,6 +510,25 @@ internal static void Trace(IGXLogger logger, params string[] list) logger.LogTrace(string.Join(" ", list)); } } + internal static void Trace(IGXLogger logger, Func buildMsg) + { + if (logger != null) + { + if (logger.IsTraceEnabled) + { + string msg = buildMsg(); + logger.LogTrace(msg); + } + } + } + internal static bool TraceEnabled(IGXLogger logger) + { + if (logger != null) + return logger.IsTraceEnabled; + else + return false; + } + public static void Critical(IGXLogger logger, params string[] list) { if (logger != null) diff --git a/dotnet/src/dotnetframework/GxClasses/Middleware/HandlerFactory.cs b/dotnet/src/dotnetframework/GxClasses/Middleware/HandlerFactory.cs index 05c998433..ae00618d6 100644 --- a/dotnet/src/dotnetframework/GxClasses/Middleware/HandlerFactory.cs +++ b/dotnet/src/dotnetframework/GxClasses/Middleware/HandlerFactory.cs @@ -58,7 +58,7 @@ public bool IsReusable } class HandlerFactory : IHttpHandlerFactory { - private static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private static List GxNamespaces; public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated) diff --git a/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs b/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs index 7098f3803..9df552904 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs @@ -433,7 +433,7 @@ public class GxReportUtils public static int OUTPUT_RVIEWER_DLL = 2; public static int OUTPUT_PDF = 3; - static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); #if NETCORE const string PDF_LIBRARY_ITEXT8 = "ITEXT8"; diff --git a/dotnet/src/dotnetframework/GxClasses/Security/WebSecurity.cs b/dotnet/src/dotnetframework/GxClasses/Security/WebSecurity.cs index bb8c6a579..79c37b6de 100644 --- a/dotnet/src/dotnetframework/GxClasses/Security/WebSecurity.cs +++ b/dotnet/src/dotnetframework/GxClasses/Security/WebSecurity.cs @@ -16,7 +16,7 @@ namespace GeneXus.Web.Security [SecuritySafeCritical] public static class WebSecurityHelper { - static readonly IGXLogger _log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger _log = GXLoggerFactory.GetLogger(typeof(WebSecurityHelper).FullName); const int SecretKeyMinimumLength = 16; @@ -112,7 +112,7 @@ internal static bool VerifySecureSignedSDTToken(string cmpCtx, GxUserType value, public static class SecureTokenHelper { - static readonly IGXLogger _log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger _log = GXLoggerFactory.GetLogger(typeof(SecureTokenHelper).FullName); public enum SecurityMode { diff --git a/dotnet/src/dotnetframework/GxClasses/Services/Caching/GxCache.cs b/dotnet/src/dotnetframework/GxClasses/Services/Caching/GxCache.cs index 1bda980fe..63f293597 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/Caching/GxCache.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/Caching/GxCache.cs @@ -587,7 +587,13 @@ public class CacheItem public CacheItem() { } - + internal CacheItem(List data, bool hasnext, int blockSize, long sizeInBytes) + { + Data = new GxArrayList(data); + HasNext = hasnext; + BlockSize = blockSize; + SizeInBytes = sizeInBytes; + } public CacheItem(GxArrayList data, bool hasnext, int blockSize, long sizeInBytes) { Data = data; diff --git a/dotnet/src/dotnetframework/GxExcel/GxExcelEPPlus.cs b/dotnet/src/dotnetframework/GxExcel/GxExcelEPPlus.cs index c833dea5a..30363b39e 100644 --- a/dotnet/src/dotnetframework/GxExcel/GxExcelEPPlus.cs +++ b/dotnet/src/dotnetframework/GxExcel/GxExcelEPPlus.cs @@ -9,7 +9,7 @@ namespace GeneXus.Office.ExcelGXEPPlus public class ExcelDocument : IGxError, IExcelDocument { - static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private ExcelPackage p; public string dateFormat = "m/d/yy h:mm"; @@ -356,7 +356,7 @@ public short Init(string previousMsgError) public class ExcelCells : IExcelCells { - static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private IGxError m_errAccess; private int pWidth, pHeight; diff --git a/dotnet/src/dotnetframework/GxExcel/GxExcelI.cs b/dotnet/src/dotnetframework/GxExcel/GxExcelI.cs index 39be3b6f0..0309e828b 100644 --- a/dotnet/src/dotnetframework/GxExcel/GxExcelI.cs +++ b/dotnet/src/dotnetframework/GxExcel/GxExcelI.cs @@ -11,7 +11,7 @@ namespace GeneXus.Office public class ExcelDocumentI { - static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public short Index = -1; @@ -589,7 +589,7 @@ public IExcelCellWrapper(Interop.GXOFFICE2Lib.ExcelCells cell) this.cell = cell; } - #region IExcelCells Members + #region IExcelCells Members public DateTime Date { @@ -732,13 +732,13 @@ public short Underline } } - #endregion + #endregion } public class IExcelDocumentWrapper : IExcelDocument { - static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); Interop.GXOFFICE2Lib.IExcelDocument doc; @@ -746,7 +746,7 @@ public IExcelDocumentWrapper(Interop.GXOFFICE2Lib.IExcelDocument document) { doc = document; } - #region IExcelDocument Members + #region IExcelDocument Members public short Init(string previousMsgError) { @@ -928,13 +928,13 @@ public void CalculateFormulas() throw new NotImplementedException(); } - #endregion + #endregion } #endif public class ExcelUtils { - static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public static void Show(string xlsFileName) { Process p = new Process(); diff --git a/dotnet/src/dotnetframework/GxExcel/GxExcelLite.cs b/dotnet/src/dotnetframework/GxExcel/GxExcelLite.cs index 7e76fe0a9..61a9ff9a9 100644 --- a/dotnet/src/dotnetframework/GxExcel/GxExcelLite.cs +++ b/dotnet/src/dotnetframework/GxExcel/GxExcelLite.cs @@ -11,7 +11,7 @@ namespace GeneXus.Office.ExcelLite { public class ExcelCells : IExcelCells { - static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public ExcelCells(IGxError errAccess, object ef, int row, int col, int height, int width) { @@ -366,7 +366,7 @@ public int Color public class ExcelDocument : IGxError, IExcelDocument { - static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public static string nmspace; #if NETCORE public static string license = "FREE-LIMITED-KEY"; diff --git a/dotnet/src/dotnetframework/GxMail/Exchange/Service.cs b/dotnet/src/dotnetframework/GxMail/Exchange/Service.cs index 1208ba985..a63a18601 100644 --- a/dotnet/src/dotnetframework/GxMail/Exchange/Service.cs +++ b/dotnet/src/dotnetframework/GxMail/Exchange/Service.cs @@ -8,7 +8,7 @@ namespace GeneXus.Mail.Exchange public static class Service { - private static readonly IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(typeof(Service).FullName); static Service() { CertificateCallback.Initialize(); diff --git a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs index 0bb0a83c8..a7706e6dd 100644 --- a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs +++ b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs @@ -30,7 +30,7 @@ public abstract class PDFReportItextBase : IReportHandler { protected int lineHeight, pageLines; - static IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static IGXLogger log = GXLoggerFactory.GetLogger(); protected bool fontUnderline; protected bool fontStrikethru; @@ -899,7 +899,7 @@ protected float reconvertScale(float value) public class ParseINI { - static IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static IGXLogger log = GXLoggerFactory.GetLogger(); private static int MAX_LINE_LENGTH=255; private static String GENERAL="&General&"; @@ -1426,7 +1426,7 @@ public class Const public class NativeSharpFunctionsMS { - static IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static IGXLogger log = GXLoggerFactory.GetLogger(); public int shellExecute(String cmd, String fileName) { Process p = new Process(); @@ -1701,7 +1701,7 @@ public class Type1FontMetrics public class MSPDFFontDescriptor { - static IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static IGXLogger log = GXLoggerFactory.GetLogger(); private static String TRUE_TYPE_REGISTRY_SIGNATURE = "(TrueType)"; private static String REGISTRY_FONTS_ENTRY = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts"; // Fonts NT/2000 diff --git a/dotnet/src/dotnetframework/GxPdfReportsCS/PdfReportInterface.cs b/dotnet/src/dotnetframework/GxPdfReportsCS/PdfReportInterface.cs index d7c71c5d2..642ce03b0 100644 --- a/dotnet/src/dotnetframework/GxPdfReportsCS/PdfReportInterface.cs +++ b/dotnet/src/dotnetframework/GxPdfReportsCS/PdfReportInterface.cs @@ -5,7 +5,7 @@ namespace GeneXus.Printer public class GxReportBuilderPdf : IReportHandler { - static IGXLogger log = GXLoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); + static IGXLogger log = GXLoggerFactory.GetLogger(); string _appPath; protected IReportHandler _pdfReport; diff --git a/dotnet/test/benchmarks/LogTest/LogTest.cs b/dotnet/test/benchmarks/LogTest/LogTest.cs new file mode 100644 index 000000000..95bcd7f87 --- /dev/null +++ b/dotnet/test/benchmarks/LogTest/LogTest.cs @@ -0,0 +1,53 @@ +using System.Linq; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Reports; +using BenchmarkDotNet.Running; +using GeneXus.Diagnostics; +using Xunit; +namespace BenchmarkTest +{ +#if DEBUG + [Config(typeof(CustomBenchmarkConfig))] +#endif + public class LoggerBenchmark + { + [Params(100)] + public int N; + const int Debug = 5; + + [Benchmark] + public void LogOnPerformanceTest() + { + for ( int i = 0; i < N; i++) + { + Log.Write("Test Message", "Test Topic", Debug); + } + } + } + public class CustomBenchmarkConfig : ManualConfig + { + public CustomBenchmarkConfig() + { + WithOptions(ConfigOptions.DisableOptimizationsValidator); + } + } + public class PerformanceTests + { + const double MAX_NANOSECONDS = 150000; + [Fact(Skip = "Temporarily disabling this test for investigation/debugging purposes.")] + public void RunLoggerBenchmark() + { + Summary summary = BenchmarkRunner.Run(); + Assert.Single(summary.Reports); + + foreach (BenchmarkReport report in summary.Reports) + { + Assert.NotEmpty(report.AllMeasurements); + Measurement runMeasure = report.AllMeasurements.FirstOrDefault(); + Assert.InRange(runMeasure.Nanoseconds, low: 0, high: MAX_NANOSECONDS); + + } + } + } +} \ No newline at end of file diff --git a/dotnet/test/benchmarks/LogTest/LogTest.csproj b/dotnet/test/benchmarks/LogTest/LogTest.csproj new file mode 100644 index 000000000..2a90ace29 --- /dev/null +++ b/dotnet/test/benchmarks/LogTest/LogTest.csproj @@ -0,0 +1,36 @@ + + + + net8.0 + false + true + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + + diff --git a/dotnet/test/benchmarks/LogTest/appsettings.json b/dotnet/test/benchmarks/LogTest/appsettings.json new file mode 100644 index 000000000..31bce50e5 --- /dev/null +++ b/dotnet/test/benchmarks/LogTest/appsettings.json @@ -0,0 +1,64 @@ +{ + "appSettings": { + "AppMainNamespace": "GeneXus.Programs", + "DataStore1": "Default", + "DataStore-Count": "1", + "DataStore-Default": "Default", + "Connection-Default-DBMS": "sqlserver", + "Connection-Default-Port": "", + "Connection-Default-LockTimeout": "0", + "Connection-Default-LockRetryCount": "10", + "Connection-Default-IsolationLevel": "CR", + "Connection-Default-Datasource": "", + "Connection-Default-User": "", + "Connection-Default-Password": "", + "Connection-Default-DB": "", + "Connection-Default-Schema": "", + "Connection-Default-Opts": "", + "Connection-Default-TrnInt": "1", + "DateFormat": "MDY", + "YearLimit": "1940", + "TimeAmPmFormat": "12", + "VER_STAMP": "20210602.093942", + "CS_BLOB_PATH": "PublicTempStorage", + "TMPMEDIA_DIR": "PrivateTempStorage", + "PRINT_LAYOUT_METADATA_DIR": "LayoutMetadata", + "StorageTimeZone": "1", + "LOGIN_AS_USERID": "0", + "LANGUAGE": "eng", + "LANG_NAME": "English", + "DECIMAL_POINT": ".", + "DATE_FMT": "MDY", + "CTOD_DATE_FMT": "L", + "Culture": "en-US", + "Theme": "Carmine", + "UseNamedParameters": "1", + "EnableIntegratedSecurity": "0", + "MAX_CURSOR": "100", + "STATIC_CONTENT": "", + "GX_BUILD_NUMBER": "11103481", + "CACHE_CONTENT_EXPIRATION": "36", + "ENABLE_MANAGEMENT": "0", + "COMPRESS_HTML": "1", + "IE_COMPATIBILITY_VIEW": "EmulateIE7", + "DocumentType": "HTML5", + "EXPOSE_METADATA": "0", + "SMART_CACHING": "0", + "wcf:serviceHostingEnvironment:useClassicReadEntityBodyMode": "true", + "HTTP_PROTOCOL": "Unsecure", + "SAMESITE_COOKIE": "Lax", + "CACHE_INVALIDATION_TOKEN": "20216211291931", + "CORS_ALLOW_ORIGIN": "https://normal-website.com", + "MY_CUSTOM_PTY": "DEFAULT_VALUE" + }, + "languages": { + "English": { + "code": "eng", + "culture": "en-US", + "date_fmt": "MDY", + "decimal_point": ".", + "thousand_sep": ",", + "time_fmt": "12" + } + } +} \ No newline at end of file diff --git a/dotnet/test/benchmarks/LogTest/log.console.config b/dotnet/test/benchmarks/LogTest/log.console.config new file mode 100644 index 000000000..b52a4d897 --- /dev/null +++ b/dotnet/test/benchmarks/LogTest/log.console.config @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From f803e9a9b3a8ef9cf6b19d6c4bbaf4789ccad6a9 Mon Sep 17 00:00:00 2001 From: Alejandro Panizza Carve Date: Tue, 12 Dec 2023 14:56:39 -0300 Subject: [PATCH 075/164] - Change Type of Protocol property for API object (#896) Protocol property is now numeric. --- .../src/dotnetframework/GxClasses/Helpers/GXRestAPIClient.cs | 2 +- .../dotnetframework/GxClasses/Helpers/GxObjectProperties.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestAPIClient.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestAPIClient.cs index bc372fc0b..61c7a16da 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestAPIClient.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestAPIClient.cs @@ -45,7 +45,7 @@ public GXRestAPIClient() public string ResponseMessage { get => responseMessage; set => responseMessage = value; } public string HttpMethod { get => httpMethod; set => httpMethod = value; } - public string protocol = "REST"; + public int protocol = 1; private string httpMethod = "GET"; diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GxObjectProperties.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GxObjectProperties.cs index 01e9634cc..3ff58bd25 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GxObjectProperties.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GxObjectProperties.cs @@ -10,7 +10,7 @@ namespace GeneXus.Application public class GxObjectProperties { private GxLocation location = null; - private string protocol = "rest"; + private int protocol = 1; private string errorMessage = String.Empty; private int errorCode = 0; private int statusCode = 0; @@ -19,7 +19,7 @@ public class GxObjectProperties public string ErrorMessage { get => errorMessage; set => errorMessage = value; } public int ErrorCode { get => errorCode; set => errorCode = value; } public int StatusCode { get => statusCode; set => statusCode = value; } - public string Protocol { get => protocol; set => protocol = value; } + public int Protocol { get => protocol; set => protocol = value; } } public class GxObjectsConfiguration { From 9a48de9e92ddb1e5af6f82c1a892be00090eecb0 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Thu, 14 Dec 2023 17:35:37 -0300 Subject: [PATCH 076/164] The smart devices cache was not working for services in modules (#913) * The smart devices cache was not working for services in modules, as it failed to consider the full name when checking for smart devices data caching on the server side * Fix build error on .NET framework. --- dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs | 2 +- .../src/dotnetframework/GxClasses/Services/GxRestWrapper.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs b/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs index 17bd377bc..685d5971a 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs @@ -60,7 +60,6 @@ protected virtual void ExecutePrivate() { } -#if NETCORE internal static string GetObjectNameWithoutNamespace(string gxObjFullName) { string mainNamespace = Preferences.AppMainNamespace; @@ -68,6 +67,7 @@ internal static string GetObjectNameWithoutNamespace(string gxObjFullName) gxObjFullName = gxObjFullName.Remove(0, mainNamespace.Length + 1); return gxObjFullName; } +#if NETCORE private void ExecuteUsingSpanCode() { string gxObjFullName = GetObjectNameWithoutNamespace(GetType().FullName); diff --git a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs index 03fd8f122..0e68a2960 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs @@ -118,7 +118,7 @@ public virtual Task MethodBodyExecute(object key) gxobject.webExecute(); return Task.CompletedTask; } - if (!ProcessHeaders(_procWorker.GetType().Name)) + if (!ProcessHeaders(GXBaseObject.GetObjectNameWithoutNamespace(_procWorker.GetType().FullName))) return Task.CompletedTask; _procWorker.IsMain = true; if (bodyParameters == null) @@ -303,7 +303,7 @@ public virtual Task MethodUrlExecute(object key) { return Task.CompletedTask; } - if (!ProcessHeaders(_procWorker.GetType().Name)) + if (!ProcessHeaders(GXBaseObject.GetObjectNameWithoutNamespace(_procWorker.GetType().FullName))) return Task.CompletedTask; _procWorker.IsMain = true; IDictionary queryParameters = ReadQueryParameters(this._variableAlias); From d4fa4e035ff3cc7253e7dbc587d13427ac46d409 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Fri, 22 Dec 2023 16:06:45 -0300 Subject: [PATCH 077/164] Jayrock replacement with System.Text.Json in .NET (core) (#894) * Added new methods in preparation for Jayrock replacement. * Remove invalid EventHandler variable instance. It must be associated with each event. * Add a configuration setting, USE_JAYROCK, to replace Jayrock with System.Text.Json at runtime * Add new tests for deserialization using System.Text.Json. * Remove jayrock dependency from .NET (Core) classes and use System.Text.Json instead. The following methods have been changed to 'internal' due to their inclusion of 'jayrock' objects in their signature: GeneXus.Utils.Geospatial String JSONPointToWKT(JArray coords) GeneXus.Http.IHttpAjaxContext: JArray AttValues { get;} JObject HiddenValues { get;} JArray PropValues { get; } JObject WebComponents { get;} JObject Messages { get;} JArray Grids { get; } GeneXus.Http.HttpAjaxContext void appendLoadData(int SId, JObject Data) static JArray GetParmsJArray(Object[] parms) void ParseGXState(JObject tokenValues) GXAjaxCommand JObject JSONObject GXAjaxCommandCollection JArray JSONArray GeneXus.Http.GXJObject GeneXus.WebControls.GXWebGrid List GetColsPropsCommon() GeneXus.SD.Store.StoreManager static bool GetConfigValue(string key, JObject storeConfig, out string value) GeneXus.SD.Store.Util static JObject FromJSonString(string s) * Keep the same encoding algorithm for the JSON returned to the client-side, ensuring that it doesn't encode characters such as +, <, >, &, and double quotes ("). * Fix build error. * Replace the base class 'DictionaryBase' of 'JObject' with 'OrderedDictionary,' which implements the same logic as intended by 'JObject' for preserving the order of properties when serializing elements. * Fix: The JSON array contains a trailing comma at the end which is not supported in this mode. Keep compatibiliy with jayrock deserialization. * Change the WriteJSON method to serialize datetimes in the 'dd/MM/yyyy HH:mm:ss' format to maintain compatibility with the previous Jayrock serialization * Avoid printing duplicate messages when deserializing an invalid JSON * Register serialization converter for Geospatial data type. * Enhance compatibility for TextJsonSerializer.WriteJSON with JayRockJsonSerializer.WriteJSON, which invokes the ToString method of the datatype. This resolves the scenario when T is a string. * Boolean values must be serialized in lowercase to conform with JSON valid values * Fix merge errors with master. --- .../GxClasses.Web/GxClasses.Web.csproj | 10 - .../Notifications/WebSocket/WSHandler.cs | 6 +- .../src/dotnetcore/GxClasses/Domain/JArray.cs | 360 ++++++++++++++++++ .../src/dotnetcore/GxClasses/Domain/JNull.cs | 87 +++++ .../dotnetcore/GxClasses/Domain/JObject.cs | 123 ++++++ .../GxClasses/Helpers/GXGeographyCore.cs | 8 +- .../GxClasses/Properties/AssemblyInfo.cs | 4 +- dotnet/src/dotnetcore/GxMaps/GxMaps.csproj | 15 +- .../GxNetCoreStartup/GxNetCoreStartup.csproj | 11 - .../src/dotnetcore/GxSearch/GxSearch.csproj | 13 - .../Projects/StoreManager/StoreManager.csproj | 15 +- .../GxClasses/Core/GXApplication.cs | 2 + .../GxClasses/Core/GXUtilsCommon.cs | 13 +- .../GxClasses/Core/Web/HttpAjaxContext.cs | 37 +- .../GxClasses/Domain/GXGeolocation.cs | 4 + .../GxClasses/Domain/GXWindow.cs | 2 + .../GxClasses/Domain/GxCollections.cs | 10 +- .../GxClasses/Domain/GxGenericCollections.cs | 7 +- .../GxClasses/Helpers/GXNavigationHelper.cs | 2 + .../GxClasses/Helpers/GXRestAPIClient.cs | 4 +- .../GxClasses/Helpers/GXRestUtils.cs | 2 + .../GxClasses/Helpers/GXUtilsGeospatial.cs | 6 +- .../GxClasses/Helpers/JSONHelper.cs | 78 +++- .../GxClasses/Middleware/GXHttp.cs | 33 +- .../GxClasses/Middleware/GXHttpServices.cs | 2 + .../GxClasses/Model/GXBaseObject.cs | 2 + .../GxClasses/Model/GXSilentTrn.cs | 2 + .../GxClasses/Services/GxRestWrapper.cs | 2 + .../GxClasses/Services/ReflectionHelper.cs | 28 +- .../GxClasses/Services/Search/GXSearch.cs | 10 +- .../GxClasses/View/GXWebControls.cs | 32 +- .../GxSearch/SearchResultCollection.cs | 7 +- .../dotnetframework/GxWebSocket/WSHandler.cs | 4 + .../Store/Platforms/AppleStoreStoreManager.cs | 6 +- .../Store/Platforms/GooglePlayStoreManager.cs | 4 +- .../StoreManager/Store/StoreManager.cs | 8 +- .../Projects/StoreManager/Store/Util.cs | 6 +- .../DotNetCoreUnitTest.csproj | 8 - .../StringUtil/JsonUtilTest.cs | 319 ++++++++++++++++ .../StringUtil/StringUtilTests.cs | 6 +- .../StringUtil/type_SdtSDTGeneric.cs | 197 ++++++++++ .../test/DotNetCoreUnitTest/appsettings.json | 1 + .../test/DotNetUnitTest/DotNetUnitTest.csproj | 10 + 43 files changed, 1346 insertions(+), 160 deletions(-) create mode 100644 dotnet/src/dotnetcore/GxClasses/Domain/JArray.cs create mode 100644 dotnet/src/dotnetcore/GxClasses/Domain/JNull.cs create mode 100644 dotnet/src/dotnetcore/GxClasses/Domain/JObject.cs create mode 100644 dotnet/test/DotNetCoreUnitTest/StringUtil/JsonUtilTest.cs create mode 100644 dotnet/test/DotNetCoreUnitTest/StringUtil/type_SdtSDTGeneric.cs diff --git a/dotnet/src/dotnetcore/GxClasses.Web/GxClasses.Web.csproj b/dotnet/src/dotnetcore/GxClasses.Web/GxClasses.Web.csproj index b838905a3..eb48e4e06 100644 --- a/dotnet/src/dotnetcore/GxClasses.Web/GxClasses.Web.csproj +++ b/dotnet/src/dotnetcore/GxClasses.Web/GxClasses.Web.csproj @@ -44,15 +44,5 @@ - - - False - ..\libs\net8.0\Jayrock.dll - - - False - ..\libs\Jayrock.dll - - \ No newline at end of file diff --git a/dotnet/src/dotnetcore/GxClasses.Web/Notifications/WebSocket/WSHandler.cs b/dotnet/src/dotnetcore/GxClasses.Web/Notifications/WebSocket/WSHandler.cs index 3a65e45bc..84430c30a 100644 --- a/dotnet/src/dotnetcore/GxClasses.Web/Notifications/WebSocket/WSHandler.cs +++ b/dotnet/src/dotnetcore/GxClasses.Web/Notifications/WebSocket/WSHandler.cs @@ -1,3 +1,8 @@ +#if NETCORE +using GeneXus.Application; +#else +using Jayrock.Json; +#endif using System; using System.Collections.Generic; using System.Linq; @@ -11,7 +16,6 @@ using GeneXus.Procedure; using GeneXus.Services; using GeneXus.Utils; -using Jayrock.Json; namespace GeneXus.Http.WebSocket { diff --git a/dotnet/src/dotnetcore/GxClasses/Domain/JArray.cs b/dotnet/src/dotnetcore/GxClasses/Domain/JArray.cs new file mode 100644 index 000000000..8d53a77e4 --- /dev/null +++ b/dotnet/src/dotnetcore/GxClasses/Domain/JArray.cs @@ -0,0 +1,360 @@ +#region License, Terms and Conditions +// +// Jayrock - A JSON-RPC implementation for the Microsoft .NET Framework +// Written by Atif Aziz (atif.aziz@skybow.com) +// Copyright (c) Atif Aziz. All rights reserved. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 2.1 of the License, or (at your option) +// any later version. +// +// This library 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +#endregion + +namespace GeneXus.Application +{ + #region Imports + + using System; + using System.Collections; + using System.Globalization; + using System.Text; + using GeneXus.Utils; + + #endregion + + /// + /// An ordered sequence of values. This class also provides a number of + /// methods that can be found on a JavaScript Array for sake of parity. + /// + /// + /// + /// Public Domain 2002 JSON.org, ported to C# by Are Bjolseth (teleplan.no) + /// and re-adapted by Atif Aziz (www.raboof.com) + /// + + [ Serializable ] + internal class JArray : CollectionBase, IJayrockCompatible + { + public JArray() {} + + public JArray(IEnumerable collection) + { + foreach (object item in collection) + List.Add(item); + } + + public virtual object this[int index] + { + get { return InnerList[index]; } + set { List[index] = value; } + } + + public int Length + { + get { return Count; } + } + + public JArray Put(object value) + { + Add(value); + return this; + } + + public virtual void Add(object value) + { + List.Add(value); + } + public virtual void Add(int index, object value) + { + InnerList.Insert(index, value); + } + + public virtual void Remove(object value) + { + List.Remove(value); + } + + public virtual bool Contains(object value) + { + return List.Contains(value); + } + + public virtual int IndexOf(object value) + { + return List.IndexOf(value); + } + + public virtual bool HasValueAt(int index) + { + return this[index] != null; + } + + public virtual object GetValue(int index) + { + return GetValue(index, null); + } + + public virtual object GetValue(int index, object defaultValue) + { + object value = this[index]; + return value != null ? value : defaultValue; + } + + public virtual bool GetBoolean(int index) + { + return GetBoolean(index, false); + } + + public virtual bool GetBoolean(int index, bool defaultValue) + { + object value = GetValue(index); + if (value == null) return defaultValue; + return Convert.ToBoolean(value, CultureInfo.InvariantCulture); + } + + public virtual double GetDouble(int index) + { + return GetDouble(index, float.NaN); + } + + public virtual double GetDouble(int index, float defaultValue) + { + object value = GetValue(index); + if (value == null) return defaultValue; + return Convert.ToDouble(value, CultureInfo.InvariantCulture); + } + + public virtual int GetInt32(int index) + { + return GetInt32(index, 0); + } + + public virtual int GetInt32(int index, int defaultValue) + { + object value = GetValue(index); + if (value == null) return defaultValue; + return Convert.ToInt32(value, CultureInfo.InvariantCulture); + } + + public virtual string GetString(int index) + { + return GetString(index, string.Empty); + } + + public virtual string GetString(int index, string defaultValue) + { + object value = GetValue(index); + if (value == null) return defaultValue; + return value.ToString(); + } + + public virtual JArray GetArray(int index) + { + return (JArray) GetValue(index); + } + + public virtual JObject GetObject(int index) + { + return (JObject) GetValue(index); + } + + protected override void OnValidate(object value) + { + // + // Null values are allowed in a JSON array so don't delegate + // to the base class (CollectionBase) implementation since that + // disallows null entries by default. + // + } + + /// + /// Make an JSON external form string of this JsonArray. For + /// compactness, no unnecessary whitespace is added. + /// + /// + /// This method assumes that the data structure is acyclical. + /// + + public override string ToString() + { + return TextJsonSerializer.SerializeToJayrockCompatibleJson(this); + } + + + /// + /// Copies the elements to a new object array. + /// + + public virtual object[] ToArray() + { + return (object[]) ToArray(typeof(object)); + } + + /// + /// Copies the elements to a new array of the specified type. + /// + + public virtual Array ToArray(Type elementType) + { + return InnerList.ToArray(elementType); + } + + public virtual void Reverse() + { + InnerList.Reverse(); + } + + // + // Methods that imitate the JavaScript array methods. + // + + /// + /// Appends new elements to an array. + /// + /// + /// The new length of the array. + /// + /// + /// This method appends elements in the order in which they appear. If + /// one of the arguments is an array, it is added as a single element. + /// Use the method to join the elements from two or + /// more arrays. + /// + + public int Push(object value) + { + Add(value); + return Count; + } + + /// + /// Appends new elements to an array. + /// + /// + /// The new length of the array. + /// + /// + /// This method appends elements in the order in which they appear. If + /// one of the arguments is an array, it is added as a single element. + /// Use the method to join the elements from two or + /// more arrays. + /// + + public int Push(params object[] values) + { + if (values != null) + { + foreach (object value in values) + Push(value); + } + + return Count; + } + + /// + /// Removes the last element from an array and returns it. + /// + /// + /// If the array is empty, null is returned. + /// + + public object Pop() + { + if (Count == 0) + return null; + + object lastValue = InnerList[Count - 1]; + RemoveAt(Count - 1); + return lastValue; + } + + /// + /// Returns a new array consisting of a combination of two or more + /// arrays. + /// + + public JArray Concat(params object[] values) + { + JArray newArray = new JArray(this); + + if (values != null) + { + foreach (object value in values) + { + JArray arrayValue = value as JArray; + + if (arrayValue != null) + { + foreach (object arrayValueValue in arrayValue) + newArray.Push(arrayValueValue); + } + else + { + newArray.Push(value); + } + } + } + + return newArray; + } + + /// + /// Removes the first element from an array and returns it. + /// + + public object Shift() + { + if (Count == 0) + return null; + + object firstValue = InnerList[0]; + RemoveAt(0); + return firstValue; + } + + /// + /// Returns an array with specified elements inserted at the beginning. + /// + /// + /// The unshift method inserts elements into the start of an array, so + /// they appear in the same order in which they appear in the argument + /// list. + /// + + public JArray Unshift(object value) + { + List.Insert(0, value); + return this; + } + + /// + /// Returns an array with specified elements inserted at the beginning. + /// + /// + /// The unshift method inserts elements into the start of an array, so + /// they appear in the same order in which they appear in the argument + /// list. + /// + + public JArray Unshift(params object[] values) + { + if (values != null) + { + foreach (object value in values) + Unshift(value); + } + + return this; + } + } +} diff --git a/dotnet/src/dotnetcore/GxClasses/Domain/JNull.cs b/dotnet/src/dotnetcore/GxClasses/Domain/JNull.cs new file mode 100644 index 000000000..434ad643d --- /dev/null +++ b/dotnet/src/dotnetcore/GxClasses/Domain/JNull.cs @@ -0,0 +1,87 @@ +#region License, Terms and Conditions +// +// Jayrock - A JSON-RPC implementation for the Microsoft .NET Framework +// Written by Atif Aziz (atif.aziz@skybow.com) +// Copyright (c) Atif Aziz. All rights reserved. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 2.1 of the License, or (at your option) +// any later version. +// +// This library 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +#endregion + +namespace GeneXus.Application +{ + #region Imports + + using System; + //using System.Data.SqlTypes; + #endregion + + /// + /// Represent the one and only representation of the "null" value in JSON. + /// + + internal interface IJayrockCompatible + { + + } + [ Serializable ] + internal sealed class JNull : IJayrockCompatible + { + public static readonly JNull Value = new JNull(); + + public override string ToString() + { + return "null"; + } + + public static bool LogicallyEquals(object o) + { + // + // Equals a null reference. + // + + if (o == null) + return true; + + // + // Equals self, of course. + // + + if (o.Equals(JNull.Value)) + return true; + + // + // Equals the logical null value used in database applications. + // + + //if (Convert.IsDBNull(o)) + // return true; + + // + // Equals any type that supports logical nullability and whose + // current state is logically null. + // + + //INullable nullable = o as INullable; + + // if (nullable == null) + return false; + + //return nullable.IsNull; + } + + private JNull() {} + } +} diff --git a/dotnet/src/dotnetcore/GxClasses/Domain/JObject.cs b/dotnet/src/dotnetcore/GxClasses/Domain/JObject.cs new file mode 100644 index 000000000..e1aadfc30 --- /dev/null +++ b/dotnet/src/dotnetcore/GxClasses/Domain/JObject.cs @@ -0,0 +1,123 @@ +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 2.1 of the License, or (at your option) +// any later version. +// +// This library 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 Lesser General Public License for more +using System; +using System.Collections; +using System.Collections.Specialized; +using GeneXus.Utils; +namespace GeneXus.Application +{ + /// the implementation does internally try to remember the order in which + /// the keys were added in order facilitate human-readability as in when + /// an instance is rendered as text. + + [ Serializable ] + internal class JObject : OrderedDictionary, IJayrockCompatible + { + public JObject() {} + + /// + /// Construct a JObject from a IDictionary + /// + + public JObject(IDictionary members) + { + foreach (DictionaryEntry entry in members) + { + if (entry.Key == null) + throw new Exception("InvalidMemberException"); + + base.Add(entry.Key.ToString(), entry.Value); + } + + } + + public virtual bool HasMembers + { + get { return Count > 0; } + } + + + /// + /// Accumulate values under a key. It is similar to the Put method except + /// that if there is already an object stored under the key then a + /// JArray is stored under the key to hold all of the accumulated values. + /// If there is already a JArray, then the new value is appended to it. + /// In contrast, the Put method replaces the previous value. + /// + + public virtual JObject Accumulate(string name, object value) + { + if (name == null) + throw new ArgumentNullException(nameof(name)); + + object current = base[name]; + + if (current == null) + { + Put(name, value); + } + else + { + IList values = current as IList; + + if (values != null) + { + values.Add(value); + } + else + { + values = new JArray + { + current, + value + }; + Put(name, values); + } + } + + return this; + } + + /// + /// Put a key/value pair in the JObject. If the value is null, + /// then the key will be removed from the JObject if it is present. + /// + + public virtual JObject Put(string name, object value) + { + if (name == null) + throw new ArgumentNullException(nameof(name)); + + if (value != null) + this[name] = value; + else + Remove(name); + + return this; + } + + public virtual ICollection Names + { + get + { + return base.Keys; + } + } + + /// + /// Overridden to return a JSON formatted object as a string. + /// + + public override string ToString() + { + return TextJsonSerializer.SerializeToJayrockCompatibleJson(this); + } + + + } +} diff --git a/dotnet/src/dotnetcore/GxClasses/Helpers/GXGeographyCore.cs b/dotnet/src/dotnetcore/GxClasses/Helpers/GXGeographyCore.cs index 80d80a9e7..af51f7be6 100644 --- a/dotnet/src/dotnetcore/GxClasses/Helpers/GXGeographyCore.cs +++ b/dotnet/src/dotnetcore/GxClasses/Helpers/GXGeographyCore.cs @@ -2,7 +2,12 @@ using System.Collections; using System.Globalization; using System.Runtime.Serialization; +using System.Text.Json.Serialization; +#if NETCORE +using GeneXus.Application; +#else using Jayrock.Json; +#endif using GeographicLib; using NetTopologySuite.Geometries; using NetTopologySuite.IO; @@ -201,6 +206,7 @@ internal static object STRingN(object instance, int i) [KnownType(typeof(System.Double[]))] [KnownType(typeof(System.Collections.ArrayList))] [DataContract] + [JsonConverter(typeof(CustomGeospatialConverter))] public class Geospatial : IGeographicNative { static readonly IGXLogger log = GXLoggerFactory.GetLogger(); @@ -405,7 +411,7 @@ public double Latitude } } - public String JSONPointToWKT(JArray coords) + internal String JSONPointToWKT(JArray coords) { String[] jbuffer = new String[] { "", "" }; jbuffer[0] = ""; diff --git a/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs b/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs index 1eeded06b..1c8dea312 100644 --- a/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs +++ b/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs @@ -14,5 +14,7 @@ [assembly: InternalsVisibleTo("GeneXus.Deploy.AzureFunctions.Handlers")] [assembly: InternalsVisibleTo("AzureFunctionsTest")] [assembly: InternalsVisibleTo("GXMessageBroker")] +[assembly: InternalsVisibleTo("GeneXus.SD.Store.StoreManager")] [assembly: InternalsVisibleTo("DotNetCoreChunkedTest")] -[assembly: InternalsVisibleTo("GeneXus.OpenTelemetry.Diagnostics")] \ No newline at end of file +[assembly: InternalsVisibleTo("DotNetCoreChunkedTest")] +[assembly: InternalsVisibleTo("GeneXus.OpenTelemetry.Diagnostics")] diff --git a/dotnet/src/dotnetcore/GxMaps/GxMaps.csproj b/dotnet/src/dotnetcore/GxMaps/GxMaps.csproj index bf243af4a..2cf496f09 100644 --- a/dotnet/src/dotnetcore/GxMaps/GxMaps.csproj +++ b/dotnet/src/dotnetcore/GxMaps/GxMaps.csproj @@ -11,17 +11,8 @@ - - - - False - ..\libs\net8.0\Jayrock.dll - - - False - ..\libs\Jayrock.dll - - - + + + \ No newline at end of file diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj b/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj index 9b0bd19a9..5b87ea4a0 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj @@ -33,17 +33,6 @@ - - - False - ..\libs\net8.0\Jayrock.dll - - - False - ..\libs\Jayrock.dll - - - diff --git a/dotnet/src/dotnetcore/GxSearch/GxSearch.csproj b/dotnet/src/dotnetcore/GxSearch/GxSearch.csproj index e2ef170a8..961485e8c 100644 --- a/dotnet/src/dotnetcore/GxSearch/GxSearch.csproj +++ b/dotnet/src/dotnetcore/GxSearch/GxSearch.csproj @@ -28,17 +28,4 @@ - - - - False - ..\libs\net8.0\Jayrock.dll - - - False - ..\libs\Jayrock.dll - - - - \ No newline at end of file diff --git a/dotnet/src/dotnetcore/Projects/StoreManager/StoreManager.csproj b/dotnet/src/dotnetcore/Projects/StoreManager/StoreManager.csproj index 64129d3dd..05981128e 100644 --- a/dotnet/src/dotnetcore/Projects/StoreManager/StoreManager.csproj +++ b/dotnet/src/dotnetcore/Projects/StoreManager/StoreManager.csproj @@ -6,7 +6,9 @@ GeneXus.SD.Store StoreManager GeneXus.StoreManager.Core - + NETCORE + + @@ -36,15 +38,4 @@ - - - False - ..\..\libs\net8.0\Jayrock.dll - - - False - ..\..\libs\Jayrock.dll - - - diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs index 37d1e67c6..b1e9a1469 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs @@ -21,7 +21,9 @@ namespace GeneXus.Application #endif using GeneXus.Configuration; using GeneXus.Metadata; +#if !NETCORE using Jayrock.Json; +#endif using GeneXus.Http; using System.Collections.Specialized; using System.Collections.Generic; diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs index 5b4ccb661..a567717dc 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs @@ -5501,15 +5501,22 @@ public static void ErrorToMessages(string errorId, string errorDescription, GXBa } } public static void ErrorToMessages(string errorId, Exception ex, GXBaseCollection Messages) + { + ErrorToMessages(errorId, ex, Messages, true); + } + internal static void ErrorToMessages(string errorId, Exception ex, GXBaseCollection Messages, bool parseInnerExceptions) { if (Messages != null && ex != null) { StringBuilder str = new StringBuilder(); str.Append(ex.Message); - while (ex.InnerException != null) + if (parseInnerExceptions) { - str.Append(ex.InnerException.Message); - ex = ex.InnerException; + while (ex.InnerException != null) + { + str.Append(ex.InnerException.Message); + ex = ex.InnerException; + } } ErrorToMessages(errorId, str.ToString(), Messages); } diff --git a/dotnet/src/dotnetframework/GxClasses/Core/Web/HttpAjaxContext.cs b/dotnet/src/dotnetframework/GxClasses/Core/Web/HttpAjaxContext.cs index 4eebfe44d..ad3055ad2 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/Web/HttpAjaxContext.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/Web/HttpAjaxContext.cs @@ -1,7 +1,10 @@ namespace GeneXus.Http { using System; + using System.IO; +#if !NETCORE using Jayrock.Json; +#endif using System.Web; using GeneXus.Application; using GeneXus.Utils; @@ -41,12 +44,6 @@ public interface IHttpAjaxContext void AddStylesHidden(); void ajax_rsp_clear(); - JArray AttValues { get;} - JObject HiddenValues { get;} - JArray PropValues { get; } - JObject WebComponents { get;} - JObject Messages { get;} - JArray Grids { get; } void LoadFormVars(HttpContext localHttpContext); void disableJsOutput(); void enableJsOutput(); @@ -146,24 +143,24 @@ public class HttpAjaxContext : IHttpAjaxContext public string FormCaption { get; set; } - public JObject HiddenValues + internal JObject HiddenValues { get { return _HiddenValues; } } - public JArray AttValues + internal JArray AttValues { get { return _AttValues; } } - public JArray PropValues + internal JArray PropValues { get { return _PropValues; } } - public JObject WebComponents + internal JObject WebComponents { get { return _WebComponents; } } - public Hashtable LoadCommands + internal Hashtable LoadCommands { get { return _LoadCommands; } } - public JObject Messages + internal JObject Messages { get { return _Messages; } } - public JArray Grids + internal JArray Grids { get { return _Grids; } } - public JObject ComponentObjects + internal JObject ComponentObjects { get { return _ComponentObjects; } } public GXAjaxCommandCollection Commands { get { return commands; } } @@ -210,7 +207,7 @@ public void appendAjaxCommand(String cmdType, Object cmdData) commands.AppendCommand(new GXAjaxCommand(cmdType, cmdData)); } - public void appendLoadData(int SId, JObject Data) + internal void appendLoadData(int SId, JObject Data) { LoadCommands[SId] = Data; } @@ -667,7 +664,7 @@ internal string getJSONResponse(string cmpContext) return jsonCmdWrapper.ToString(); } - public static JArray GetParmsJArray(Object[] parms) + internal static JArray GetParmsJArray(Object[] parms) { JArray inputs = new JArray(); for (int i = 0; i < parms.Length; i++) @@ -744,7 +741,7 @@ public void LoadFormVars(HttpContext localHttpContext) } } - public void ParseGXState(JObject tokenValues) + internal void ParseGXState(JObject tokenValues) { if (tokenValues != null) { @@ -821,7 +818,7 @@ public string Content } } - public class GXJObject : JObject + internal class GXJObject : JObject { private bool base64Encoded; @@ -882,7 +879,7 @@ public object Data } } - public JObject JSONObject + internal JObject JSONObject { get { @@ -1027,7 +1024,7 @@ private GXAjaxCommand GetCommand(GXAjaxCommand cmd) return null; } - public JArray JSONArray + internal JArray JSONArray { get { diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GXGeolocation.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GXGeolocation.cs index e6c8e6aa2..3de8bcdec 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GXGeolocation.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GXGeolocation.cs @@ -3,7 +3,11 @@ using System.Text; using System.Net; using System.IO; +#if NETCORE +using GeneXus.Application; +#else using Jayrock.Json; +#endif using GeneXus.Utils; using System.Globalization; using GeneXus; diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GXWindow.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GXWindow.cs index bc9443380..f33c73abf 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GXWindow.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GXWindow.cs @@ -1,6 +1,8 @@ using GeneXus.Utils; using System; +#if !NETCORE using Jayrock.Json; +#endif namespace GeneXus.Application { public class GXWindow : IGxJSONAble diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs index 6a69c2d9e..10e24713f 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs @@ -8,6 +8,9 @@ namespace GeneXus.Utils using System.ComponentModel; using System.Data; using System.Globalization; +#if !NETCORE + using Jayrock.Json; +#endif using System.Linq; using System.Reflection; using System.Runtime.Serialization; @@ -19,7 +22,6 @@ namespace GeneXus.Utils using GeneXus.Http; using GeneXus.Metadata; using GeneXus.XML; - using Jayrock.Json; public class GxParameterCollection : IDataParameterCollection { @@ -235,7 +237,7 @@ public bool FromJSonString(string s, GXBaseCollection Messa } catch (Exception ex) { - GXUtil.ErrorToMessages("FromJson Error", ex, Messages); + GXUtil.ErrorToMessages("FromJson Error", ex, Messages, false); return false; } } @@ -706,7 +708,7 @@ public bool FromJSonString(string s, GXBaseCollection Messa } catch (Exception ex) { - GXUtil.ErrorToMessages("FromJson Error", ex, Messages); + GXUtil.ErrorToMessages("FromJson Error", ex, Messages, false); return false; } } @@ -1267,7 +1269,7 @@ public bool FromJSonString(string s, GXBaseCollection Messa } catch (Exception ex) { - GXUtil.ErrorToMessages("FromJson Error", ex, Messages); + GXUtil.ErrorToMessages("FromJson Error", ex, Messages, false); return false; } } diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxGenericCollections.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxGenericCollections.cs index 657b8feaa..b1d3a50fb 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxGenericCollections.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxGenericCollections.cs @@ -1,3 +1,6 @@ +#if !NETCORE +using Jayrock.Json; +#endif using System; using System.Collections; using System.Collections.Generic; @@ -5,7 +8,7 @@ using System.Xml.Serialization; using GeneXus.Application; using GeneXus.XML; -using Jayrock.Json; + namespace GeneXus.Utils { @@ -468,7 +471,7 @@ public bool FromJSonString(string s, GXBaseCollection Messa } catch (Exception ex) { - GXUtil.ErrorToMessages("FromJson Error", ex, Messages); + GXUtil.ErrorToMessages("FromJson Error", ex, Messages, false); return false; } } diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXNavigationHelper.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXNavigationHelper.cs index 1b755911c..218180e38 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXNavigationHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXNavigationHelper.cs @@ -1,7 +1,9 @@ namespace GeneXus.Application { using System; +#if !NETCORE using Jayrock.Json; +#endif using System.Collections.Generic; [Serializable] public class GXNavigationHelper diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestAPIClient.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestAPIClient.cs index 61c7a16da..295e266a0 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestAPIClient.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestAPIClient.cs @@ -109,7 +109,7 @@ public void AddQueryVar(String varName, Geospatial varValue) public void AddQueryVar(String varName, bool varValue) { - _queryVars[varName] = varValue.ToString(); + _queryVars[varName] = StringUtil.BoolToStr(varValue); } public void AddQueryVar(String varName, GxUserType varValue) @@ -164,7 +164,7 @@ public void AddBodyVar(String varName, long varValue) } public void AddBodyVar(String varName, bool varValue) { - _bodyVars[varName] = varValue.ToString(); + _bodyVars[varName] = StringUtil.BoolToStr(varValue); } public void AddBodyVar(String varName, Guid varValue) { diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestUtils.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestUtils.cs index 27e7b1928..e32d5f04b 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestUtils.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestUtils.cs @@ -9,7 +9,9 @@ using System.Text.Json.Serialization; #endif using System.IO; +#if !NETCORE using Jayrock.Json; +#endif using GeneXus.Configuration; namespace GeneXus.Utils diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXUtilsGeospatial.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXUtilsGeospatial.cs index b760d64ee..74e030fa4 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXUtilsGeospatial.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXUtilsGeospatial.cs @@ -1,11 +1,15 @@ using System; using System.Collections; +#if NETCORE +using GeneXus.Application; +#else +using Jayrock.Json; +#endif using System.Data.SqlTypes; using System.Globalization; using System.Reflection; using System.Runtime.Serialization; using GeneXus.Metadata; -using Jayrock.Json; #if NETCORE using GxClasses.Helpers; #endif diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/JSONHelper.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/JSONHelper.cs index a857c3f27..846101bf8 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/JSONHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/JSONHelper.cs @@ -3,13 +3,19 @@ using System.IO; using System.Runtime.Serialization.Json; using System.Text; +#if NETCORE +using GeneXus.Application; +#else using Jayrock.Json; +#endif using System.Runtime.Serialization; using GeneXus.Configuration; #if NETCORE using System.Buffers.Text; using System.Text.Json; using System.Text.Json.Serialization; +using System.Text.Encodings.Web; +using System.Globalization; #endif namespace GeneXus.Utils @@ -33,10 +39,20 @@ public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonS return JsonSerializer.Deserialize(ref reader, options); case JsonTokenType.StartObject: return JsonSerializer.Deserialize(ref reader, options); + case JsonTokenType.Number: + if (reader.TryGetInt32(out int l)) + return l; + else + if (reader.TryGetDecimal(out decimal d)) + return d; + else + return reader.GetDouble(); + case JsonTokenType.String: + return reader.GetString(); default: using (JsonDocument document = JsonDocument.ParseValue(ref reader)) { - return document.RootElement.Clone().ToString(); + return document.RootElement.Clone(); } } } @@ -46,6 +62,29 @@ public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOp throw new NotImplementedException(); } } + internal class CustomGeospatialConverter : JsonConverter + { + public override Geospatial Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => + throw new NotImplementedException("Deserialization is not supported."); + + public override void Write(Utf8JsonWriter writer, Geospatial value, JsonSerializerOptions options) + { + string stringValue = value?.ToString(); + JsonSerializer.Serialize(writer, stringValue, options); + } + } + internal class CustomDateTimeConverter : JsonConverter + { + public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + throw new NotImplementedException("Deserialization is not supported."); + } + + public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) + { + writer.WriteStringValue(Convert.ToString(value, CultureInfo.InvariantCulture)); //"dd/MM/yyyy HH:mm:ss" + } + } internal class TextJsonSerializer : GXJsonSerializer { internal override bool IsJsonNull(object jobject) @@ -56,14 +95,27 @@ internal override T ReadJSON(string json) { JsonSerializerOptions opts = new JsonSerializerOptions(); opts.Converters.Add(new GxJsonConverter()); + opts.AllowTrailingCommas = true; return JsonSerializer.Deserialize(json, opts); } internal override string WriteJSON(T kbObject) { - return JsonSerializer.Serialize(kbObject); + if (kbObject != null) + { + return kbObject.ToString(); + } + return null; + } + internal static string SerializeToJayrockCompatibleJson(T value) where T : IJayrockCompatible + { + JsonSerializerOptions opts = new JsonSerializerOptions(); + opts.Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping; + opts.Converters.Add(new CustomDateTimeConverter()); + opts.NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals; + return JsonSerializer.Serialize(value, opts); } } -#endif +#else internal class JayRockJsonSerializer : GXJsonSerializer { internal override bool IsJsonNull(object jobject) @@ -85,6 +137,7 @@ internal override string WriteJSON(T kbObject) return null; } } +#endif internal enum GXJsonSerializerType { Utf8, @@ -94,8 +147,7 @@ internal enum GXJsonSerializerType internal abstract class GXJsonSerializer { private static GXJsonSerializer s_instance = null; - private static object syncRoot = new Object(); - static GXJsonSerializerType DefaultJSonSerializer= GXJsonSerializerType.Jayrock; + private static object syncRoot = new object(); internal static GXJsonSerializer Instance { get @@ -106,17 +158,11 @@ internal static GXJsonSerializer Instance { if (s_instance == null) { - switch (DefaultJSonSerializer) - { #if NETCORE - case GXJsonSerializerType.TextJson: - s_instance = new TextJsonSerializer(); - break; + s_instance = new TextJsonSerializer(); +#else + s_instance = new JayRockJsonSerializer(); #endif - default: - s_instance = new JayRockJsonSerializer(); - break; - } } } } @@ -156,7 +202,7 @@ public static T ReadJSON(string json, GXBaseCollection M } catch (Exception ex) { - GXUtil.ErrorToMessages("FromJson Error", ex, Messages); + GXUtil.ErrorToMessages("FromJson Error", ex, Messages, false); GXLogging.Error(log, "FromJsonError ", ex); return default(T); } @@ -178,7 +224,7 @@ public static T ReadJavascriptJSON(string json, GXBaseCollection EventsMetadata = new Dictionary(); +#else private Hashtable EventsMetadata = new Hashtable(); +#endif +#if NETCORE + protected void setEventMetadata(string EventName, string Metadata) + { + if (EventsMetadata.ContainsKey(EventName)) + EventsMetadata[EventName] += Metadata; + else + EventsMetadata[EventName] = Metadata; + } +#else protected void setEventMetadata(string EventName, string Metadata) { if (EventsMetadata[EventName] == null) EventsMetadata[EventName] = string.Empty; EventsMetadata[EventName] += Metadata; } - +#endif public void webExecuteEx(HttpContext httpContext) { if (IsUploadRequest(httpContext)) @@ -442,7 +455,7 @@ private void ParseInputJSonMessage(JObject objMessage, GXHttpHandler targetObj) } if (objMessage.Contains("fullPost")) { - this.targetObj._Context.httpAjaxContext.ParseGXState((Jayrock.Json.JObject)objMessage["fullPost"]); + this.targetObj._Context.httpAjaxContext.ParseGXState((JObject)objMessage["fullPost"]); } } private void ParseGridsDataParms(JObject gxGrids) @@ -522,7 +535,12 @@ private void ParseMetadata() int eventCount = 0; foreach (string eventName in events) { +#if NETCORE + + JObject eventMetadata = JSONHelper.ReadJSON(targetObj.EventsMetadata[eventName.ToString()]); +#else JObject eventMetadata = JSONHelper.ReadJSON((string)targetObj.EventsMetadata[eventName.ToString()]); +#endif eventHandlers[eventCount] = (string)eventMetadata["handler"]; JArray eventInputParms = (JArray)eventMetadata["iparms"]; foreach (JObject inputParm in eventInputParms) @@ -531,9 +549,12 @@ private void ParseMetadata() eventUseInternalParms[eventCount] = eventUseInternalParms[eventCount] || IsInternalParm(inputParm); } JArray eventOutputParms = (JArray)eventMetadata["oparms"]; - foreach (JObject outputParm in eventOutputParms) + if (eventOutputParms != null) { - AddParmsMetadata(outputParm, DynAjaxEventContext.outParmsMetadata, DynAjaxEventContext.outParmsMetadataHash); + foreach (JObject outputParm in eventOutputParms) + { + AddParmsMetadata(outputParm, DynAjaxEventContext.outParmsMetadata, DynAjaxEventContext.outParmsMetadataHash); + } } eventCount++; } @@ -882,7 +903,7 @@ private object[] BeforeInvoke() { try { - JObject hashObj = (JObject)(hash_i < inHashValues.Length ? inHashValues[hash_i] : new Jayrock.Json.JObject()); + JObject hashObj = (JObject)(hash_i < inHashValues.Length ? inHashValues[hash_i] : new JObject()); string sRow = hashObj.Contains("row") ? (string)hashObj["row"] : string.Empty; string hash = hashObj.Contains("hsh") ? (string)hashObj["hsh"] : string.Empty; SetScalarOrCollectionValue((string)parm["av"], inParmsValues[parm_i], columnValues); diff --git a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpServices.cs b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpServices.cs index 992631cde..b9b993bc1 100644 --- a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpServices.cs +++ b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpServices.cs @@ -13,7 +13,9 @@ namespace GeneXus.Http using GeneXus.Mime; using GeneXus.Security; using GeneXus.Utils; +#if !NETCORE using Jayrock.Json; +#endif using System.Web.SessionState; using System.Web; #if NETCORE diff --git a/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs b/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs index 685d5971a..8cc6f616b 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs @@ -7,7 +7,9 @@ using GeneXus.Services.OpenTelemetry; #endif using GeneXus.Utils; +#if !NETCORE using Jayrock.Json; +#endif #if NETCORE using Microsoft.AspNetCore.Http.Extensions; #endif diff --git a/dotnet/src/dotnetframework/GxClasses/Model/GXSilentTrn.cs b/dotnet/src/dotnetframework/GxClasses/Model/GXSilentTrn.cs index cb76d4193..1bff5d5cb 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/GXSilentTrn.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/GXSilentTrn.cs @@ -6,7 +6,9 @@ namespace GeneXus.Utils using GeneXus.Application; using System.Xml.Serialization; using System.Collections.Generic; +#if !NETCORE using Jayrock.Json; +#endif using System.Text; using System.Security.Cryptography; using System.Reflection; diff --git a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs index 0e68a2960..d866e3288 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs @@ -24,7 +24,9 @@ using System.Collections.Specialized; using GeneXus.Security; using System.Collections; +#if !NETCORE using Jayrock.Json; +#endif using System.Net.Http; using System.Diagnostics; using GeneXus.Diagnostics; diff --git a/dotnet/src/dotnetframework/GxClasses/Services/ReflectionHelper.cs b/dotnet/src/dotnetframework/GxClasses/Services/ReflectionHelper.cs index 80c093834..5108ae30d 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/ReflectionHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/ReflectionHelper.cs @@ -7,7 +7,9 @@ using System.Text.RegularExpressions; using GeneXus.Utils; using System.Linq; +#if !NETCORE using Jayrock.Json; +#endif using Type = System.Type; @@ -179,9 +181,9 @@ private static object ConvertStringToNewNonNullableType(object value, Type newTy Type singleItemType = newType.GetElementType(); var elements = new ArrayList(); - foreach (var element in value.ToString().Split(',')) + foreach (string element in value.ToString().Split(',')) { - var convertedSingleItem = ConvertSingleJsonItem(element, singleItemType, context); + object convertedSingleItem = ConvertSingleJsonItem(element, singleItemType, context); elements.Add(convertedSingleItem); } return elements.ToArray(singleItemType); @@ -211,11 +213,11 @@ public static Dictionary ParametersFormat(object instance, strin var methodParameters = methodInfo.GetParameters(); foreach (var methodParameter in methodParameters) { - var gxParameterName = GxParameterName(methodParameter.Name); + string gxParameterName = GxParameterName(methodParameter.Name); if (IsByRefParameter(methodParameter)) { string fmt = ""; - var attributes = methodParameter.GetCustomAttributes(true); + object[] attributes = methodParameter.GetCustomAttributes(true); GxJsonFormatAttribute attFmt = (GxJsonFormatAttribute)attributes.Where(a => a.GetType() == typeof(GxJsonFormatAttribute)).FirstOrDefault(); if (attFmt != null) fmt = attFmt.JsonFormat; @@ -233,7 +235,7 @@ private static Dictionary ProcessParametersAfterInvoke(MethodInf int idx = 0; foreach (var methodParameter in methodParameters) { - var gxParameterName = GxParameterName(methodParameter.Name); + string gxParameterName = GxParameterName(methodParameter.Name); if (IsByRefParameter(methodParameter)) { outputParameters.Add(gxParameterName, parametersForInvocation[idx]); @@ -250,12 +252,12 @@ internal static object[] ProcessParametersForInvoke(MethodInfo methodInfo, IDict { var methodParameters = methodInfo.GetParameters(); object[] parametersForInvocation = new object[methodParameters.Length]; - var idx = 0; + int idx = 0; foreach (var methodParameter in methodParameters) { object value; - var gxParameterName = GxParameterName(methodParameter.Name).ToLower(); + string gxParameterName = GxParameterName(methodParameter.Name).ToLower(); Type parmType = methodParameter.ParameterType; if (IsByRefParameter(methodParameter)) { @@ -269,13 +271,13 @@ internal static object[] ProcessParametersForInvoke(MethodInfo methodInfo, IDict } else { - var convertedValue = ConvertStringToNewType(value, parmType, context); + object convertedValue = ConvertStringToNewType(value, parmType, context); parametersForInvocation[idx] = convertedValue; } } else { - var defaultValue = CreateInstance(parmType); + object defaultValue = CreateInstance(parmType); parametersForInvocation[idx] = defaultValue; } idx++; @@ -287,7 +289,7 @@ internal static object[] ProcessParametersForInvoke(MethodInfo methodInfo, IList { var methodParameters = methodInfo.GetParameters(); object[] parametersForInvocation = new object[methodParameters.Length]; - var idx = 0; + int idx = 0; foreach (var methodParameter in methodParameters) { Type parmType = methodParameter.ParameterType; @@ -301,7 +303,7 @@ internal static object[] ProcessParametersForInvoke(MethodInfo methodInfo, IList //To avoid convertion from string type if (value.GetType() != typeof(string)) { - var convertedValue = ConvertStringToNewType(value, parmType, context); + object convertedValue = ConvertStringToNewType(value, parmType, context); parametersForInvocation[idx] = convertedValue; } else @@ -335,7 +337,7 @@ private static object[] ProcessParametersForInvoke(MethodInfo methodInfo, IList< { var methodParameters = methodInfo.GetParameters(); object[] parametersForInvocation = new object[methodParameters.Length]; - var idx = 0; + int idx = 0; string pattern = @"(AV\d+)(.*)"; string replacement = "$2"; Regex rgx = new Regex(pattern); @@ -344,7 +346,7 @@ private static object[] ProcessParametersForInvoke(MethodInfo methodInfo, IList< { rgx.Replace(methodParameter.Name, replacement); Type parmType = methodParameter.ParameterType; - var convertedValue = ConvertStringToNewType(parametersValues[idx], parmType); + object convertedValue = ConvertStringToNewType(parametersValues[idx], parmType); parametersForInvocation[idx] = convertedValue; idx++; } diff --git a/dotnet/src/dotnetframework/GxClasses/Services/Search/GXSearch.cs b/dotnet/src/dotnetframework/GxClasses/Services/Search/GXSearch.cs index ed83471b8..70c2a49a9 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/Search/GXSearch.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/Search/GXSearch.cs @@ -2,7 +2,9 @@ using System.Collections.Generic; using System.Text; using GeneXus.Utils; +#if !NETCORE using Jayrock.Json; +#endif using GeneXus.Application; using System.Reflection; using GeneXus.Metadata; @@ -169,12 +171,16 @@ public class SearchResultItem : ISearchResultItem, IGxJSONAble { #region Internal Data - protected JObject _Properties; + JObject _Properties; protected float m_score; #endregion + public SearchResultItem() + { + _Properties = new JObject(); + } -#region ISearchResultItem Members + #region ISearchResultItem Members public virtual string Id { get { return ""; } } public virtual string Viewer { get { return ""; } } diff --git a/dotnet/src/dotnetframework/GxClasses/View/GXWebControls.cs b/dotnet/src/dotnetframework/GxClasses/View/GXWebControls.cs index 8985e6859..2ca0bd23d 100644 --- a/dotnet/src/dotnetframework/GxClasses/View/GXWebControls.cs +++ b/dotnet/src/dotnetframework/GxClasses/View/GXWebControls.cs @@ -13,7 +13,9 @@ using System.Collections.Specialized; using GeneXus.Utils; using System.Text.RegularExpressions; +#if !NETCORE using Jayrock.Json; +#endif using GeneXus.Configuration; using GeneXus.Application; @@ -323,7 +325,7 @@ public int GetWrapped() return 0; } - public List GetColsPropsCommon() + internal List GetColsPropsCommon() { return this._ColsPropsCommon; } @@ -733,7 +735,7 @@ public abstract class GXWebControl : IGxJSONAble, IGxJSONSerializable Unit _Height = Unit.Empty; ListDictionary _attributes = new ListDictionary(); ListDictionary _styleAttributes = new ListDictionary(); - protected JObject jsonObj = new JObject(); + JObject jsonObj = new JObject(); string _WebTags; static Regex rAttributes = new Regex("\\s*(?\\S*)\\s*=\\s*\"(?[^\"]*)\"", RegexOptions.IgnoreCase | RegexOptions.Compiled); @@ -752,7 +754,16 @@ public GXWebControl() _ID = ""; _title = new GxWebControlTitle(); } - public string CssClass + protected void PutJsonValue(string key, object value) + { + jsonObj.Put(key, value); + } + protected void ClearJsonValues() + { + jsonObj = new JObject(); + } + + public string CssClass { get { @@ -1414,7 +1425,7 @@ public void Render(HtmlTextWriter ControlOutputWriter) public override void ToJSON() { - jsonObj.Put(Value, Value); + PutJsonValue(Value, Value); } } @@ -1525,10 +1536,11 @@ public void removeAllItems() { _IsSet = true; Items.Clear(); - jsonObj = new JObject(); + ClearJsonValues(); _SelectedIndex = -1; } - public void removeItem(string itemValue) + + public void removeItem(string itemValue) { _IsSet = true; foreach (ListItem item in Items) @@ -1625,8 +1637,8 @@ protected virtual void ApplyProperties(ListControl control) public override void ToJSON() { - jsonObj.Put("isset", _IsSet); - jsonObj.Put("s", SelectedItemValue.Trim()); + PutJsonValue("isset", _IsSet); + PutJsonValue("s", SelectedItemValue.Trim()); JArray jsonArrValues = new JArray(); Dictionary itemsHash = new Dictionary(); foreach (ListItem Item in Items) @@ -1645,7 +1657,7 @@ public override void ToJSON() itemsHash[itemValue][1] = Item.Text; } } - jsonObj.Put("v", jsonArrValues); + PutJsonValue("v", jsonArrValues); } public override void FromJSONObject(dynamic Obj) @@ -1729,7 +1741,7 @@ public void Render(HtmlTextWriter ControlOutputWriter) public override void ToJSON() { - jsonObj.Put(CheckedValue, Checked); + PutJsonValue(CheckedValue, Checked); } } diff --git a/dotnet/src/dotnetframework/GxSearch/SearchResultCollection.cs b/dotnet/src/dotnetframework/GxSearch/SearchResultCollection.cs index 660dbd961..ad6884684 100644 --- a/dotnet/src/dotnetframework/GxSearch/SearchResultCollection.cs +++ b/dotnet/src/dotnetframework/GxSearch/SearchResultCollection.cs @@ -7,7 +7,11 @@ using GeneXus.Utils; +#if NETCORE +using GeneXus.Application; +#else using Jayrock.Json; +#endif using System.Globalization; using System.Security; @@ -116,9 +120,8 @@ public LuceneSearchResultItem() #endregion - internal LuceneSearchResultItem(Document document, float score) + internal LuceneSearchResultItem(Document document, float score):base() { - _Properties = new JObject(); m_document = document; m_score = score; } diff --git a/dotnet/src/dotnetframework/GxWebSocket/WSHandler.cs b/dotnet/src/dotnetframework/GxWebSocket/WSHandler.cs index ddf4f9fe4..2c4983fdd 100644 --- a/dotnet/src/dotnetframework/GxWebSocket/WSHandler.cs +++ b/dotnet/src/dotnetframework/GxWebSocket/WSHandler.cs @@ -8,7 +8,11 @@ using GeneXus.Procedure; using GeneXus.Services; using GeneXus.Utils; +#if NETCORE +using GeneXus.Application; +#else using Jayrock.Json; +#endif using Microsoft.Web.WebSockets; namespace GeneXus.Http.WebSocket diff --git a/dotnet/src/dotnetframework/Projects/StoreManager/Store/Platforms/AppleStoreStoreManager.cs b/dotnet/src/dotnetframework/Projects/StoreManager/Store/Platforms/AppleStoreStoreManager.cs index 6bbc71836..23afb45d3 100644 --- a/dotnet/src/dotnetframework/Projects/StoreManager/Store/Platforms/AppleStoreStoreManager.cs +++ b/dotnet/src/dotnetframework/Projects/StoreManager/Store/Platforms/AppleStoreStoreManager.cs @@ -2,10 +2,12 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading.Tasks; using System.Net; -using System.IO; +#if NETCORE +using GeneXus.Application; +#else using Jayrock.Json; +#endif using GeneXus.SD.Store.Model; using System.Collections.Concurrent; using System.Net.Http; diff --git a/dotnet/src/dotnetframework/Projects/StoreManager/Store/Platforms/GooglePlayStoreManager.cs b/dotnet/src/dotnetframework/Projects/StoreManager/Store/Platforms/GooglePlayStoreManager.cs index 799e53f5f..126c5b448 100644 --- a/dotnet/src/dotnetframework/Projects/StoreManager/Store/Platforms/GooglePlayStoreManager.cs +++ b/dotnet/src/dotnetframework/Projects/StoreManager/Store/Platforms/GooglePlayStoreManager.cs @@ -1,13 +1,13 @@ using GeneXus.Utils; using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Security.Cryptography.X509Certificates; using Google.Apis.Auth.OAuth2; using Google.Apis.AndroidPublisher.v3; using Google.Apis.Services; +#if !NETCORE using Jayrock.Json; +#endif using Google.Apis.AndroidPublisher.v3.Data; using GeneXus.Application; using System.IO; diff --git a/dotnet/src/dotnetframework/Projects/StoreManager/Store/StoreManager.cs b/dotnet/src/dotnetframework/Projects/StoreManager/Store/StoreManager.cs index ff8279c6d..aba1cdb1c 100644 --- a/dotnet/src/dotnetframework/Projects/StoreManager/Store/StoreManager.cs +++ b/dotnet/src/dotnetframework/Projects/StoreManager/Store/StoreManager.cs @@ -1,9 +1,13 @@ using System; using System.Collections.Generic; +#if NETCORE +using GeneXus.Application; +#else +using Jayrock.Json; +#endif using GeneXus.SD.Store.Model; using GeneXus.SD.Store.Platforms; using GeneXus.Utils; -using Jayrock.Json; namespace GeneXus.SD.Store { @@ -165,7 +169,7 @@ public int GetManager(GxUserType gxStoreConfig, int platform, out IStoreManager return errCode; } - public static bool GetConfigValue(string key, JObject storeConfig, out string value) + static bool GetConfigValue(string key, JObject storeConfig, out string value) { value = string.Empty; if (storeConfig.Contains(key)) diff --git a/dotnet/src/dotnetframework/Projects/StoreManager/Store/Util.cs b/dotnet/src/dotnetframework/Projects/StoreManager/Store/Util.cs index ce6a2a344..3544e3732 100644 --- a/dotnet/src/dotnetframework/Projects/StoreManager/Store/Util.cs +++ b/dotnet/src/dotnetframework/Projects/StoreManager/Store/Util.cs @@ -1,5 +1,9 @@ using GeneXus.Utils; +#if NETCORE +using GeneXus.Application; +#else using Jayrock.Json; +#endif using System; using System.Security.Cryptography; using System.Text; @@ -14,7 +18,7 @@ public static DateTime FromUnixTime(long unixMillisecondsTime) return dt.AddMilliseconds(unixMillisecondsTime); } - public static JObject FromJSonString(string s) + internal static JObject FromJSonString(string s) { JObject _jsonArr = null; if (!string.IsNullOrEmpty(s)) diff --git a/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj b/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj index aa96f1c8b..4b671a244 100644 --- a/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj +++ b/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj @@ -55,8 +55,6 @@ - - @@ -180,10 +178,4 @@ - - - - ..\..\src\dotnetcore\libs\Jayrock.dll - - diff --git a/dotnet/test/DotNetCoreUnitTest/StringUtil/JsonUtilTest.cs b/dotnet/test/DotNetCoreUnitTest/StringUtil/JsonUtilTest.cs new file mode 100644 index 000000000..768153bd2 --- /dev/null +++ b/dotnet/test/DotNetCoreUnitTest/StringUtil/JsonUtilTest.cs @@ -0,0 +1,319 @@ +using System; +using System.Collections; +using System.Xml.Serialization; +using GeneXus.Application; +using GeneXus.Utils; +using System.ServiceModel; +using GeneXus.Programs; +#if !NETCORE +using Jayrock.Json; +#endif +using Xunit; + +namespace xUnitTesting +{ + public class JsonUtilTest + { + [Fact] + public void PropertiesSerialization() + { + GXProperties AV9properties = new GXProperties(); + string url = "http://localhost/OuvidoriaOuvidoriaAndroidHomologa/login.aspx?pmsa"; + string user = "mpsa"; + string AV8json = "{\"Url\" : \""+ url + "\",\"User\" : \"" + user + "\"}"; + AV9properties.FromJSonString(AV8json, null); + GxKeyValuePair AV10property = AV9properties.GetFirst(); + Assert.Equal("Url", AV10property.Key); + Assert.Equal(url, AV10property.Value); + AV10property = AV9properties.GetNext(); + Assert.Equal("User", AV10property.Key); + Assert.Equal(user, AV10property.Value); + + } + [Fact] + public void StringSerialization() + { + string result = JSONHelper.WriteJSON("myvalue"); + Assert.Equal("myvalue", result); + + } + [Fact] + public void SerializationFloatingNumbers() + { + SdtSDTGeneric genericSdt = new SdtSDTGeneric(); + genericSdt.gxTpr_Itemnum = 1; + genericSdt.gxTpr_Itemchar = "Caso Base"; + genericSdt.gxTpr_Itemgeopoint = new Geospatial("POINT(-56.248367 -34.873821)"); + genericSdt.gxTpr_Itemgeography = new Geospatial("-34.873821, -56.248367"); + string json = genericSdt.ToJSonString(); + string expectedJson = "{\"ItemNum\":1,\"ItemChar\":\"Caso Base\",\"ItemGeoPoint\":\"POINT (-56.248367 -34.873821)\",\"ItemGeography\":\"\",\"ItemGEolocation\":\"\"}"; + Assert.Equal(expectedJson, json); + } + [Fact] + public void DeserializationInvalidJsonNoDuplicateError() + { + string invalidJson1 = "{\"id\":1,\"name\":\"uno\",\"date\":\"2016-02-24\"'"; + GXBaseCollection messages = new GXBaseCollection(); + JSONHelper.ReadJSON(invalidJson1, messages); + string errMessage = messages.ToJSonString(); +#if NETCORE + string expectedError = "[{\"Id\":\"FromJson Error\",\"Type\":1,\"Description\":\"''' is invalid after a value. Expected either ',', '}', or ']'. Path: $.date | LineNumber: 0 | BytePositionInLine: 40.\"}]"; +#else + string expectedError = "[{\"Id\":\"FromJson Error\",\"Type\":1,\"Description\":\"Expected a ',' or '}'.\"}]"; +#endif + Assert.Equal(expectedError, errMessage); + } + + [Fact] + public void SerializationWithDateTimes() + { + object[] parms = new object[] + { + new DateTime(2016, 6, 29, 0, 0, 0), + new DateTime(2016, 6, 29, 12, 12, 0), + true + }; + JArray jarray = new JArray(parms); + string json = jarray.ToString(); + Assert.Equal("[\"06/29/2016 00:00:00\",\"06/29/2016 12:12:00\",true]", json); + + JObject jObject = new JObject(); + jObject.Put("datetime", new DateTime(2016, 6, 29, 12, 12, 0)); + json = jObject.ToString(); + Assert.Equal("{\"datetime\":\"06/29/2016 12:12:00\"}", json); + } + [Fact] + public void DeserializationWithDateTimes() + { + string json = "{\"parms\": [\"2016/06/29 00:00:00\", \"2016/06/29 12:12:00\", true]}"; + JObject jObj = JSONHelper.ReadJSON(json); + string parm = (string)((JArray)jObj["parms"])[1]; + GxContext gxContext = new GxContext(); + DateTime dParm = gxContext.localUtil.CToT(parm, 0, 0); + Assert.Equal(new DateTime(2016, 6, 29, 12, 12, 0), dParm); + } + [Fact] + public void SerializationWithNumbers() + { + JObject jObject = new JObject(); + jObject.Put("gridId", 2); + string json = JSONHelper.WriteJSON(jObject); + Assert.Contains(":2", json, StringComparison.OrdinalIgnoreCase); + } + [Fact] + public void DeserializationWithNumbers() + { + string json = "{\"MPage\":false,\"cmpCtx\":\"\",\"parms\":[0,\"\",\"\",\"\",[{\"pRow\":\"\",\"c\":[],\"v\":null}],\"\",\"0\",{\"gridRC\":53903859.090,\"hsh\":true,\"grid\":2},\"0\",null],\"hsh\":[],\"objClass\":\"testsac42351\",\"pkgName\":\"GeneXus.Programs\",\"events\":[\"'BTN_SEARCH'\"],\"grids\":{\"Grid1\":{\"id\":2,\"lastRow\":0,\"pRow\":\"\"}}}"; + JObject jObj = JSONHelper.ReadJSON(json); + JObject parm = (JObject)((JArray)jObj["parms"])[7]; + Assert.NotNull(parm); + int gridId = (int)(parm["grid"]); + Assert.Equal(2, gridId); + decimal gridRC = Convert.ToDecimal(parm["gridRC"]); + Assert.Equal(53903859.090M, gridRC); + bool hash = (bool)parm["hsh"]; + Assert.True(hash); + } + + [Fact] + public void DeserializationWithBigDecimalsTest_Issue70446() + { + decimal expectedBigdecimal = 53903859.09090909M; + GxContext context = new GxContext(); + SdtSDTteste sdt = new SdtSDTteste(context); + string json = "{\"testeID\":1,\"testeName\":\"um\",\"testeNumero\":53903859.09090909}"; + sdt.FromJSonString(json, null); + Assert.Equal(expectedBigdecimal, sdt.gxTpr_Testenumero); + Assert.Equal(1, sdt.gxTpr_Testeid); + Assert.Equal("um", sdt.gxTpr_Testename); + } + [Fact] + public void SerializationWithBigDecimalsTest_Issue70446() + { + decimal expectedBigdecimal = 53903859.09090909M; + GxContext context = new GxContext(); + SdtSDTteste sdt = new SdtSDTteste(context); + sdt.gxTpr_Testeid = 1; + sdt.gxTpr_Testename = "um"; + sdt.gxTpr_Testenumero = expectedBigdecimal; + + string expectedJson = "{\"testeID\":1,\"testeName\":\"um\",\"testeNumero\":\"53903859.09090909\"}"; + string json = sdt.ToJSonString(); + Assert.Equal(expectedJson, json); + } + [Fact] + public void SerializationWithSpecialCharacters_Issue69271() + { + string specialCharacters = $"1:{StringUtil.Chr(30)}:1-2:{StringUtil.Chr(29)}:2"; + GxContext context = new GxContext(); + SdtSDTteste sdt = new SdtSDTteste(context); + string json = "{\"testeID\":1,\"testeName\":\"" + StringUtil.JSONEncode(specialCharacters) + "\"}"; + sdt.FromJSonString(json, null); + Assert.Equal(specialCharacters, sdt.gxTpr_Testename); + } + + [Fact] + public void SerializationWithSpecialCharacters_js() + { + JObject jObject = new JObject(); + jObject.Put("Grid1ContainerData", "{\"GridName\":\"Links\",\"CmpContext\":\"MPW0020\",\"Caption\":\"One+Two<>&\"}"); + string json = JSONHelper.WriteJSON(jObject); + Assert.Contains("\\\"GridName\\\"", json, StringComparison.OrdinalIgnoreCase); + } + [Fact] + public void DeserializationWithSpecialCharacters_js() + { + string json="{\"GridName\":\"Links\",\"CmpContext\":\"MPW0020\",\"Caption\":\"One+Two<>&\"}"; + JObject jObject = JSONHelper.ReadJSON(json); + string caption = (string)jObject["Caption"]; + Assert.Equal("One+Two<>&", caption); + } + + [Fact] + public void SerializationPropertiesKeepOrder() + { + string json = JSONHelper.WriteJSON(GetJSONObject()); + Assert.Equal("{\"ClientId\":0,\"ClientName\":\"John\",\"ClientActive\":false}", json); + } + object GetJSONObject() + { + JObject jObject = new JObject(); + jObject.Put("ClientId", 0); + jObject.Put("ClientName", "John"); + jObject.Put("ClientActive", false); + return jObject; + } + [Fact] + public void DeserializationTrailingCommasCompatibility() + { + string json = "[[\"Client\",\"5a4ff115ab7e9d0f6c290b4ef33e34ce\"],[\"Invoice\",\"6c656e4034128018024144afdcc756aa\"],[\"InvoiceLine\",\"cd07f8e2bc014e27340005d9f26ec626\"],[\"Product\",\"84da0573bd448e9761ce20a4c4f9fce1\"],[\"ClientAutonumber\",\"479484926ef142cc026b362e2579a9f3\"],[\"Orders\",\"d857b7ff7dbf9329047b52918f7c5cac\"],[\"TiposDeDatos\",\"0c9a48d30dc26bd787ce466f235a5b3f\"],]"; + JArray array = JSONHelper.ReadJSON(json); + Assert.Equal(7, array.Count); + } + } + + [XmlSerializerFormat] + [XmlRoot(ElementName = "SDTteste")] + [XmlType(TypeName = "SDTteste", Namespace = "JsonSerialization")] + [Serializable] + public class SdtSDTteste : GxUserType + { + public SdtSDTteste() + { + /* Constructor for serialization */ + gxTv_SdtSDTteste_Testename = ""; + + } + public SdtSDTteste(IGxContext context) + { + this.context = context; + initialize(); + } + #region Json + private static Hashtable mapper; + public override string JsonMap(string value) + { + if (mapper == null) + { + mapper = new Hashtable(); + } + return (string)mapper[value]; ; + } + public override void ToJSON() + { + ToJSON(true); + return; + } + public override void ToJSON(bool includeState) + { + AddObjectProperty("testeID", gxTpr_Testeid, false); + AddObjectProperty("testeName", gxTpr_Testename, false); + AddObjectProperty("testeNumero", StringUtil.LTrim(StringUtil.Str(gxTpr_Testenumero, 21, 8)), false); + return; + } + #endregion + + #region Properties + + [SoapElement(ElementName = "testeID")] + [XmlElement(ElementName = "testeID")] + public short gxTpr_Testeid + { + get + { + return gxTv_SdtSDTteste_Testeid; + } + set + { + gxTv_SdtSDTteste_Testeid = value; + SetDirty("Testeid"); + } + } + + [SoapElement(ElementName = "testeName")] + [XmlElement(ElementName = "testeName")] + public string gxTpr_Testename + { + get + { + return gxTv_SdtSDTteste_Testename; + } + set + { + gxTv_SdtSDTteste_Testename = value; + SetDirty("Testename"); + } + } + [SoapElement(ElementName = "testeNumero")] + [XmlElement(ElementName = "testeNumero")] + public string gxTpr_Testenumero_double + { + get + { + return Convert.ToString(gxTv_SdtSDTteste_Testenumero, System.Globalization.CultureInfo.InvariantCulture); + } + set + { + gxTv_SdtSDTteste_Testenumero = Convert.ToDecimal(value, System.Globalization.CultureInfo.InvariantCulture); + } + } + [SoapIgnore] + [XmlIgnore] + public decimal gxTpr_Testenumero + { + get + { + return gxTv_SdtSDTteste_Testenumero; + } + set + { + gxTv_SdtSDTteste_Testenumero = value; + SetDirty("Testenumero"); + } + } + public override bool ShouldSerializeSdtJson() + { + return true; + } + + #endregion + + #region Initialization + + public void initialize() + { + gxTv_SdtSDTteste_Testename = ""; + + return; + } + + #endregion + + #region Declaration + + protected short gxTv_SdtSDTteste_Testeid; + protected string gxTv_SdtSDTteste_Testename; + protected decimal gxTv_SdtSDTteste_Testenumero; + #endregion + } +} diff --git a/dotnet/test/DotNetCoreUnitTest/StringUtil/StringUtilTests.cs b/dotnet/test/DotNetCoreUnitTest/StringUtil/StringUtilTests.cs index c7b1b9225..40a1f15bb 100644 --- a/dotnet/test/DotNetCoreUnitTest/StringUtil/StringUtilTests.cs +++ b/dotnet/test/DotNetCoreUnitTest/StringUtil/StringUtilTests.cs @@ -1,6 +1,6 @@ +using GeneXus.Application; using GeneXus.Programs; using GeneXus.Utils; -using Newtonsoft.Json.Linq; using Xunit; namespace xUnitTesting @@ -36,7 +36,7 @@ public void TestJSONEncodeDoNotEncodeGreaterCharacter() public void TestFromJsonSDTWithBlankDateTime() { SdtSDT1_SDT1Item sdt = new SdtSDT1_SDT1Item(); - Jayrock.Json.JObject json = new Jayrock.Json.JObject(); + JObject json = new JObject(); json["SDT1_DateTime"] = " 00:00:00"; json["SDT1_Name"]=string.Empty; json["SDT1_No"] = 0; @@ -49,7 +49,7 @@ public void TestFromJsonSDTWithBlankDateTime() public void TestFromJsonSDTWithTimeMustNotApplyTimezone() { SdtSDT1_SDT1Item sdt = new SdtSDT1_SDT1Item(); - Jayrock.Json.JObject json = new Jayrock.Json.JObject(); + JObject json = new JObject(); json["SDT1_DateTime"] = "2014-04-29T14:29:40"; json["SDT1_Name"] = string.Empty; json["SDT1_No"] = 0; diff --git a/dotnet/test/DotNetCoreUnitTest/StringUtil/type_SdtSDTGeneric.cs b/dotnet/test/DotNetCoreUnitTest/StringUtil/type_SdtSDTGeneric.cs new file mode 100644 index 000000000..2ba8db20f --- /dev/null +++ b/dotnet/test/DotNetCoreUnitTest/StringUtil/type_SdtSDTGeneric.cs @@ -0,0 +1,197 @@ +using System; +using System.Collections; +using System.Xml.Serialization; +using GeneXus.Application; +using GeneXus.Utils; + + +namespace GeneXus.Programs +{ + [XmlRoot(ElementName="SDTGeneric")] + [XmlType(TypeName="SDTGeneric" , Namespace="TestGeographyDatatype" )] + [Serializable] + public class SdtSDTGeneric : GxUserType + { + public SdtSDTGeneric( ) + { + /* Constructor for serialization */ + gxTv_SdtSDTGeneric_Itemchar = ""; + + gxTv_SdtSDTGeneric_Itemgeopoint = new Geospatial(""); + + gxTv_SdtSDTGeneric_Itemgeography = new Geospatial(""); + + gxTv_SdtSDTGeneric_Itemgeolocation = ""; + + } + + public SdtSDTGeneric(IGxContext context) + { + this.context = context; + initialize(); + } + + #region Json + private static Hashtable mapper; + public override string JsonMap(string value) + { + if (mapper == null) + { + mapper = new Hashtable(); + } + return (string)mapper[value]; ; + } + + public override void ToJSON() + { + ToJSON(true) ; + return; + } + + public override void ToJSON(bool includeState) + { + AddObjectProperty("ItemNum", gxTpr_Itemnum, false); + + + AddObjectProperty("ItemChar", gxTpr_Itemchar, false); + + + AddObjectProperty("ItemGeoPoint", gxTpr_Itemgeopoint, false); + + + AddObjectProperty("ItemGeography", gxTpr_Itemgeography, false); + + + AddObjectProperty("ItemGEolocation", gxTpr_Itemgeolocation, false); + + return; + } + #endregion + + #region Properties + + [SoapElement(ElementName="ItemNum")] + [XmlElement(ElementName="ItemNum")] + public short gxTpr_Itemnum + { + get { + return gxTv_SdtSDTGeneric_Itemnum; + } + set { + gxTv_SdtSDTGeneric_Itemnum = value; + SetDirty("Itemnum"); + } + } + + + + + [SoapElement(ElementName="ItemChar")] + [XmlElement(ElementName="ItemChar")] + public string gxTpr_Itemchar + { + get { + return gxTv_SdtSDTGeneric_Itemchar; + } + set { + gxTv_SdtSDTGeneric_Itemchar = value; + SetDirty("Itemchar"); + } + } + + + + + [SoapElement(ElementName="ItemGeoPoint")] + [XmlElement(ElementName="ItemGeoPoint")] + public Geospatial gxTpr_Itemgeopoint + { + get { + return gxTv_SdtSDTGeneric_Itemgeopoint; + } + set { + gxTv_SdtSDTGeneric_Itemgeopoint = value; + SetDirty("Itemgeopoint"); + } + } + + + + + [SoapElement(ElementName="ItemGeography")] + [XmlElement(ElementName="ItemGeography")] + public Geospatial gxTpr_Itemgeography + { + get { + return gxTv_SdtSDTGeneric_Itemgeography; + } + set { + gxTv_SdtSDTGeneric_Itemgeography = value; + SetDirty("Itemgeography"); + } + } + + + + + [SoapElement(ElementName="ItemGEolocation")] + [XmlElement(ElementName="ItemGEolocation")] + public string gxTpr_Itemgeolocation + { + get { + return gxTv_SdtSDTGeneric_Itemgeolocation; + } + set { + gxTv_SdtSDTGeneric_Itemgeolocation = value; + SetDirty("Itemgeolocation"); + } + } + + + + public override bool ShouldSerializeSdtJson() + { + return true; + } + + + + #endregion + + #region Initialization + + public void initialize( ) + { + gxTv_SdtSDTGeneric_Itemchar = ""; + gxTv_SdtSDTGeneric_Itemgeopoint = new Geospatial(""); + gxTv_SdtSDTGeneric_Itemgeography = new Geospatial(""); + gxTv_SdtSDTGeneric_Itemgeolocation = ""; + return ; + } + + + + #endregion + + #region Declaration + + protected short gxTv_SdtSDTGeneric_Itemnum; + + + protected string gxTv_SdtSDTGeneric_Itemchar; + + + protected Geospatial gxTv_SdtSDTGeneric_Itemgeopoint; + + + protected Geospatial gxTv_SdtSDTGeneric_Itemgeography; + + + protected string gxTv_SdtSDTGeneric_Itemgeolocation; + + + + #endregion + } + +} \ No newline at end of file diff --git a/dotnet/test/DotNetCoreUnitTest/appsettings.json b/dotnet/test/DotNetCoreUnitTest/appsettings.json index 31bce50e5..d38ee5c57 100644 --- a/dotnet/test/DotNetCoreUnitTest/appsettings.json +++ b/dotnet/test/DotNetCoreUnitTest/appsettings.json @@ -49,6 +49,7 @@ "SAMESITE_COOKIE": "Lax", "CACHE_INVALIDATION_TOKEN": "20216211291931", "CORS_ALLOW_ORIGIN": "https://normal-website.com", + "USE_JAYROCK": "0", "MY_CUSTOM_PTY": "DEFAULT_VALUE" }, "languages": { diff --git a/dotnet/test/DotNetUnitTest/DotNetUnitTest.csproj b/dotnet/test/DotNetUnitTest/DotNetUnitTest.csproj index ed384f5fb..76f536242 100644 --- a/dotnet/test/DotNetUnitTest/DotNetUnitTest.csproj +++ b/dotnet/test/DotNetUnitTest/DotNetUnitTest.csproj @@ -10,6 +10,10 @@ + + + + PreserveNewest @@ -51,6 +55,10 @@ + + ..\..\src\dotnetframework\libs\Jayrock-JSON.dll + + ..\..\src\dotnetframework\libs\TZ4Net.dll @@ -92,6 +100,7 @@ + @@ -101,5 +110,6 @@ Settings.settings + From 2ab253da9857607e57104788184e608a26c7eab0 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 26 Dec 2023 12:26:58 -0300 Subject: [PATCH 078/164] Customize session id cookie name to allow multiple websites deployed under the same domain. (#915) This prevents conflicts between applications, as having the same cookie names set at the domain root path could lead to unintended overrides. --- .../dotnetcore/GxNetCoreStartup/Startup.cs | 6 ++ .../GxClasses/Core/gxconfig.cs | 20 +++++- .../GxClasses/Domain/GxSession.cs | 65 ++++++++++++++++--- 3 files changed, 82 insertions(+), 9 deletions(-) diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs index 5cda19ae5..4515024ec 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs @@ -196,6 +196,12 @@ public void ConfigureServices(IServiceCollection services) options.Cookie.HttpOnly = true; options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest; options.Cookie.IsEssential = true; + string sessionCookieName = GxWebSession.GetSessionCookieName(VirtualPath); + if (!string.IsNullOrEmpty(sessionCookieName)) + { + options.Cookie.Name=sessionCookieName; + GxWebSession.SessionCookieName = sessionCookieName; + } string sameSite; SameSiteMode sameSiteMode = SameSiteMode.Unspecified; if (Config.GetValueOf("SAMESITE_COOKIE", out sameSite) && Enum.TryParse(sameSite, out sameSiteMode)) diff --git a/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs b/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs index a57cd234b..3cd2fb6ba 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs @@ -157,7 +157,25 @@ public static bool GetValueOf(string sId, out string sString) return false; } } - + internal static bool GetValueOrEnvironmentVarOf(string sId, out string sString) + { + try + { + sString = config.Get(sId); + if (String.IsNullOrEmpty(sString)) + { + MappedValue(sId, sString); + if (string.IsNullOrEmpty(sString)) + return false; + } + return true; + } + catch + { + sString = string.Empty; + return false; + } + } public static bool GetValueOf(string sId) { string sString; diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxSession.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxSession.cs index af89955f3..13881d355 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxSession.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxSession.cs @@ -5,10 +5,12 @@ using System.Web.SessionState; #else using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Session; #endif using GeneXus.Utils; using GeneXus.Encryption; using GeneXus.Application; +using GeneXus.Configuration; namespace GeneXus.Http { @@ -29,7 +31,12 @@ string Id } public class GxWebSession : IGxSession - { + { +#if NETCORE + const string SESSION_COOKIE_NAME = "SESSION_COOKIE_NAME"; + const string ASPNETCORE_APPL_PATH = "ASPNETCORE_APPL_PATH"; +#endif + private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private HttpSessionState _httpSession; #region InternalKeys @@ -215,19 +222,61 @@ public static bool IsSessionExpired(HttpContext httpContext) if (httpContext.IsNewSession()) { string CookieHeaders = httpContext.Request.Headers["Cookie"]; - - if ((null != CookieHeaders) && ((CookieHeaders.IndexOf("ASP.NET_SessionId") >= 0)|| CookieHeaders.IndexOf(".AspNetCore.Session") >= 0)) - { - // IsNewSession is true, but session cookie exists, - // so, ASP.NET session is expired - return true; + if ((null != CookieHeaders) && (CookieHeaders.IndexOf(SessionCookieName) >= 0)) + { + // IsNewSession is true, but session cookie exists, + // so, ASP.NET session is expired + return true; } } } return false; } +#if NETCORE + internal static string GetSessionCookieName(string virtualPath) + { + string cookieName; + if (Config.GetValueOrEnvironmentVarOf(SESSION_COOKIE_NAME, out cookieName)) + return cookieName; + else + { + if (!string.IsNullOrEmpty(virtualPath)) + { + return $"{SessionDefaults.CookieName}.{virtualPath.ToLower()}"; + } + else + { + string applPath = Config.ConfigRoot[ASPNETCORE_APPL_PATH]; - } + if (!string.IsNullOrEmpty(applPath)) + { + cookieName = ToCookieName(applPath).ToLower(); + return $"{SessionDefaults.CookieName}.{cookieName}"; + } + } + return SessionDefaults.CookieName; + } + } + static string ToCookieName(string name) + { + char[] cookieName = new char[name.Length]; + int index = 0; + + foreach (char character in name) + { + if (char.IsLetter(character) || char.IsNumber(character)) + { + cookieName[index] = character; + index++; + } + } + return new string(cookieName, 0, index); + } + internal static string SessionCookieName { get; set; } +#else + const string SessionCookieName="ASP.NET_SessionId"; +#endif + } public class GxSession : IGxSession { From 0f96366bfe2ab432eec6a5fbbaeeaa05714175c5 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 27 Dec 2023 16:57:07 -0300 Subject: [PATCH 079/164] Extend CSRF validation to all backend services (#917) * Extend CSRF validation to all backend services requested through POST/DELETE/PUT methods * Rename ValidateCSRF to CSRF_PROTECTION in accordance with the spec. * Rename ValidateCSRF to CSRF_PROTECTION at appsettings.json in accordance with the spec. * Check csrf token is not null. * Set StatusCode to 400 on web panels and REST procedures that fail CSRF token validation --- .../dotnetcore/GxNetCoreStartup/CsrfHelper.cs | 12 ++- .../dotnetcore/GxNetCoreStartup/Startup.cs | 8 +- .../GxClasses/Helpers/GXRestUtils.cs | 2 +- .../GxClasses/Helpers/HttpHelper.cs | 8 +- .../GxClasses/Middleware/GXHttp.cs | 31 ++++++-- .../GxClasses/Services/GXRestServices.cs | 6 +- .../Middleware/RestServiceTest.cs | 77 +++++++++++++------ .../appsettings.json | 2 +- 8 files changed, 102 insertions(+), 44 deletions(-) diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/CsrfHelper.cs b/dotnet/src/dotnetcore/GxNetCoreStartup/CsrfHelper.cs index 2306f028e..2020e7371 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/CsrfHelper.cs +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/CsrfHelper.cs @@ -13,13 +13,15 @@ public class ValidateAntiForgeryTokenMiddleware static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private readonly RequestDelegate _next; private readonly IAntiforgery _antiforgery; + private string _restBasePath; private string _basePath; - public ValidateAntiForgeryTokenMiddleware(RequestDelegate next, IAntiforgery antiforgery, String basePath) + public ValidateAntiForgeryTokenMiddleware(RequestDelegate next, IAntiforgery antiforgery, string basePath) { _next = next; _antiforgery = antiforgery; - _basePath = "/" + basePath; + _restBasePath = $"{basePath}{Startup.REST_BASE_URL}"; + _basePath = $"/{basePath}"; } public async Task Invoke(HttpContext context) @@ -42,9 +44,13 @@ public async Task Invoke(HttpContext context) SetAntiForgeryTokens(_antiforgery, context); } } - if (!context.Request.Path.Value.EndsWith(_basePath)) //VerificationToken + if (!IsVerificationTokenServiceRequest(context)) await _next(context); } + private bool IsVerificationTokenServiceRequest(HttpContext context) + { + return context.Request.Path.Value.EndsWith(_restBasePath); + } internal static void SetAntiForgeryTokens(IAntiforgery _antiforgery, HttpContext context) { AntiforgeryTokenSet tokenSet = _antiforgery.GetAndStoreTokens(context); diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs index 4515024ec..0438dfdc3 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs @@ -133,7 +133,7 @@ public class Startup const string RESOURCES_FOLDER = "Resources"; const string TRACE_FOLDER = "logs"; const string TRACE_PATTERN = "trace.axd"; - const string REST_BASE_URL = "rest/"; + internal const string REST_BASE_URL = "rest/"; const string DATA_PROTECTION_KEYS = "DataProtection-Keys"; const string REWRITE_FILE = "rewrite.config"; const string SWAGGER_DEFAULT_YAML = "default.yaml"; @@ -417,7 +417,7 @@ public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHos if (RestAPIHelpers.ValidateCsrfToken()) { antiforgery = app.ApplicationServices.GetRequiredService(); - app.UseAntiforgeryTokens(restBasePath); + app.UseAntiforgeryTokens(apiBasePath); } app.UseMvc(routes => { @@ -507,7 +507,6 @@ bool IsAspx(HttpContext context, string basePath) } public class CustomExceptionHandlerMiddleware { - const string InvalidCSRFToken = "InvalidCSRFToken"; static readonly IGXLogger log = GXLoggerFactory.GetLogger(); public async Task Invoke(HttpContext httpContext) { @@ -522,9 +521,8 @@ public async Task Invoke(HttpContext httpContext) } else if (ex is AntiforgeryValidationException) { - //"The required antiforgery header value "X-GXCSRF-TOKEN" is not present. httpStatusCode = HttpStatusCode.BadRequest; - httpReasonPhrase = InvalidCSRFToken; + httpReasonPhrase = HttpHelper.InvalidCSRFToken; GXLogging.Error(log, $"Validation of antiforgery failed", ex); } else diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestUtils.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestUtils.cs index e32d5f04b..ec16827f6 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestUtils.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestUtils.cs @@ -143,7 +143,7 @@ public static Dictionary ReadRestBodyParameters(Stream stream) internal static bool ValidateCsrfToken() { - return Config.GetValueOf("ValidateCSRF", Preferences.NO) == Preferences.YES; + return Config.GetValueOf("CSRF_PROTECTION", Preferences.NO) == Preferences.YES; } } } diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs index 0e19a76d5..a0e94c333 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs @@ -93,7 +93,7 @@ public class HttpHelper const string GAM_CODE_TFA_USER_MUST_VALIDATE = "410"; const string GAM_CODE_TOKEN_EXPIRED = "103"; static Regex CapitalsToTitle = new Regex(@"(?<=[A-Z])(?=[A-Z][a-z]) | (?<=[^A-Z])(?=[A-Z]) | (?<=[A-Za-z])(?=[^A-Za-z])", RegexOptions.IgnorePatternWhitespace); - + internal const string InvalidCSRFToken = "InvalidCSRFToken"; const string CORS_MAX_AGE_SECONDS = "86400"; internal static void CorsHeaders(HttpContext httpContext) { @@ -286,10 +286,14 @@ internal static void TraceUnexpectedError(Exception ex) } internal static void SetUnexpectedError(HttpContext httpContext, HttpStatusCode statusCode, Exception ex) + { + string statusCodeDesc = StatusCodeToTitle(statusCode); + SetUnexpectedError(httpContext, statusCode, statusCodeDesc, ex); + } + internal static void SetUnexpectedError(HttpContext httpContext, HttpStatusCode statusCode, string statusCodeDesc, Exception ex) { TraceUnexpectedError(ex); string statusCodeStr = statusCode.ToString(INT_FORMAT); - string statusCodeDesc = StatusCodeToTitle(statusCode); SetResponseStatus(httpContext, statusCode, statusCodeDesc); SetJsonError(httpContext, statusCodeStr, statusCodeDesc); } diff --git a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs index 27cd41b07..239aa1a8f 100644 --- a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs +++ b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs @@ -38,17 +38,17 @@ namespace GeneXus.Http using System.Web; using System.Web.UI; using System.Web.UI.WebControls; - using System.Web.Script.Serialization; using System.Net; using GeneXus.Notifications; using Web.Security; using System.Web.SessionState; - using GeneXus.Mock; using GeneXus.Data.NTier; -#endif + using System.Web.Mvc; + using System.Security; +#endif #if NETCORE public abstract class GXHttpHandler : GXBaseObject, IHttpHandler #else @@ -1926,8 +1926,9 @@ public bool IsMain get { return _isMain; } } #endif - - +#if !NETCORE + [SecuritySafeCritical] +#endif public void ProcessRequest(HttpContext httpContext) { localHttpContext = httpContext; @@ -1955,6 +1956,9 @@ public void ProcessRequest(HttpContext httpContext) SetStreaming(); SendHeaders(); string clientid = context.ClientID; //Send clientid cookie (before response HasStarted) if necessary, since UseResponseBuffering is not in .netcore3.0 +#if !NETCORE + CSRFHelper.ValidateAntiforgery(httpContext); +#endif bool validSession = ValidWebSession(); if (validSession && IntegratedSecurityEnabled) @@ -1999,9 +2003,20 @@ public void ProcessRequest(HttpContext httpContext) context.CloseConnections(); } catch { } - Exception exceptionToHandle = e.InnerException ?? e; - handleException(exceptionToHandle.GetType().FullName, exceptionToHandle.Message, exceptionToHandle.StackTrace); - throw new Exception("GXApplication exception", e); +#if !NETCORE + if (e is HttpAntiForgeryException) + { + httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; + httpContext.Response.StatusDescription = HttpHelper.InvalidCSRFToken; + GXLogging.Error(log, $"Validation of antiforgery failed", e); + } + else +#endif + { + Exception exceptionToHandle = e.InnerException ?? e; + handleException(exceptionToHandle.GetType().FullName, exceptionToHandle.Message, exceptionToHandle.StackTrace); + throw new Exception("GXApplication exception", e); + } } } protected virtual bool ChunkedStreaming() { return false; } diff --git a/dotnet/src/dotnetframework/GxClasses/Services/GXRestServices.cs b/dotnet/src/dotnetframework/GxClasses/Services/GXRestServices.cs index 0d974268a..7f63cc340 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/GXRestServices.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/GXRestServices.cs @@ -389,10 +389,14 @@ public void WebException(Exception ex) { throw ex; } - else if (ex is FormatException || (RestAPIHelpers.ValidateCsrfToken() && AntiForgeryException(ex))) + else if (ex is FormatException) { HttpHelper.SetUnexpectedError(httpContext, HttpStatusCode.BadRequest, ex); } + else if (RestAPIHelpers.ValidateCsrfToken() && AntiForgeryException(ex)) + { + HttpHelper.SetUnexpectedError(httpContext, HttpStatusCode.BadRequest, HttpHelper.InvalidCSRFToken, ex); + } else { HttpHelper.SetUnexpectedError(httpContext, HttpStatusCode.InternalServerError, ex); diff --git a/dotnet/test/DotNetCoreAttackMitigationTest/Middleware/RestServiceTest.cs b/dotnet/test/DotNetCoreAttackMitigationTest/Middleware/RestServiceTest.cs index d292393c7..987a51b60 100644 --- a/dotnet/test/DotNetCoreAttackMitigationTest/Middleware/RestServiceTest.cs +++ b/dotnet/test/DotNetCoreAttackMitigationTest/Middleware/RestServiceTest.cs @@ -24,21 +24,19 @@ public RestServiceTest() : base() server.AllowSynchronousIO = true; } - - public async Task TestSimpleRestPost() + [Fact] + public async Task InvalidPostToRestService() { server.AllowSynchronousIO = true; HttpClient client = server.CreateClient(); StringContent body = new StringContent("{\"Image\":\"imageName\",\"ImageDescription\":\"imageDescription\"}"); HttpResponseMessage response = await client.PostAsync("rest/apps/saveimage", body); - Assert.Equal(System.Net.HttpStatusCode.BadRequest, response.StatusCode); + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); } - - public async Task RunController() + [Fact] + public async Task ValidPostToRestService() { - - - CookieContainer cookies = new System.Net.CookieContainer(); + CookieContainer cookies = new CookieContainer(); HttpClient client = server.CreateClient(); string requestUri = "rest/apps/append"; Uri requestUriObj = new Uri("http://localhost/" + requestUri); @@ -51,43 +49,76 @@ public async Task RunController() foreach (var item in SetCookieHeaderValue.ParseList(values.ToList())) cookies.Add(requestUriObj, new Cookie(item.Name.Value, item.Value.Value, item.Path.Value)); - var setCookie = SetCookieHeaderValue.ParseList(values.ToList()).FirstOrDefault(t => t.Name.Equals(HttpHeader.X_CSRF_TOKEN_COOKIE, StringComparison.OrdinalIgnoreCase)); + SetCookieHeaderValue setCookie = SetCookieHeaderValue.ParseList(values.ToList()).FirstOrDefault(t => t.Name.Equals(HttpHeader.X_CSRF_TOKEN_COOKIE, StringComparison.OrdinalIgnoreCase)); + Assert.NotNull(setCookie); + Assert.True(setCookie.Value.HasValue); csrfToken = setCookie.Value.Value; response.EnsureSuccessStatusCode(); - Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); //When failed, turn on log.config to see server side error. + Assert.Equal(HttpStatusCode.OK, response.StatusCode); //When failed, turn on log.config to see server side error. StringContent body = new StringContent("{\"Image\":\"imageName\",\"ImageDescription\":\"imageDescription\"}"); client.DefaultRequestHeaders.Add(HttpHeader.X_CSRF_TOKEN_HEADER, csrfToken); client.DefaultRequestHeaders.Add("Cookie", values);// //cookies.GetCookieHeader(requestUriObj)); response = await client.PostAsync("rest/apps/saveimage", body); - Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + } + [Fact] + public async Task ValidPostToHttpService() + { + CookieContainer cookies = new CookieContainer(); + HttpClient client = server.CreateClient(); + string requestUri = "webhook.aspx"; + Uri requestUriObj = new Uri("http://localhost/" + requestUri); + HttpResponseMessage response = await client.GetAsync(requestUri); + string csrfToken = string.Empty; + + IEnumerable values; + Assert.True(response.Headers.TryGetValues("Set-Cookie", out values)); + + foreach (var item in SetCookieHeaderValue.ParseList(values.ToList())) + cookies.Add(requestUriObj, new Cookie(item.Name.Value, item.Value.Value, item.Path.Value)); + + SetCookieHeaderValue setCookie = SetCookieHeaderValue.ParseList(values.ToList()).FirstOrDefault(t => t.Name.Equals(HttpHeader.X_CSRF_TOKEN_COOKIE, StringComparison.OrdinalIgnoreCase)); + Assert.NotNull(setCookie); + Assert.True(setCookie.Value.HasValue); + csrfToken = setCookie.Value.Value; + + response.EnsureSuccessStatusCode(); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); //When failed, turn on log.config to see server side error. + + client.DefaultRequestHeaders.Add(HttpHeader.X_CSRF_TOKEN_HEADER, csrfToken); + client.DefaultRequestHeaders.Add("Cookie", values);// //cookies.GetCookieHeader(requestUriObj)); + + response = await client.PostAsync(requestUri, null); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); } - public async Task HttpFirstPost() + [Fact] + public async Task InvalidPostToHttpService() { HttpClient client = server.CreateClient(); HttpResponseMessage response = await client.PostAsync("webhook.aspx", null); IEnumerable cookies = response.Headers.SingleOrDefault(header => header.Key == "Set-Cookie").Value; - foreach (string cookie in cookies) + if (cookies != null) { - Assert.False(cookie.StartsWith(HttpHeader.X_CSRF_TOKEN_COOKIE)); + foreach (string cookie in cookies) + { + Assert.False(cookie.StartsWith(HttpHeader.X_CSRF_TOKEN_COOKIE)); + } } - response.EnsureSuccessStatusCode(); - Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + Assert.Contains("InvalidCSRFToken", response.ReasonPhrase, StringComparison.OrdinalIgnoreCase); } - public async Task HttpFirstGet() + [Fact] + public async Task GetToHttpService() { HttpClient client = server.CreateClient(); HttpResponseMessage response = await client.GetAsync("webhook.aspx"); IEnumerable cookies = response.Headers.SingleOrDefault(header => header.Key == "Set-Cookie").Value; - foreach (string cookie in cookies) - { - Assert.False(cookie.StartsWith(HttpHeader.X_CSRF_TOKEN_COOKIE)); - } - + Assert.Contains(cookies, x => x.StartsWith(HttpHeader.X_CSRF_TOKEN_COOKIE, StringComparison.OrdinalIgnoreCase)); response.EnsureSuccessStatusCode(); - Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); } } } diff --git a/dotnet/test/DotNetCoreAttackMitigationTest/appsettings.json b/dotnet/test/DotNetCoreAttackMitigationTest/appsettings.json index 4eb415947..f97425b16 100644 --- a/dotnet/test/DotNetCoreAttackMitigationTest/appsettings.json +++ b/dotnet/test/DotNetCoreAttackMitigationTest/appsettings.json @@ -50,7 +50,7 @@ "CACHE_INVALIDATION_TOKEN": "20216211291931", "CORS_ALLOW_ORIGIN": "https://normal-website.com", "MY_CUSTOM_PTY": "DEFAULT_VALUE", - "ValidateCSRF": "1" + "CSRF_PROTECTION": "1" }, "languages": { "English": { From 82184217e64d4a3fbe63aceafa16bb2151ccc43e Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Thu, 28 Dec 2023 14:17:03 -0300 Subject: [PATCH 080/164] Add configuration option to set MinRequestBodyDataRate (#919) * Add configuration option to set MinRequestBodyDataRate https://learn.microsoft.com/en-us/answers/questions/1305885/why-do-we-get-this-error-reading-the-request-body * Fix on GetValueOrEnvironmentVarOf. --- dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs | 5 +++++ dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs index 0438dfdc3..e86d3bf46 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs @@ -165,6 +165,11 @@ public void ConfigureServices(IServiceCollection services) { options.AllowSynchronousIO = true; options.Limits.MaxRequestBodySize = null; + if (Config.GetValueOrEnvironmentVarOf("MinRequestBodyDataRate", out string MinRequestBodyDataRateStr) && double.TryParse(MinRequestBodyDataRateStr, out double MinRequestBodyDataRate)) + { + GXLogging.Info(log, $"MinRequestBodyDataRate:{MinRequestBodyDataRate}"); + options.Limits.MinRequestBodyDataRate = new MinDataRate(bytesPerSecond: MinRequestBodyDataRate, gracePeriod: TimeSpan.FromSeconds(10)); + } }); services.Configure(options => { diff --git a/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs b/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs index 3cd2fb6ba..00443b224 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs @@ -164,7 +164,7 @@ internal static bool GetValueOrEnvironmentVarOf(string sId, out string sString) sString = config.Get(sId); if (String.IsNullOrEmpty(sString)) { - MappedValue(sId, sString); + sString = MappedValue(sId, sString); if (string.IsNullOrEmpty(sString)) return false; } From 063487c0f5904d17fd069f487213329300fb2dc1 Mon Sep 17 00:00:00 2001 From: Claudia Murialdo Date: Thu, 28 Dec 2023 16:09:54 -0300 Subject: [PATCH 081/164] Move antiforgery exception handling to CSRFHelper. --- .../GxClasses/Helpers/CsrfHelper.cs | 14 ++++++++++++++ .../dotnetframework/GxClasses/Middleware/GXHttp.cs | 5 +---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/CsrfHelper.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/CsrfHelper.cs index f2b346659..24013e848 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/CsrfHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/CsrfHelper.cs @@ -1,7 +1,10 @@ +using System; +using System.Net; using System.Net.Http; using System.Security; using System.Web; using System.Web.Helpers; +using System.Web.Mvc; using GeneXus.Application; using GeneXus.Utils; @@ -9,6 +12,17 @@ namespace GeneXus.Http { internal class CSRFHelper { + internal static bool HandleException(Exception e, HttpContext httpContext) + { + if (RestAPIHelpers.ValidateCsrfToken() && e is HttpAntiForgeryException) + { + httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; + httpContext.Response.StatusDescription = HttpHelper.InvalidCSRFToken; + return true; + } + return false; + } + [SecuritySafeCritical] internal static void ValidateAntiforgery(HttpContext context) { diff --git a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs index 239aa1a8f..5cda2adab 100644 --- a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs +++ b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs @@ -43,7 +43,6 @@ namespace GeneXus.Http using Web.Security; using System.Web.SessionState; using GeneXus.Data.NTier; - using System.Web.Mvc; using System.Security; @@ -2004,10 +2003,8 @@ public void ProcessRequest(HttpContext httpContext) } catch { } #if !NETCORE - if (e is HttpAntiForgeryException) + if (CSRFHelper.HandleException(e, httpContext)) { - httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; - httpContext.Response.StatusDescription = HttpHelper.InvalidCSRFToken; GXLogging.Error(log, $"Validation of antiforgery failed", e); } else From ecfd587afcf4ac26703f27560d5272e6606144b2 Mon Sep 17 00:00:00 2001 From: Claudia Murialdo Date: Thu, 28 Dec 2023 16:10:51 -0300 Subject: [PATCH 082/164] Revert "Move antiforgery exception handling to CSRFHelper." This reverts commit 063487c0f5904d17fd069f487213329300fb2dc1. --- .../GxClasses/Helpers/CsrfHelper.cs | 14 -------------- .../dotnetframework/GxClasses/Middleware/GXHttp.cs | 5 ++++- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/CsrfHelper.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/CsrfHelper.cs index 24013e848..f2b346659 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/CsrfHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/CsrfHelper.cs @@ -1,10 +1,7 @@ -using System; -using System.Net; using System.Net.Http; using System.Security; using System.Web; using System.Web.Helpers; -using System.Web.Mvc; using GeneXus.Application; using GeneXus.Utils; @@ -12,17 +9,6 @@ namespace GeneXus.Http { internal class CSRFHelper { - internal static bool HandleException(Exception e, HttpContext httpContext) - { - if (RestAPIHelpers.ValidateCsrfToken() && e is HttpAntiForgeryException) - { - httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; - httpContext.Response.StatusDescription = HttpHelper.InvalidCSRFToken; - return true; - } - return false; - } - [SecuritySafeCritical] internal static void ValidateAntiforgery(HttpContext context) { diff --git a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs index 5cda2adab..239aa1a8f 100644 --- a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs +++ b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs @@ -43,6 +43,7 @@ namespace GeneXus.Http using Web.Security; using System.Web.SessionState; using GeneXus.Data.NTier; + using System.Web.Mvc; using System.Security; @@ -2003,8 +2004,10 @@ public void ProcessRequest(HttpContext httpContext) } catch { } #if !NETCORE - if (CSRFHelper.HandleException(e, httpContext)) + if (e is HttpAntiForgeryException) { + httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; + httpContext.Response.StatusDescription = HttpHelper.InvalidCSRFToken; GXLogging.Error(log, $"Validation of antiforgery failed", e); } else From 8be9e4c4aa747e983a7d19353f2dd2a3ae8deacf Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Thu, 28 Dec 2023 16:18:07 -0300 Subject: [PATCH 083/164] Move antiforgery exception handling to CSRFHelper. (#921) --- .../GxClasses/Helpers/CsrfHelper.cs | 14 ++++++++++++++ .../dotnetframework/GxClasses/Middleware/GXHttp.cs | 5 +---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/CsrfHelper.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/CsrfHelper.cs index f2b346659..7e399a54f 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/CsrfHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/CsrfHelper.cs @@ -1,7 +1,10 @@ +using System.Net; +using System; using System.Net.Http; using System.Security; using System.Web; using System.Web.Helpers; +using System.Web.Mvc; using GeneXus.Application; using GeneXus.Utils; @@ -9,6 +12,17 @@ namespace GeneXus.Http { internal class CSRFHelper { + internal static bool HandleException(Exception e, HttpContext httpContext) + { + if (RestAPIHelpers.ValidateCsrfToken() && e is HttpAntiForgeryException) + { + httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; + httpContext.Response.StatusDescription = HttpHelper.InvalidCSRFToken; + return true; + } + return false; + } + [SecuritySafeCritical] internal static void ValidateAntiforgery(HttpContext context) { diff --git a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs index 239aa1a8f..5cda2adab 100644 --- a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs +++ b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs @@ -43,7 +43,6 @@ namespace GeneXus.Http using Web.Security; using System.Web.SessionState; using GeneXus.Data.NTier; - using System.Web.Mvc; using System.Security; @@ -2004,10 +2003,8 @@ public void ProcessRequest(HttpContext httpContext) } catch { } #if !NETCORE - if (e is HttpAntiForgeryException) + if (CSRFHelper.HandleException(e, httpContext)) { - httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; - httpContext.Response.StatusDescription = HttpHelper.InvalidCSRFToken; GXLogging.Error(log, $"Validation of antiforgery failed", e); } else From 49fb09b5d12012b9552ad326705a1f7868ebd05d Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Fri, 29 Dec 2023 21:12:41 -0300 Subject: [PATCH 084/164] Eliminate the dependency on System.Web.WebPages when CSRF is disabled (#923) --- .../GxClasses/Helpers/CsrfHelper.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/CsrfHelper.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/CsrfHelper.cs index 7e399a54f..5b9490dbb 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/CsrfHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/CsrfHelper.cs @@ -14,7 +14,15 @@ internal class CSRFHelper { internal static bool HandleException(Exception e, HttpContext httpContext) { - if (RestAPIHelpers.ValidateCsrfToken() && e is HttpAntiForgeryException) + if (RestAPIHelpers.ValidateCsrfToken()) + { + return HandleExceptionImp(e, httpContext); + } + return false; + } + private static bool HandleExceptionImp(Exception e, HttpContext httpContext) + { + if (e is HttpAntiForgeryException) { httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; httpContext.Response.StatusDescription = HttpHelper.InvalidCSRFToken; @@ -28,11 +36,11 @@ internal static void ValidateAntiforgery(HttpContext context) { if (RestAPIHelpers.ValidateCsrfToken()) { - ValidateAntiforgeryImpl(context); + ValidateAntiforgeryImp(context); } } [SecurityCritical] - static void ValidateAntiforgeryImpl(HttpContext context) + private static void ValidateAntiforgeryImp(HttpContext context) { string cookieToken, formToken; string httpMethod = context.Request.HttpMethod; From 49e69a0e7f8b2c72b517cdde03a1396609c5a763 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Sexenian?= <99925035+tomas-sexenian@users.noreply.github.com> Date: Tue, 2 Jan 2024 12:24:37 -0300 Subject: [PATCH 085/164] Remove the ; at the end of httpclient variable (#916) Issue: 106225 --- dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs index 0f3b40e4a..b536ad6c1 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs @@ -51,7 +51,7 @@ internal MultiPartTemplate() Boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x"); ContentType = $"multipart/form-data; boundary={Boundary}"; FormdataSeparator = "\r\n"; - FormdataTemplate = "--" + Boundary + "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}"; + FormdataTemplate = "--" + Boundary + "\r\nContent-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}"; Boundarybytes = Encoding.ASCII.GetBytes($"\r\n--{Boundary}\r\n"); EndBoundaryBytes = Encoding.ASCII.GetBytes($"\r\n--{Boundary}--"); HeaderTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" + "Content-Type: {2}\r\n\r\n"; From 7e60ef5859fd30e250ea58ed6fe50940c9d0764f Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Thu, 4 Jan 2024 17:09:40 -0300 Subject: [PATCH 086/164] Add support to azure functions triggered by Event Grid (#920) --- .../Handlers/Dummies/EventGridTriggerDummy.cs | 22 +++ .../EventGridTriggerHandlerAzure.cs | 187 ++++++++++++++++++ .../EventGridTriggerHandlerCloud.cs | 187 ++++++++++++++++++ ...eXus.Deploy.AzureFunctions.Handlers.csproj | 8 +- .../Azure/Handlers/Helpers/EventSourceType.cs | 2 +- .../AzureFunctionsTest/EventGridTrigger.cs | 102 ++++++++++ .../test/AzureFunctionsTest/gxazmappings.json | 19 +- 7 files changed, 524 insertions(+), 3 deletions(-) create mode 100644 dotnet/src/extensions/Azure/Handlers/Dummies/EventGridTriggerDummy.cs create mode 100644 dotnet/src/extensions/Azure/Handlers/EventGridHandler/EventGridTriggerHandlerAzure.cs create mode 100644 dotnet/src/extensions/Azure/Handlers/EventGridHandler/EventGridTriggerHandlerCloud.cs create mode 100644 dotnet/src/extensions/Azure/test/AzureFunctionsTest/EventGridTrigger.cs diff --git a/dotnet/src/extensions/Azure/Handlers/Dummies/EventGridTriggerDummy.cs b/dotnet/src/extensions/Azure/Handlers/Dummies/EventGridTriggerDummy.cs new file mode 100644 index 000000000..0d0c4c489 --- /dev/null +++ b/dotnet/src/extensions/Azure/Handlers/Dummies/EventGridTriggerDummy.cs @@ -0,0 +1,22 @@ +using Azure.Messaging; +using Azure.Messaging.EventGrid; +using GeneXus.Deploy.AzureFunctions.Handlers.Helpers; +using Microsoft.Azure.Functions.Worker; + +namespace EventGridTriggerDummy +{ + public static class EventGridFunction + { + + [Function("EventGridFunctionCloudSchema")] + public static void Run([EventGridTrigger] CloudEvent input, FunctionContext context) + { + + } + [Function("EventGridFunctionAzureSchema")] + public static void Run([EventGridTrigger] EventGridEvent input, FunctionContext context) + { + + } + } +} \ No newline at end of file diff --git a/dotnet/src/extensions/Azure/Handlers/EventGridHandler/EventGridTriggerHandlerAzure.cs b/dotnet/src/extensions/Azure/Handlers/EventGridHandler/EventGridTriggerHandlerAzure.cs new file mode 100644 index 000000000..4bb5e0337 --- /dev/null +++ b/dotnet/src/extensions/Azure/Handlers/EventGridHandler/EventGridTriggerHandlerAzure.cs @@ -0,0 +1,187 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Text; +using System.Text.Json; +using Azure.Messaging; +using Azure.Messaging.EventGrid; +using GeneXus.Application; +using GeneXus.Deploy.AzureFunctions.Handlers.Helpers; +using GeneXus.Metadata; +using GeneXus.Utils; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Extensions.Logging; + +namespace GeneXus.Deploy.AzureFunctions.EventGridHandler +{ + public class EventGridTriggerHandlerAzure + { + private ICallMappings _callmappings; + + public EventGridTriggerHandlerAzure(ICallMappings callMappings) + { + _callmappings = callMappings; + } + public void Run(EventGridEvent input, FunctionContext context) + { + var logger = context.GetLogger("EventGridTriggerHandler"); + string functionName = context.FunctionDefinition.Name; + Guid eventId = new Guid(context.InvocationId); + logger.LogInformation($"GeneXus Event Grid trigger handler. Function processed: {functionName}. Event Id: {eventId}. Function executed at: {DateTime.Now}."); + + try + { + ProcessEvent(context, logger, input, eventId.ToString()); + } + catch (Exception ex) //Catch System exception and retry + { + logger.LogError(ex.ToString()); + throw; + } + } + private void ProcessEvent(FunctionContext context, ILogger log, EventGridEvent input, string eventId) + { + CallMappings callmap = (CallMappings)_callmappings; + + GxAzMappings map = callmap.mappings is object ? callmap.mappings.First(m => m.FunctionName == context.FunctionDefinition.Name) : null; + string gxProcedure = (map != null && map is object) ? map.GXEntrypoint : string.Empty; + string exMessage; + + if (!string.IsNullOrEmpty(gxProcedure)) + { + try + { + StringBuilder sb1 = new StringBuilder(gxProcedure); + sb1.Append(".dll"); + string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), sb1.ToString()); + Assembly obj = Assembly.LoadFile(path); + + StringBuilder sb2 = new StringBuilder("GeneXus.Programs."); + sb2.Append(gxProcedure); + + Type objexec = obj.GetType(sb2.ToString()); + if (objexec != null) + { + object objgxproc = Activator.CreateInstance(objexec); + var method = objexec.GetMethod("execute"); + ParameterInfo[] parameters = method.GetParameters(); + + //Check parameters + + if (parameters.Length != 2) + { + //Thrown to the Azure monitor + + exMessage = string.Format("{0} Error for Event Id {1}: the number of parameters in GeneXus procedure is not correct.", FunctionExceptionType.SysRuntimeError, eventId); + throw new Exception(exMessage); //Send to retry if possible. + } + else + { + //Two valid signatures for the GX procedure: + //parm(in:&EventMessageCollection, out:&ExternalEventMessageResponse ); + //parm(in:&rawData, out:&ExternalEventMessageResponse ); + + GxContext gxcontext = new GxContext(); + object[] parametersdata; + parametersdata = new object[] { null }; + + if (parameters[0].ParameterType == typeof(string)) + { + string eventMessageSerialized = string.Empty; + eventMessageSerialized = JsonSerializer.Serialize(input); + parametersdata = new object[] { eventMessageSerialized, null }; + } + else + { + + //Initialization + + Type eventMessagesType = parameters[0].ParameterType; //SdtEventMessages + GxUserType eventMessages = (GxUserType)Activator.CreateInstance(eventMessagesType, new object[] { gxcontext }); // instance of SdtEventMessages + + IList eventMessage = (IList)ClassLoader.GetPropValue(eventMessages, "gxTpr_Eventmessage");//instance of GXBaseCollection + Type eventMessageItemType = eventMessage.GetType().GetGenericArguments()[0];//SdtEventMessage + + GxUserType eventMessageItem = (GxUserType)Activator.CreateInstance(eventMessageItemType, new object[] { gxcontext }); // instance of SdtEventMessage + + IList eventMessageProperties = (IList)ClassLoader.GetPropValue(eventMessageItem, "gxTpr_Eventmessageproperties");//instance of GXBaseCollection + Type eventMessPropsItemType = eventMessageProperties.GetType().GetGenericArguments()[0];//SdtEventMessageProperty + + GxUserType eventMessageProperty; + + if (input.Subject != null) + { + eventMessageProperty = EventMessagePropertyMapping.CreateEventMessageProperty(eventMessPropsItemType, "Subject", input.Subject, gxcontext); + eventMessageProperties.Add(eventMessageProperty); + } + + if (input.Topic != null) + { + eventMessageProperty = EventMessagePropertyMapping.CreateEventMessageProperty(eventMessPropsItemType, "Topic", input.Topic, gxcontext); + eventMessageProperties.Add(eventMessageProperty); + } + + //Event + + ClassLoader.SetPropValue(eventMessageItem, "gxTpr_Eventmessageid", input.Id); + ClassLoader.SetPropValue(eventMessageItem, "gxTpr_Eventmessagesourcetype", input.EventType); + ClassLoader.SetPropValue(eventMessageItem, "gxTpr_Eventmessageversion", input.DataVersion); + ClassLoader.SetPropValue(eventMessageItem, "gxTpr_Eventmessageproperties", eventMessageProperties); + ClassLoader.SetPropValue(eventMessageItem, "gxTpr_Eventmessagedate", input.EventTime.UtcDateTime); + ClassLoader.SetPropValue(eventMessageItem, "gxTpr_Eventmessagedata", input.Data.ToString()); + + //List of Events + eventMessage.Add(eventMessageItem); + parametersdata = new object[] { eventMessages, null }; + } + + try + { + method.Invoke(objgxproc, parametersdata); + GxUserType EventMessageResponse = parametersdata[1] as GxUserType;//SdtEventMessageResponse + bool result = (bool)ClassLoader.GetPropValue(EventMessageResponse, "gxTpr_Handlefailure"); + + //Error handling + + if (result == true) //Must retry + { + exMessage = string.Format("{0} {1}", FunctionExceptionType.AppError, ClassLoader.GetPropValue(EventMessageResponse, "gxTpr_Errormessage")); + throw new Exception(exMessage); + } + else + { + log.LogInformation("(GX function handler) Function finished execution."); + } + } + catch (Exception) + { + log.LogError("{0} Error invoking the GX procedure for Event Id {1}.", FunctionExceptionType.SysRuntimeError, eventId); + throw; //Throw the exception so the runtime can Retry the operation. + } + } + } + else + { + exMessage = string.Format("{0} GeneXus procedure could not be executed for Event Id {1}.", FunctionExceptionType.SysRuntimeError, eventId); + throw new Exception(exMessage); + } + } + catch (Exception) + { + log.LogError("{0} Error processing Event Id {1}.", FunctionExceptionType.SysRuntimeError, eventId); + throw; //Throw the exception so the runtime can Retry the operation. + } + } + else + { + exMessage = string.Format("{0} GeneXus procedure could not be executed while processing Event Id {1}. Reason: procedure not specified in configuration file.", FunctionExceptionType.SysRuntimeError, eventId); + throw new Exception(exMessage); + } + } + } +} + diff --git a/dotnet/src/extensions/Azure/Handlers/EventGridHandler/EventGridTriggerHandlerCloud.cs b/dotnet/src/extensions/Azure/Handlers/EventGridHandler/EventGridTriggerHandlerCloud.cs new file mode 100644 index 000000000..4ae40dfc7 --- /dev/null +++ b/dotnet/src/extensions/Azure/Handlers/EventGridHandler/EventGridTriggerHandlerCloud.cs @@ -0,0 +1,187 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Text; +using System.Text.Json; +using Azure.Messaging; +using GeneXus.Application; +using GeneXus.Deploy.AzureFunctions.Handlers.Helpers; +using GeneXus.Metadata; +using GeneXus.Utils; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Extensions.Logging; + +namespace GeneXus.Deploy.AzureFunctions.EventGridHandler +{ + public class EventGridTriggerHandlerCloud + { + private ICallMappings _callmappings; + + public EventGridTriggerHandlerCloud(ICallMappings callMappings) + { + _callmappings = callMappings; + } + public void Run(CloudEvent input, FunctionContext context) + { + var logger = context.GetLogger("EventGridTriggerHandler"); + string functionName = context.FunctionDefinition.Name; + Guid eventId = new Guid(context.InvocationId); + logger.LogInformation($"GeneXus Event Grid trigger handler. Function processed: {functionName}. Event Id: {eventId}. Function executed at: {DateTime.Now}."); + + try + { + ProcessEvent(context, logger, input, eventId.ToString()); + } + catch (Exception ex) //Catch System exception and retry + { + logger.LogError(ex.ToString()); + throw; + } + } + private void ProcessEvent(FunctionContext context, ILogger log, CloudEvent input, string eventId) + { + CallMappings callmap = (CallMappings)_callmappings; + + GxAzMappings map = callmap.mappings is object ? callmap.mappings.First(m => m.FunctionName == context.FunctionDefinition.Name) : null; + string gxProcedure = (map != null && map is object) ? map.GXEntrypoint : string.Empty; + string exMessage; + + if (!string.IsNullOrEmpty(gxProcedure)) + { + try + { + StringBuilder sb1 = new StringBuilder(gxProcedure); + sb1.Append(".dll"); + string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), sb1.ToString()); + Assembly obj = Assembly.LoadFile(path); + + StringBuilder sb2 = new StringBuilder("GeneXus.Programs."); + sb2.Append(gxProcedure); + + Type objexec = obj.GetType(sb2.ToString()); + if (objexec != null) + { + object objgxproc = Activator.CreateInstance(objexec); + var method = objexec.GetMethod("execute"); + ParameterInfo[] parameters = method.GetParameters(); + + //Check parameters + + if (parameters.Length != 2) + { + //Thrown to the Azure monitor + + exMessage = string.Format("{0} Error for Event Id {1}: the number of parameters in GeneXus procedure is not correct.", FunctionExceptionType.SysRuntimeError, eventId); + throw new Exception(exMessage); //Send to retry if possible. + } + else + { + //Two valid signatures for the GX procedure: + //parm(in:&EventMessageCollection, out:&ExternalEventMessageResponse ); + //parm(in:&rawData, out:&ExternalEventMessageResponse ); + + GxContext gxcontext = new GxContext(); + object[] parametersdata; + parametersdata = new object[] { null }; + + if (parameters[0].ParameterType == typeof(string)) + { + string eventMessageSerialized = string.Empty; + eventMessageSerialized = JsonSerializer.Serialize(input); + parametersdata = new object[] { eventMessageSerialized, null }; + } + else + { + + //Initialization + + Type eventMessagesType = parameters[0].ParameterType; //SdtEventMessages + GxUserType eventMessages = (GxUserType)Activator.CreateInstance(eventMessagesType, new object[] { gxcontext }); // instance of SdtEventMessages + + IList eventMessage = (IList)ClassLoader.GetPropValue(eventMessages, "gxTpr_Eventmessage");//instance of GXBaseCollection + Type eventMessageItemType = eventMessage.GetType().GetGenericArguments()[0];//SdtEventMessage + + GxUserType eventMessageItem = (GxUserType)Activator.CreateInstance(eventMessageItemType, new object[] { gxcontext }); // instance of SdtEventMessage + + IList eventMessageProperties = (IList)ClassLoader.GetPropValue(eventMessageItem, "gxTpr_Eventmessageproperties");//instance of GXBaseCollection + Type eventMessPropsItemType = eventMessageProperties.GetType().GetGenericArguments()[0];//SdtEventMessageProperty + + GxUserType eventMessageProperty; + + if (input.Subject != null) + { + eventMessageProperty = EventMessagePropertyMapping.CreateEventMessageProperty(eventMessPropsItemType, "Subject", input.Subject, gxcontext); + eventMessageProperties.Add(eventMessageProperty); + } + + if (input.Source != null) + { + eventMessageProperty = EventMessagePropertyMapping.CreateEventMessageProperty(eventMessPropsItemType, "Source", input.Source, gxcontext); + eventMessageProperties.Add(eventMessageProperty); + } + + //Event + + ClassLoader.SetPropValue(eventMessageItem, "gxTpr_Eventmessageid", input.Id); + ClassLoader.SetPropValue(eventMessageItem, "gxTpr_Eventmessagesourcetype", input.Type); + ClassLoader.SetPropValue(eventMessageItem, "gxTpr_Eventmessageversion", string.Empty); + ClassLoader.SetPropValue(eventMessageItem, "gxTpr_Eventmessageproperties", eventMessageProperties); + ClassLoader.SetPropValue(eventMessageItem, "gxTpr_Eventmessagedate", input.Time.Value.UtcDateTime); + ClassLoader.SetPropValue(eventMessageItem, "gxTpr_Eventmessagedata", input.Data.ToString()); + + + //List of Events + eventMessage.Add(eventMessageItem); + parametersdata = new object[] { eventMessages, null }; + } + + try + { + method.Invoke(objgxproc, parametersdata); + GxUserType EventMessageResponse = parametersdata[1] as GxUserType;//SdtEventMessageResponse + bool result = (bool)ClassLoader.GetPropValue(EventMessageResponse, "gxTpr_Handlefailure"); + + //Error handling + + if (result == true) //Must retry + { + exMessage = string.Format("{0} {1}", FunctionExceptionType.AppError, ClassLoader.GetPropValue(EventMessageResponse, "gxTpr_Errormessage")); + throw new Exception(exMessage); + } + else + { + log.LogInformation("(GX function handler) Function finished execution."); + } + } + catch (Exception) + { + log.LogError("{0} Error invoking the GX procedure for Event Id {1}.", FunctionExceptionType.SysRuntimeError, eventId); + throw; //Throw the exception so the runtime can Retry the operation. + } + } + } + else + { + exMessage = string.Format("{0} GeneXus procedure could not be executed for Event Id {1}.", FunctionExceptionType.SysRuntimeError, eventId); + throw new Exception(exMessage); + } + } + catch (Exception) + { + log.LogError("{0} Error processing Event Id {1}.", FunctionExceptionType.SysRuntimeError, eventId); + throw; //Throw the exception so the runtime can Retry the operation. + } + } + else + { + exMessage = string.Format("{0} GeneXus procedure could not be executed while processing Event Id {1}. Reason: procedure not specified in configuration file.", FunctionExceptionType.SysRuntimeError, eventId); + throw new Exception(exMessage); + } + } + } +} + diff --git a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj b/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj index 609e2d6c2..a49099aa5 100644 --- a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj +++ b/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj @@ -17,6 +17,7 @@ true true true + true @@ -61,11 +62,16 @@ + + + + + - + diff --git a/dotnet/src/extensions/Azure/Handlers/Helpers/EventSourceType.cs b/dotnet/src/extensions/Azure/Handlers/Helpers/EventSourceType.cs index 2d2e94f80..ecc7f6af0 100644 --- a/dotnet/src/extensions/Azure/Handlers/Helpers/EventSourceType.cs +++ b/dotnet/src/extensions/Azure/Handlers/Helpers/EventSourceType.cs @@ -1,7 +1,7 @@ +using System; using GeneXus.Application; using GeneXus.Metadata; using GeneXus.Utils; -using System; namespace GeneXus.Deploy.AzureFunctions.Handlers.Helpers { diff --git a/dotnet/src/extensions/Azure/test/AzureFunctionsTest/EventGridTrigger.cs b/dotnet/src/extensions/Azure/test/AzureFunctionsTest/EventGridTrigger.cs new file mode 100644 index 000000000..96cc8a06d --- /dev/null +++ b/dotnet/src/extensions/Azure/test/AzureFunctionsTest/EventGridTrigger.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Messaging; +using Azure.Messaging.EventGrid; +using GeneXus.Deploy.AzureFunctions.EventGridHandler; +using GeneXus.Deploy.AzureFunctions.Handlers.Helpers; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace Extensions.AzureFunctions.Test +{ + public class EventGridTriggerTest + { + + [Fact] + public void EventGridTestCloudEventSchema() + { + try + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddScoped(); + var serviceProvider = serviceCollection.BuildServiceProvider(); + + var context = new Mock(); + context.SetupProperty(c => c.InstanceServices, serviceProvider); + + context.SetupGet(c => c.FunctionId).Returns("815504e67081459c9ef1d0399a4aeda3"); + context.SetupGet(c => c.FunctionDefinition.Name).Returns("eventgridTest"); + context.SetupGet(c => c.InvocationId).Returns("d1934e45f752478d899ddb87d262f313"); + + ICallMappings callMappings = new CallMappings("."); + + + IReadOnlyDictionary bindingData = new Dictionary() + { + { + "Id", new PropertyId { Id = "75c7ead6-6485-4aeb-9b31-a0778b4d64a3"} + }, + }; + + Object data = "{\r\n \"api\": \"PutBlockList\",\r\n \"clientRequestId\": \"4c5dd7fb-2c48-4a27-bb30-5361b5de920a\",\r\n \"requestId\": \"9aeb0fdf-c01e-0131-0922-9eb549000000\",\r\n \"eTag\": \"0x8D76C39E4407333\",\r\n \"contentType\": \"image/png\",\r\n \"contentLength\": 30699,\r\n \"blobType\": \"BlockBlob\",\r\n \"url\": \"https://gridtesting.blob.core.windows.net/testcontainer/{new-file}\",\r\n \"sequencer\": \"000000000000000000000000000099240000000000c41c18\",\r\n \"storageDiagnostics\": {\r\n \"batchId\": \"681fe319-3006-00a8-0022-9e7cde000000\"\r\n }"; + context.SetupGet(c => c.BindingContext.BindingData).Returns(bindingData); + + CloudEvent cloudEvent = new("\"/subscriptions/{subscription-id}/resourceGroups/{resource-group}/providers/Microsoft.Storage/storageAccounts/{storage-account}\"", "Microsoft.Storage.BlobCreated", data); + var ex = Record.Exception(() => new EventGridTriggerHandlerCloud(callMappings).Run(cloudEvent, context.Object)); + Assert.Null(ex); + + } catch(Exception ex) + { + throw new Exception("Exception should not be thrown.", ex); + } + + } + + [Fact] + public void EventGridTestAzureSchema() + { + try + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddScoped(); + var serviceProvider = serviceCollection.BuildServiceProvider(); + + var context = new Mock(); + context.SetupProperty(c => c.InstanceServices, serviceProvider); + + context.SetupGet(c => c.FunctionId).Returns("39e90db641d94d81b0e854016dcffef9"); + context.SetupGet(c => c.FunctionDefinition.Name).Returns("eventgridTestAzureSchema"); + context.SetupGet(c => c.InvocationId).Returns("4ceabb102cbc48378f58bbc3911d348d"); + + ICallMappings callMappings = new CallMappings("."); + + + IReadOnlyDictionary bindingData = new Dictionary() + { + { + "Id", new PropertyId { Id = "514fa418-08fc-4aab-ba41-ed00375b6928"} + }, + }; + + + context.SetupGet(c => c.BindingContext.BindingData).Returns(bindingData); + + Object data = "{\r\n \"api\": \"PutBlockList\",\r\n \"clientRequestId\": \"4c5dd7fb-2c48-4a27-bb30-5361b5de920a\",\r\n \"requestId\": \"9aeb0fdf-c01e-0131-0922-9eb549000000\",\r\n \"eTag\": \"0x8D76C39E4407333\",\r\n \"contentType\": \"image/png\",\r\n \"contentLength\": 30699,\r\n \"blobType\": \"BlockBlob\",\r\n \"url\": \"https://gridtesting.blob.core.windows.net/testcontainer/{new-file}\",\r\n \"sequencer\": \"000000000000000000000000000099240000000000c41c18\",\r\n \"storageDiagnostics\": {\r\n \"batchId\": \"681fe319-3006-00a8-0022-9e7cde000000\"\r\n }"; + EventGridEvent eventGridEvent = new EventGridEvent("TestEventAzureEventGridSchema", "GXTest", "1.0", data); + + var ex = Record.Exception(() => new EventGridTriggerHandlerAzure(callMappings).Run(eventGridEvent, context.Object)); + Assert.Null(ex); + + } + catch (Exception ex) + { + throw new Exception("Exception should not be thrown.", ex); + } + + } + } +} \ No newline at end of file diff --git a/dotnet/src/extensions/Azure/test/AzureFunctionsTest/gxazmappings.json b/dotnet/src/extensions/Azure/test/AzureFunctionsTest/gxazmappings.json index ea2febc38..3342d6577 100644 --- a/dotnet/src/extensions/Azure/test/AzureFunctionsTest/gxazmappings.json +++ b/dotnet/src/extensions/Azure/test/AzureFunctionsTest/gxazmappings.json @@ -1 +1,18 @@ -[{"FunctionName":"timerTest","GXEntrypoint":"amyprochandler"},{"FunctionName":"queueTest","GXEntrypoint":"amyprochandler"}] \ No newline at end of file +[ + { + "FunctionName": "timerTest", + "GXEntrypoint": "amyprochandler" + }, + { + "FunctionName": "queueTest", + "GXEntrypoint": "amyprochandler" + }, + { + "FunctionName": "eventgridTest", + "GXEntrypoint": "amyprochandler" + }, + { + "FunctionName": "eventgridTestAzureSchema", + "GXEntrypoint": "amyprochandler" + } +] \ No newline at end of file From f6f93ad041d999aa8715639bc29764d69fb06717 Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Thu, 11 Jan 2024 09:39:59 -0300 Subject: [PATCH 087/164] Export metrics in applications using OTEL (#924) --- .../DynService.Core/DynService.Core.csproj | 4 +++ .../DynService.DynamoDB.csproj | 1 + .../Cosmos/DynService.CosmosDB.csproj | 3 +- .../DynService/OData/DynServiceOData.csproj | 1 + .../GxClasses.Web/GxClasses.Web.csproj | 5 ++-- .../src/dotnetcore/GxClasses/GxClasses.csproj | 14 +++++----- .../GXDataInitialization.csproj | 4 +++ dotnet/src/dotnetcore/GxExcel/GxExcel.csproj | 1 + dotnet/src/dotnetcore/GxMail/GxMail.csproj | 1 + dotnet/src/dotnetcore/GxMaps/GxMaps.csproj | 5 +++- .../GxNetCoreStartup/GxNetCoreStartup.csproj | 12 ++++---- .../src/dotnetcore/GxOffice/GxOffice.csproj | 1 + .../GxPdfReportsCS/GxPdfReportsCS.csproj | 1 + .../src/dotnetcore/GxSearch/GxSearch.csproj | 1 + .../Projects/StoreManager/StoreManager.csproj | 3 +- .../Cache/GxMemcached/GxMemcached.csproj | 3 +- .../Providers/Cache/GxRedis/GxRedis.csproj | 4 +++ .../GXAzureEventGrid/GXAzureEventGrid.csproj | 2 +- .../GXAzureQueue/GXAzureQueue.csproj | 2 +- .../GXAzureServiceBus.csproj | 2 +- .../GXEventRouter/GXEventRouter.csproj | 4 +++ .../GXMessageBroker/GXMessageBroker.csproj | 5 ++++ .../Messaging/GXQueue/GXQueue.csproj | 6 +++- .../GXOtel.Diagnostics.csproj | 4 +-- .../OpenTelemetry/GXMeterProviderBuilder.cs | 28 +++++++++++++++++++ .../GeneXus.OpenTelemetry.csproj | 12 ++++---- .../OpenTelemetry/GxTraceProviderBuilder.cs | 11 ++++---- .../OpenTelemetry/OpenTelemetryProvider.cs | 7 +++++ .../AzureAppInsights.cs | 1 + ...Xus.OpenTelemetry.Azure.AppInsights.csproj | 8 +++--- .../Storage/GXAmazonS3/GXAmazonS3.csproj | 1 + .../GXAzureStorage/GXAzureStorage.csproj | 1 + .../GXGoogleCloud/GXGoogleCloud.csproj | 1 + dotnet/src/dotnetcore/Reor/Reor.csproj | 4 +++ .../dotnetframework/GxOffice/GxOffice.csproj | 1 + ...eXus.Deploy.AzureFunctions.Handlers.csproj | 2 +- .../AzureFunctionsTest.csproj | 2 +- .../GeneXus.Programs.Common.csproj | 4 +++ .../amyprocedurehandler/amyprochandler.csproj | 4 +++ .../test/apiattractions/apiattractions.csproj | 4 +++ .../src/MockDBAccess/MockDBAccess.csproj | 4 +++ .../DotNetCoreAttackMitigationTest.csproj | 1 + .../DotNetCoreChunkedTest.csproj | 1 + .../DotNetCoreCmdTest.csproj | 1 + .../DotNetCoreOpenTelemetryTest.csproj | 1 + .../DotNetCoreWebUnitTest.csproj | 1 + .../DotNetPdfTest/DotNetPDFUnitTest.csproj | 1 + .../DotNetRedisTest/DotNetRedisTest.csproj | 3 +- 48 files changed, 149 insertions(+), 44 deletions(-) create mode 100644 dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/GXMeterProviderBuilder.cs diff --git a/dotnet/src/dotnetcommon/DynService.Core/DynService.Core.csproj b/dotnet/src/dotnetcommon/DynService.Core/DynService.Core.csproj index dde00ac2a..45d27f4a7 100644 --- a/dotnet/src/dotnetcommon/DynService.Core/DynService.Core.csproj +++ b/dotnet/src/dotnetcommon/DynService.Core/DynService.Core.csproj @@ -18,4 +18,8 @@ + + + + \ No newline at end of file diff --git a/dotnet/src/dotnetcommon/DynService.Dynamo/DynService.DynamoDB.csproj b/dotnet/src/dotnetcommon/DynService.Dynamo/DynService.DynamoDB.csproj index 58d869618..16e8434b3 100644 --- a/dotnet/src/dotnetcommon/DynService.Dynamo/DynService.DynamoDB.csproj +++ b/dotnet/src/dotnetcommon/DynService.Dynamo/DynService.DynamoDB.csproj @@ -13,6 +13,7 @@ + diff --git a/dotnet/src/dotnetcore/DynService/Cosmos/DynService.CosmosDB.csproj b/dotnet/src/dotnetcore/DynService/Cosmos/DynService.CosmosDB.csproj index 281cac6cd..0c61c7593 100644 --- a/dotnet/src/dotnetcore/DynService/Cosmos/DynService.CosmosDB.csproj +++ b/dotnet/src/dotnetcore/DynService/Cosmos/DynService.CosmosDB.csproj @@ -13,8 +13,9 @@ - + + diff --git a/dotnet/src/dotnetcore/DynService/OData/DynServiceOData.csproj b/dotnet/src/dotnetcore/DynService/OData/DynServiceOData.csproj index 0d2a21dba..d57e3d3ee 100644 --- a/dotnet/src/dotnetcore/DynService/OData/DynServiceOData.csproj +++ b/dotnet/src/dotnetcore/DynService/OData/DynServiceOData.csproj @@ -12,6 +12,7 @@ + diff --git a/dotnet/src/dotnetcore/GxClasses.Web/GxClasses.Web.csproj b/dotnet/src/dotnetcore/GxClasses.Web/GxClasses.Web.csproj index eb48e4e06..e95fc82c8 100644 --- a/dotnet/src/dotnetcore/GxClasses.Web/GxClasses.Web.csproj +++ b/dotnet/src/dotnetcore/GxClasses.Web/GxClasses.Web.csproj @@ -29,8 +29,9 @@ - - + + + diff --git a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj index 43b211dc5..1805e02db 100644 --- a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj +++ b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj @@ -1,4 +1,4 @@ - + net6.0;net8.0 @@ -157,12 +157,12 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - + + + + + + diff --git a/dotnet/src/dotnetcore/GxDataInitialization/GXDataInitialization.csproj b/dotnet/src/dotnetcore/GxDataInitialization/GXDataInitialization.csproj index 886477ee5..31547472d 100644 --- a/dotnet/src/dotnetcore/GxDataInitialization/GXDataInitialization.csproj +++ b/dotnet/src/dotnetcore/GxDataInitialization/GXDataInitialization.csproj @@ -12,6 +12,10 @@ + + + + diff --git a/dotnet/src/dotnetcore/GxExcel/GxExcel.csproj b/dotnet/src/dotnetcore/GxExcel/GxExcel.csproj index 775944fc7..2c747897b 100644 --- a/dotnet/src/dotnetcore/GxExcel/GxExcel.csproj +++ b/dotnet/src/dotnetcore/GxExcel/GxExcel.csproj @@ -16,6 +16,7 @@ + diff --git a/dotnet/src/dotnetcore/GxMail/GxMail.csproj b/dotnet/src/dotnetcore/GxMail/GxMail.csproj index 61616d6d9..b9210f368 100644 --- a/dotnet/src/dotnetcore/GxMail/GxMail.csproj +++ b/dotnet/src/dotnetcore/GxMail/GxMail.csproj @@ -66,6 +66,7 @@ + diff --git a/dotnet/src/dotnetcore/GxMaps/GxMaps.csproj b/dotnet/src/dotnetcore/GxMaps/GxMaps.csproj index 2cf496f09..dc95fa2c3 100644 --- a/dotnet/src/dotnetcore/GxMaps/GxMaps.csproj +++ b/dotnet/src/dotnetcore/GxMaps/GxMaps.csproj @@ -15,4 +15,7 @@ - \ No newline at end of file + + + + \ No newline at end of file diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj b/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj index 5b87ea4a0..42af849da 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj @@ -16,13 +16,13 @@ - + - - - - - + + + + + diff --git a/dotnet/src/dotnetcore/GxOffice/GxOffice.csproj b/dotnet/src/dotnetcore/GxOffice/GxOffice.csproj index 3169f7bcf..094c0b13e 100644 --- a/dotnet/src/dotnetcore/GxOffice/GxOffice.csproj +++ b/dotnet/src/dotnetcore/GxOffice/GxOffice.csproj @@ -36,6 +36,7 @@ + diff --git a/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj b/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj index 01a52310d..ab6fb41c6 100644 --- a/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj +++ b/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj @@ -17,6 +17,7 @@ + diff --git a/dotnet/src/dotnetcore/GxSearch/GxSearch.csproj b/dotnet/src/dotnetcore/GxSearch/GxSearch.csproj index 961485e8c..0b3f8ae7d 100644 --- a/dotnet/src/dotnetcore/GxSearch/GxSearch.csproj +++ b/dotnet/src/dotnetcore/GxSearch/GxSearch.csproj @@ -20,6 +20,7 @@ + diff --git a/dotnet/src/dotnetcore/Projects/StoreManager/StoreManager.csproj b/dotnet/src/dotnetcore/Projects/StoreManager/StoreManager.csproj index 05981128e..b4815e353 100644 --- a/dotnet/src/dotnetcore/Projects/StoreManager/StoreManager.csproj +++ b/dotnet/src/dotnetcore/Projects/StoreManager/StoreManager.csproj @@ -27,8 +27,9 @@ - + + diff --git a/dotnet/src/dotnetcore/Providers/Cache/GxMemcached/GxMemcached.csproj b/dotnet/src/dotnetcore/Providers/Cache/GxMemcached/GxMemcached.csproj index f69db1bbf..ecc9fba40 100644 --- a/dotnet/src/dotnetcore/Providers/Cache/GxMemcached/GxMemcached.csproj +++ b/dotnet/src/dotnetcore/Providers/Cache/GxMemcached/GxMemcached.csproj @@ -15,7 +15,8 @@ - + + diff --git a/dotnet/src/dotnetcore/Providers/Cache/GxRedis/GxRedis.csproj b/dotnet/src/dotnetcore/Providers/Cache/GxRedis/GxRedis.csproj index 9d38c6b46..f6c96079c 100644 --- a/dotnet/src/dotnetcore/Providers/Cache/GxRedis/GxRedis.csproj +++ b/dotnet/src/dotnetcore/Providers/Cache/GxRedis/GxRedis.csproj @@ -24,4 +24,8 @@ + + + + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj index 1bacb83af..47d2c6a5e 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj @@ -8,7 +8,7 @@ - + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj index 543b2cd48..e9956e29f 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj @@ -8,7 +8,7 @@ - + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj index 15a2e62da..251919cc3 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj @@ -8,7 +8,7 @@ - + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/GXEventRouter.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/GXEventRouter.csproj index c2c2ccf43..cdf1f3ab0 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/GXEventRouter.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXEventRouter/GXEventRouter.csproj @@ -7,6 +7,10 @@ TRACE;DEBUG;NETCORE + + + + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/GXMessageBroker.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/GXMessageBroker.csproj index 2cc2f4242..d40bc0234 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/GXMessageBroker.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXMessageBroker/GXMessageBroker.csproj @@ -7,6 +7,11 @@ TRACE;DEBUG;NETCORE + + + + + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/GXQueue.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/GXQueue.csproj index 4779d04dc..bce3bd249 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/GXQueue.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXQueue/GXQueue.csproj @@ -5,7 +5,11 @@ TRACE;DEBUG;NETCORE GeneXus.Message.Queue - + + + + + diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/Diagnostics/GXOtel.Diagnostics/GXOtel.Diagnostics.csproj b/dotnet/src/dotnetcore/Providers/OpenTelemetry/Diagnostics/GXOtel.Diagnostics/GXOtel.Diagnostics.csproj index 8c6a62190..ef080b861 100644 --- a/dotnet/src/dotnetcore/Providers/OpenTelemetry/Diagnostics/GXOtel.Diagnostics/GXOtel.Diagnostics.csproj +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/Diagnostics/GXOtel.Diagnostics/GXOtel.Diagnostics.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/GXMeterProviderBuilder.cs b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/GXMeterProviderBuilder.cs new file mode 100644 index 000000000..0e5630c85 --- /dev/null +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/GXMeterProviderBuilder.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using OpenTelemetry.Metrics; +using OpenTelemetry.Trace; + +namespace GeneXus.OpenTelemetry +{ + public static class GXMeterProviderBuilder + { + public static MeterProviderBuilder AddGxMeterAspNetInstrumentation(this MeterProviderBuilder meter) + { + string envvar = Environment.GetEnvironmentVariable("OTEL_METRICS_EXPORTER"); + meter + .AddAspNetCoreInstrumentation() + .AddHttpClientInstrumentation() + .AddRuntimeInstrumentation() + .AddOtlpExporter(); + if (envvar != null && envvar.Contains("console")) + meter.AddConsoleExporter(); + return meter; + } + + } +} diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/GeneXus.OpenTelemetry.csproj b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/GeneXus.OpenTelemetry.csproj index 9ecede1d6..171a608cd 100644 --- a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/GeneXus.OpenTelemetry.csproj +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/GeneXus.OpenTelemetry.csproj @@ -2,7 +2,6 @@ net6.0;net8.0 - enable GeneXus.OpenTelemetry OpenTelemetry GeneXus DotNet GeneXus.OpenTelemetry.OpenTelemetry @@ -10,11 +9,12 @@ - - - - - + + + + + + diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/GxTraceProviderBuilder.cs b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/GxTraceProviderBuilder.cs index 58da3b8d2..124a86da6 100644 --- a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/GxTraceProviderBuilder.cs +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/GxTraceProviderBuilder.cs @@ -1,3 +1,4 @@ +using System; using GeneXus.Services.OpenTelemetry; using OpenTelemetry.Trace; @@ -19,17 +20,15 @@ public static TracerProviderBuilder AddGxAspNetInstrumentation(this TracerProvid { opt.RecordException = true; }) - .AddAspNetCoreInstrumentation(opt => - { - opt.RecordException = true; - }) .AddSqlClientInstrumentation(opt => { opt.RecordException = true; opt.EnableConnectionLevelAttributes = true; opt.SetDbStatementForText = true; - }) - .AddConsoleExporter(); + }); + string envvar = Environment.GetEnvironmentVariable("OTEL_TRACES_EXPORTER"); + if (envvar != null && envvar.Contains("console")) + tracer.AddConsoleExporter(); return tracer; } } diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/OpenTelemetryProvider.cs b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/OpenTelemetryProvider.cs index 78eaf649e..c3ce730c9 100644 --- a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/OpenTelemetryProvider.cs +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/OpenTelemetryProvider.cs @@ -2,6 +2,8 @@ using GeneXus.Services.OpenTelemetry; using Microsoft.Extensions.DependencyInjection; using OpenTelemetry.Trace; +using OpenTelemetry.Metrics; +using OpenTelemetry.Resources; namespace GeneXus.OpenTelemetry.OpenTelemetry { @@ -19,6 +21,11 @@ public bool InstrumentAspNetCoreApplication(IServiceCollection services) .AddOtlpExporter() .AddGxAspNetInstrumentation(); }); + services.AddOpenTelemetry().WithMetrics(metricsProviderBuilder => + { + metricsProviderBuilder + .AddGxMeterAspNetInstrumentation(); + }); return true; } } diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/AzureAppInsights.cs b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/AzureAppInsights.cs index 98d6c7d1c..96c804a64 100644 --- a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/AzureAppInsights.cs +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/AzureAppInsights.cs @@ -56,6 +56,7 @@ public bool InstrumentAspNetCoreApplication(IServiceCollection _) GXLogging.Debug(log, "Connect to Azure monitor Opentelemetry Metrics exporter using Default Azure credential"); } }) + .AddGxMeterAspNetInstrumentation() .Build(); return true; } diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/GeneXus.OpenTelemetry.Azure.AppInsights.csproj b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/GeneXus.OpenTelemetry.Azure.AppInsights.csproj index 12ae1791b..bda60f087 100644 --- a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/GeneXus.OpenTelemetry.Azure.AppInsights.csproj +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/GeneXus.OpenTelemetry.Azure.AppInsights.csproj @@ -12,12 +12,12 @@ - + - + - - + + diff --git a/dotnet/src/dotnetcore/Providers/Storage/GXAmazonS3/GXAmazonS3.csproj b/dotnet/src/dotnetcore/Providers/Storage/GXAmazonS3/GXAmazonS3.csproj index 2e1e3ce13..ca162324b 100644 --- a/dotnet/src/dotnetcore/Providers/Storage/GXAmazonS3/GXAmazonS3.csproj +++ b/dotnet/src/dotnetcore/Providers/Storage/GXAmazonS3/GXAmazonS3.csproj @@ -13,6 +13,7 @@ + diff --git a/dotnet/src/dotnetcore/Providers/Storage/GXAzureStorage/GXAzureStorage.csproj b/dotnet/src/dotnetcore/Providers/Storage/GXAzureStorage/GXAzureStorage.csproj index 099f6efb1..62f614c32 100644 --- a/dotnet/src/dotnetcore/Providers/Storage/GXAzureStorage/GXAzureStorage.csproj +++ b/dotnet/src/dotnetcore/Providers/Storage/GXAzureStorage/GXAzureStorage.csproj @@ -15,6 +15,7 @@ + diff --git a/dotnet/src/dotnetcore/Providers/Storage/GXGoogleCloud/GXGoogleCloud.csproj b/dotnet/src/dotnetcore/Providers/Storage/GXGoogleCloud/GXGoogleCloud.csproj index 0c3bfd68c..1af8b36e6 100644 --- a/dotnet/src/dotnetcore/Providers/Storage/GXGoogleCloud/GXGoogleCloud.csproj +++ b/dotnet/src/dotnetcore/Providers/Storage/GXGoogleCloud/GXGoogleCloud.csproj @@ -14,6 +14,7 @@ + diff --git a/dotnet/src/dotnetcore/Reor/Reor.csproj b/dotnet/src/dotnetcore/Reor/Reor.csproj index 59e7feedf..7743e4090 100644 --- a/dotnet/src/dotnetcore/Reor/Reor.csproj +++ b/dotnet/src/dotnetcore/Reor/Reor.csproj @@ -16,6 +16,10 @@ + + + + diff --git a/dotnet/src/dotnetframework/GxOffice/GxOffice.csproj b/dotnet/src/dotnetframework/GxOffice/GxOffice.csproj index c80721437..2ae847298 100644 --- a/dotnet/src/dotnetframework/GxOffice/GxOffice.csproj +++ b/dotnet/src/dotnetframework/GxOffice/GxOffice.csproj @@ -9,6 +9,7 @@ + diff --git a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj b/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj index a49099aa5..7a1c905c7 100644 --- a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj +++ b/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj @@ -69,7 +69,7 @@ - + diff --git a/dotnet/src/extensions/Azure/test/AzureFunctionsTest/AzureFunctionsTest.csproj b/dotnet/src/extensions/Azure/test/AzureFunctionsTest/AzureFunctionsTest.csproj index f47c0cc47..6b54739ec 100644 --- a/dotnet/src/extensions/Azure/test/AzureFunctionsTest/AzureFunctionsTest.csproj +++ b/dotnet/src/extensions/Azure/test/AzureFunctionsTest/AzureFunctionsTest.csproj @@ -7,7 +7,7 @@ - + diff --git a/dotnet/src/extensions/Azure/test/GeneXus.Programs.Common/GeneXus.Programs.Common.csproj b/dotnet/src/extensions/Azure/test/GeneXus.Programs.Common/GeneXus.Programs.Common.csproj index f9024993a..35573e5fd 100644 --- a/dotnet/src/extensions/Azure/test/GeneXus.Programs.Common/GeneXus.Programs.Common.csproj +++ b/dotnet/src/extensions/Azure/test/GeneXus.Programs.Common/GeneXus.Programs.Common.csproj @@ -5,6 +5,10 @@ false + + + + diff --git a/dotnet/src/extensions/Azure/test/amyprocedurehandler/amyprochandler.csproj b/dotnet/src/extensions/Azure/test/amyprocedurehandler/amyprochandler.csproj index 9119547f2..e80fca417 100644 --- a/dotnet/src/extensions/Azure/test/amyprocedurehandler/amyprochandler.csproj +++ b/dotnet/src/extensions/Azure/test/amyprocedurehandler/amyprochandler.csproj @@ -11,6 +11,10 @@ + + + + PreserveNewest diff --git a/dotnet/src/extensions/Azure/test/apiattractions/apiattractions.csproj b/dotnet/src/extensions/Azure/test/apiattractions/apiattractions.csproj index 5454ea407..08378cf4a 100644 --- a/dotnet/src/extensions/Azure/test/apiattractions/apiattractions.csproj +++ b/dotnet/src/extensions/Azure/test/apiattractions/apiattractions.csproj @@ -7,6 +7,10 @@ false + + + + diff --git a/dotnet/src/extensions/mocking/src/MockDBAccess/MockDBAccess.csproj b/dotnet/src/extensions/mocking/src/MockDBAccess/MockDBAccess.csproj index 4487458fe..c193f0b38 100644 --- a/dotnet/src/extensions/mocking/src/MockDBAccess/MockDBAccess.csproj +++ b/dotnet/src/extensions/mocking/src/MockDBAccess/MockDBAccess.csproj @@ -6,6 +6,10 @@ 618;1607;1698 + + + + diff --git a/dotnet/test/DotNetCoreAttackMitigationTest/DotNetCoreAttackMitigationTest.csproj b/dotnet/test/DotNetCoreAttackMitigationTest/DotNetCoreAttackMitigationTest.csproj index fa3f01cd2..4821322b2 100644 --- a/dotnet/test/DotNetCoreAttackMitigationTest/DotNetCoreAttackMitigationTest.csproj +++ b/dotnet/test/DotNetCoreAttackMitigationTest/DotNetCoreAttackMitigationTest.csproj @@ -14,6 +14,7 @@ + diff --git a/dotnet/test/DotNetCoreChunkedTest/DotNetCoreChunkedTest.csproj b/dotnet/test/DotNetCoreChunkedTest/DotNetCoreChunkedTest.csproj index 4e4d04086..2ff695e87 100644 --- a/dotnet/test/DotNetCoreChunkedTest/DotNetCoreChunkedTest.csproj +++ b/dotnet/test/DotNetCoreChunkedTest/DotNetCoreChunkedTest.csproj @@ -14,6 +14,7 @@ + diff --git a/dotnet/test/DotNetCoreCmdTest/DotNetCoreCmdTest.csproj b/dotnet/test/DotNetCoreCmdTest/DotNetCoreCmdTest.csproj index 7d3f1be7d..8b376f5fc 100644 --- a/dotnet/test/DotNetCoreCmdTest/DotNetCoreCmdTest.csproj +++ b/dotnet/test/DotNetCoreCmdTest/DotNetCoreCmdTest.csproj @@ -14,6 +14,7 @@ + diff --git a/dotnet/test/DotNetCoreOpenTelemetryTest/DotNetCoreOpenTelemetryTest.csproj b/dotnet/test/DotNetCoreOpenTelemetryTest/DotNetCoreOpenTelemetryTest.csproj index 03f844c27..c38eb7844 100644 --- a/dotnet/test/DotNetCoreOpenTelemetryTest/DotNetCoreOpenTelemetryTest.csproj +++ b/dotnet/test/DotNetCoreOpenTelemetryTest/DotNetCoreOpenTelemetryTest.csproj @@ -14,6 +14,7 @@ + diff --git a/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj b/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj index 8dcbb4c25..266ef7208 100644 --- a/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj +++ b/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj @@ -14,6 +14,7 @@ + diff --git a/dotnet/test/DotNetPdfTest/DotNetPDFUnitTest.csproj b/dotnet/test/DotNetPdfTest/DotNetPDFUnitTest.csproj index 43cbea27f..970f681b1 100644 --- a/dotnet/test/DotNetPdfTest/DotNetPDFUnitTest.csproj +++ b/dotnet/test/DotNetPdfTest/DotNetPDFUnitTest.csproj @@ -18,6 +18,7 @@ + diff --git a/dotnet/test/DotNetRedisTest/DotNetRedisTest.csproj b/dotnet/test/DotNetRedisTest/DotNetRedisTest.csproj index c71055ece..7180cd953 100644 --- a/dotnet/test/DotNetRedisTest/DotNetRedisTest.csproj +++ b/dotnet/test/DotNetRedisTest/DotNetRedisTest.csproj @@ -3,7 +3,7 @@ net6.0;net8.0 - + @@ -15,6 +15,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all + From 146c3208567ae3c115568de29888f4fb2763f3cf Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 16 Jan 2024 10:12:32 -0300 Subject: [PATCH 088/164] Keep low and moderate vulnerabilities as warnings (#933) Treat high and critical vulnerabilities as errors --- dotnet/Directory.Build.props | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dotnet/Directory.Build.props b/dotnet/Directory.Build.props index b1007160e..46c2c8f2a 100644 --- a/dotnet/Directory.Build.props +++ b/dotnet/Directory.Build.props @@ -29,6 +29,8 @@ NU5105;CS0618;CS8032;CS0618;SYSLIB0021;SYSLIB0023 true True + + NU1900;NU1901;NU1902; From 3ca9ef608fd7739912337dad31975ae605ff10ff Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 16 Jan 2024 11:22:47 -0300 Subject: [PATCH 089/164] Rename dfwpnumTest.txt to xmlDfwpnumTest.txt (#932) * Rename dfwpnumTest.txt to xmlDfwpnumTest.txt, considering that the name is already in use by the DfrgFunctions test * Remove unused usings. --- dotnet/test/DotNetUnitTest/Domain/XMLWriterTest.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/dotnet/test/DotNetUnitTest/Domain/XMLWriterTest.cs b/dotnet/test/DotNetUnitTest/Domain/XMLWriterTest.cs index b3e1ce1b0..d428e6764 100644 --- a/dotnet/test/DotNetUnitTest/Domain/XMLWriterTest.cs +++ b/dotnet/test/DotNetUnitTest/Domain/XMLWriterTest.cs @@ -1,9 +1,5 @@ using System; -using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using GeneXus.Application; using GeneXus.XML; using Xunit; @@ -27,7 +23,7 @@ public void dfwpnumEmptyElementWithoutEndTest() internal string dfwpnumTest(string varcharValue, bool closeElements) { GxContext context = new GxContext(); - string fileName = Path.Combine(BaseDir, "dfwpnumTest.txt"); + string fileName = Path.Combine(BaseDir, "xmlDfwpnumTest.txt"); GXXMLWriter GXSoapXMLWriter = new GXXMLWriter(context.GetPhysicalPath()); GXSoapXMLWriter.Open(fileName); GXSoapXMLWriter.WriteStartDocument("utf-8", 0); From 07675defa51510e7405b339227d42ffbca7fb9bc Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 17 Jan 2024 14:03:46 -0300 Subject: [PATCH 090/164] Fix error security transparent issue with method HandleExceptionImp (#934) --- dotnet/src/dotnetframework/GxClasses/Helpers/CsrfHelper.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/CsrfHelper.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/CsrfHelper.cs index 5b9490dbb..6da5f4545 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/CsrfHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/CsrfHelper.cs @@ -12,6 +12,7 @@ namespace GeneXus.Http { internal class CSRFHelper { + [SecuritySafeCritical] internal static bool HandleException(Exception e, HttpContext httpContext) { if (RestAPIHelpers.ValidateCsrfToken()) @@ -20,6 +21,7 @@ internal static bool HandleException(Exception e, HttpContext httpContext) } return false; } + [SecuritySafeCritical] private static bool HandleExceptionImp(Exception e, HttpContext httpContext) { if (e is HttpAntiForgeryException) From 733fe166aeca1d0cd98b2e055c20abe81e1ee4c0 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 17 Jan 2024 18:07:40 -0300 Subject: [PATCH 091/164] Set all vulnerability issues to be treated as warnings. (#944) * Temporarily set all vulnerability issues to be treated as warnings to ensure the build process can proceed * Set all vulnerability issues in tests to be treated as warnings to ensure the build process can proceed --- dotnet/Directory.Build.props | 4 ++-- dotnet/test/Directory.Build.props | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/dotnet/Directory.Build.props b/dotnet/Directory.Build.props index 46c2c8f2a..46a3897d3 100644 --- a/dotnet/Directory.Build.props +++ b/dotnet/Directory.Build.props @@ -29,8 +29,8 @@ NU5105;CS0618;CS8032;CS0618;SYSLIB0021;SYSLIB0023 true True - - NU1900;NU1901;NU1902; + + NU1900;NU1901;NU1902;NU1903;NU1904 diff --git a/dotnet/test/Directory.Build.props b/dotnet/test/Directory.Build.props index 52a699878..b065977e2 100644 --- a/dotnet/test/Directory.Build.props +++ b/dotnet/test/Directory.Build.props @@ -5,5 +5,6 @@ false $(OutputPath) trx + NU1900;NU1901;NU1902;NU1903;NU1904; From cb5abed2a578bce2965ecbdba98301b11c4a5dec Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Thu, 18 Jan 2024 15:48:56 -0300 Subject: [PATCH 092/164] Build will now fail if any error occurs during the NuGet package push. (#945) --- .github/workflows/Build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/Build.yml b/.github/workflows/Build.yml index edfb8415f..f822ba417 100644 --- a/.github/workflows/Build.yml +++ b/.github/workflows/Build.yml @@ -190,14 +190,14 @@ jobs: $PushToAzureArgs += "--skip-duplicate" } - dotnet $PushToAzureArgs + dotnet $PushToAzureArgs || exit 1 $pushedToAzure += 1 if (!$IsPrerelease) { - dotnet $PushToGitHubArgs + dotnet $PushToGitHubArgs || exit 1 $pushedToGitHub += 1 - dotnet $PushToNugetArgs + dotnet $PushToNugetArgs || exit 1 $pushedToNuget += 1 } From 91c6a3cfa080275af57dc0279386ea0366a89eea Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Fri, 19 Jan 2024 14:30:41 -0300 Subject: [PATCH 093/164] Update references to Microsoft.IdentityModel and System.IdentityModel to address vulnerability issues (#931) * Update references to Microsoft.IdentityModel and System.IdentityModel to address vulnerability issues. Bump System.IdentityModel.Tokens.Jwt from 6.8.0 to 6.34.0 Bump Microsoft.IdentityModel.JsonWebTokens from 6.8.0 to 6.34.0 * Upgrade Microsoft.IdentityModel.Tokens from 6.5.1 to 6.34.0 for .NET Framework. --- dotnet/src/dotnetcommon/GxEncrypt/GxEncrypt.csproj | 8 ++------ dotnet/src/dotnetcore/GxClasses/GxClasses.csproj | 4 ++-- dotnet/src/dotnetframework/GxClasses/GxClasses.csproj | 4 ++-- .../dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj | 8 ++++---- .../dotnet/dotnetframework/GeneXusJWT/GeneXusJWT.csproj | 8 ++++---- .../DotNetCoreChunkedTest/DotNetCoreChunkedTest.csproj | 2 +- .../DotNetCoreOpenTelemetryTest.csproj | 2 +- dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj | 2 +- .../DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj | 2 +- 9 files changed, 18 insertions(+), 22 deletions(-) diff --git a/dotnet/src/dotnetcommon/GxEncrypt/GxEncrypt.csproj b/dotnet/src/dotnetcommon/GxEncrypt/GxEncrypt.csproj index 5f7d6885f..f4518c1e4 100644 --- a/dotnet/src/dotnetcommon/GxEncrypt/GxEncrypt.csproj +++ b/dotnet/src/dotnetcommon/GxEncrypt/GxEncrypt.csproj @@ -6,11 +6,7 @@ Encrypt64 Decrypt64 GeneXus.Encrypt - - + + - - - - \ No newline at end of file diff --git a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj index 1805e02db..7efd344ff 100644 --- a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj +++ b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj @@ -173,9 +173,9 @@ - + - + diff --git a/dotnet/src/dotnetframework/GxClasses/GxClasses.csproj b/dotnet/src/dotnetframework/GxClasses/GxClasses.csproj index edf352ed3..3d89f45e6 100644 --- a/dotnet/src/dotnetframework/GxClasses/GxClasses.csproj +++ b/dotnet/src/dotnetframework/GxClasses/GxClasses.csproj @@ -13,11 +13,11 @@ - + - + diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj index 3ffbb4bec..8cebbad16 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj @@ -33,12 +33,12 @@ - - - + + + - + diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusJWT/GeneXusJWT.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusJWT/GeneXusJWT.csproj index 598e1ce0f..8d481a451 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusJWT/GeneXusJWT.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusJWT/GeneXusJWT.csproj @@ -17,11 +17,11 @@ - - - + + + - + diff --git a/dotnet/test/DotNetCoreChunkedTest/DotNetCoreChunkedTest.csproj b/dotnet/test/DotNetCoreChunkedTest/DotNetCoreChunkedTest.csproj index 2ff695e87..6340919c6 100644 --- a/dotnet/test/DotNetCoreChunkedTest/DotNetCoreChunkedTest.csproj +++ b/dotnet/test/DotNetCoreChunkedTest/DotNetCoreChunkedTest.csproj @@ -19,7 +19,7 @@ - + diff --git a/dotnet/test/DotNetCoreOpenTelemetryTest/DotNetCoreOpenTelemetryTest.csproj b/dotnet/test/DotNetCoreOpenTelemetryTest/DotNetCoreOpenTelemetryTest.csproj index c38eb7844..d14b29d86 100644 --- a/dotnet/test/DotNetCoreOpenTelemetryTest/DotNetCoreOpenTelemetryTest.csproj +++ b/dotnet/test/DotNetCoreOpenTelemetryTest/DotNetCoreOpenTelemetryTest.csproj @@ -17,7 +17,7 @@ - + diff --git a/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj b/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj index 4b671a244..29f1c66a3 100644 --- a/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj +++ b/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj @@ -60,7 +60,7 @@ - + diff --git a/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj b/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj index 266ef7208..47a5713c7 100644 --- a/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj +++ b/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj @@ -19,7 +19,7 @@ - + From d04b027327caa18f4e5ff234bdb1f89e5dbebc92 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Mon, 22 Jan 2024 16:31:49 -0300 Subject: [PATCH 094/164] Improve host resolution at FtpService to align with previous behavior. (#948) --- .../dotnetframework/GxClasses/Domain/GxFtp.cs | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxFtp.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxFtp.cs index bf774c728..9fc057b38 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxFtp.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxFtp.cs @@ -8,12 +8,14 @@ using System.Linq; using GeneXus.Encryption; using GeneXus.Configuration; +using log4net; namespace GeneXus.Utils { [SecuritySafeCritical] public class FtpService { + private static readonly ILog log = log4net.LogManager.GetLogger(typeof(FtpService)); private Socket _DataSocket; private Socket _ControlSocket; @@ -511,8 +513,7 @@ private void OpenDataConnection() } _DataSocket = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp ); - IPHostEntry localHostEntry = Dns.GetHostEntry(Dns.GetHostName()); - IPAddress hostAddress = localHostEntry.AddressList.First(a => (a.AddressFamily == _DataSocket.AddressFamily)); ; + IPAddress hostAddress = GetIpAddress(Dns.GetHostName()); IPEndPoint epListener = new IPEndPoint(hostAddress, 0); _DataSocket.Bind(epListener); @@ -565,8 +566,7 @@ private void OpenPassiveDataConnection() { ProcessProtocolViolationError("Error in creating Data Socket"); } - IPHostEntry serverHostEntry = Dns.GetHostEntry(_RequestUri.Host); - IPAddress hostAddress = serverHostEntry.AddressList.First(a => (a.AddressFamily == _DataSocket.AddressFamily)); ; ; + IPAddress hostAddress = GetIpAddress(_RequestUri.Host); IPEndPoint serverEndPoint = new IPEndPoint(hostAddress, Port); try @@ -631,10 +631,8 @@ private void OpenControlConnection(Uri uriToConnect) clientEndPoint = _ControlSocket.LocalEndPoint; try { - IPHostEntry serverHostEntry = Dns.GetHostEntry(Host); - IPAddress ipAddresses = serverHostEntry.AddressList.First(a => (a.AddressFamily == _ControlSocket.AddressFamily)); + IPAddress ipAddresses = GetIpAddress(Host); IPEndPoint serverEndPoint = new IPEndPoint(ipAddresses, Port); - try { if (GXUtil.IsWindowsPlatform) @@ -679,6 +677,21 @@ private void OpenControlConnection(Uri uriToConnect) } } + private IPAddress GetIpAddress(string host) + { + IPHostEntry serverHostEntry = Dns.GetHostEntry(host); + IPAddress ipAddresses = serverHostEntry.AddressList.FirstOrDefault(); + GXLogging.Debug(log, $"GetHostEntry({host}) AddressList length: ", serverHostEntry.AddressList.Length.ToString()); + if (ipAddresses == null) + { + serverHostEntry = Dns.GetHostByName(host); + ipAddresses = serverHostEntry.AddressList.FirstOrDefault(); + GXLogging.Debug(log, $"GetHostByName({host}) AddressList length: ", serverHostEntry.AddressList.Length.ToString()); + } + GXLogging.Debug(log, "HostAddress ", ipAddresses.ToString()); + return ipAddresses; + } + void CloseDataConnection() { if(_DataSocket != null) @@ -976,19 +989,19 @@ internal void ProcessApplicationError( string s) { this._status = 1; this._statusDescription = s; - + GXLogging.Error(log, "ProcessApplicationError " + s); } internal void ProcessApplicationError( string s, Exception e) { this._status = 1; this._statusDescription = s + e.Message; - + GXLogging.Error(log, "ProcessApplicationError " + s, e); } internal void ProcessProtocolViolationError( string s) { this._status = 1; this._statusDescription = new ProtocolViolationException(s).ToString(); - + GXLogging.Warn(log, "ProcessProtocolViolationError ", this._statusDescription); } internal string ComposeExceptionMessage(ResponseDescription resp_desc, string log) { From 39d264ff607cdc0698f0aee9bb38cdc8e5884067 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 24 Jan 2024 11:26:10 -0300 Subject: [PATCH 095/164] The static HttpContext.Current property returns null when the calling-thread is not the same thread that was associated with the current HTTP request/response. (#949) Add a workaround for it when called from objects with UseBigStack enabled. --- dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs index 5cda2adab..d67069d3f 100644 --- a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs +++ b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs @@ -2281,6 +2281,9 @@ protected virtual void sendSpaHeaders() private void webExecuteWorker(object target) { HttpContext httpContext = (HttpContext)target; +#if !NETCORE + HttpContext.Current = httpContext; +#endif try { webExecuteEx(httpContext); From badae4ceda1fdfc8d4fb7aa95d966b9b085aa767 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Mon, 29 Jan 2024 15:00:38 -0300 Subject: [PATCH 096/164] OutputFileDirectory in PDFReport.ini was not considered. (#922) --- .../GxPdfReportsCS/PDFReportCommon.cs | 16 ++++++++-------- .../GxPdfReportsCS/PdfReportInterface.cs | 1 - dotnet/test/DotNetPdfTest/PDFReport.ini | 2 +- dotnet/test/DotNetPdfTest/PDFTests.cs | 12 ++++++------ 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs index a7706e6dd..265d865c1 100644 --- a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs +++ b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs @@ -724,7 +724,7 @@ public void GxSetDocName(String docName) this.docName = docName.Trim(); if(!Path.IsPathRooted(docName)) { - string outputDir = props.getGeneralProperty(Const.OUTPUT_FILE_DIRECTORY, "").Replace(alternateSeparator, Path.DirectorySeparatorChar).Trim(); + string outputDir = props.getGeneralProperty(Const.OUTPUT_FILE_DIRECTORY, string.Empty).Replace(alternateSeparator, Path.DirectorySeparatorChar).Trim(); if(!string.IsNullOrEmpty(outputDir) && outputDir!=".") { try @@ -733,22 +733,22 @@ public void GxSetDocName(String docName) { outputDir += Path.DirectorySeparatorChar; } - string[] dirs = Directory.GetDirectories(outputDir); - foreach (string dir in dirs) - { - Directory.CreateDirectory(dir); - } + Directory.CreateDirectory(outputDir); }catch (Exception ex) { Exception exDetailed = new Exception($"Error creating {Const.OUTPUT_FILE_DIRECTORY} of {Const.INI_FILE} ({outputDir})", ex); GXLogging.Error(log, "GxSetDocName error", exDetailed); throw exDetailed; } - this.docName = outputDir + this.docName; + this.docName = Path.Combine(outputDir, this.docName); } } - if(this.docName.IndexOf('.') < 0) + this.docName = ReportUtils.AddPath(this.docName, defaultRelativePrepend); + + if (string.IsNullOrEmpty(new FileInfo(this.docName).Extension)) + { this.docName += ".pdf"; + } GXLogging.Debug(log,"GxSetDocName: '" + this.docName + "'"); } diff --git a/dotnet/src/dotnetframework/GxPdfReportsCS/PdfReportInterface.cs b/dotnet/src/dotnetframework/GxPdfReportsCS/PdfReportInterface.cs index 642ce03b0..2081bb475 100644 --- a/dotnet/src/dotnetframework/GxPdfReportsCS/PdfReportInterface.cs +++ b/dotnet/src/dotnetframework/GxPdfReportsCS/PdfReportInterface.cs @@ -117,7 +117,6 @@ public virtual void GxRVSetLanguage(string lang) } public virtual void GxSetDocName(string docName) { - docName = ReportUtils.AddPath( docName, _appPath ); _pdfReport.GxSetDocName(docName); } public void GxSetDocFormat(string docFormat) diff --git a/dotnet/test/DotNetPdfTest/PDFReport.ini b/dotnet/test/DotNetPdfTest/PDFReport.ini index 57a516fb5..0f77d4cac 100644 --- a/dotnet/test/DotNetPdfTest/PDFReport.ini +++ b/dotnet/test/DotNetPdfTest/PDFReport.ini @@ -14,7 +14,7 @@ LongDashedStyle= 6;2 EmbeedNotSpecifiedFonts= false Barcode128AsImage= true MarginsInsideBorder= false -OutputFileDirectory= . +OutputFileDirectory= .\temp\ LineCapProjectingSquare= true DottedStyle= 1;2 JustifiedTypeAll= false diff --git a/dotnet/test/DotNetPdfTest/PDFTests.cs b/dotnet/test/DotNetPdfTest/PDFTests.cs index 8996fb004..7e17ac513 100644 --- a/dotnet/test/DotNetPdfTest/PDFTests.cs +++ b/dotnet/test/DotNetPdfTest/PDFTests.cs @@ -1,8 +1,6 @@ using System; using System.IO; -using GeneXus.Configuration; using GeneXus.Programs; -using GeneXus.Utils; using Xunit; namespace UnitTesting @@ -13,13 +11,15 @@ public class PDFTests public void TestITextFormat() { string report = "PDFFormat.pdf"; - if (File.Exists(report)) - File.Delete(report); + string outputFileDirectory = @".\temp\"; + + string reportFullPath = Path.Combine(Directory.GetCurrentDirectory(), outputFileDirectory, report); + if (File.Exists(reportFullPath)) + File.Delete(reportFullPath); try { apdfformats2 test = new apdfformats2(); test.execute(); - longHtml test2 = new longHtml(); test2.execute(); } @@ -29,7 +29,7 @@ public void TestITextFormat() { Console.WriteLine(ex.ToString()); } - Assert.True(File.Exists(report)); + Assert.True(File.Exists(reportFullPath)); } } } From df1fa07a04b633df99ccd1693457fecf785d0d65 Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Tue, 30 Jan 2024 10:12:26 -0300 Subject: [PATCH 097/164] Avoid generating Otel Traces and metrics through Env Var (#952) --- .../OpenTelemetry/OpenTelemetryProvider.cs | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/OpenTelemetryProvider.cs b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/OpenTelemetryProvider.cs index c3ce730c9..c7c237dcf 100644 --- a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/OpenTelemetryProvider.cs +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/OpenTelemetryProvider.cs @@ -4,28 +4,39 @@ using OpenTelemetry.Trace; using OpenTelemetry.Metrics; using OpenTelemetry.Resources; +using System; +using Microsoft.IdentityModel.Tokens; namespace GeneXus.OpenTelemetry.OpenTelemetry { public class OpenTelemetryProvider : IOpenTelemetryProvider { + const string OTEL_METRICS_EXPORTER = "OTEL_METRICS_EXPORTER"; + const string OTEL_TRACES_EXPORTER = "OTEL_TRACES_EXPORTER"; public OpenTelemetryProvider(GXService s) { } public bool InstrumentAspNetCoreApplication(IServiceCollection services) { - services.AddOpenTelemetry().WithTracing(tracerProviderBuilder => - { - tracerProviderBuilder - .AddOtlpExporter() - .AddGxAspNetInstrumentation(); - }); - services.AddOpenTelemetry().WithMetrics(metricsProviderBuilder => - { - metricsProviderBuilder - .AddGxMeterAspNetInstrumentation(); - }); + string envvar = Environment.GetEnvironmentVariable(OTEL_TRACES_EXPORTER); + if (envvar.IsNullOrEmpty() || !envvar.ToLower().Equals("none")) { + services.AddOpenTelemetry().WithTracing(tracerProviderBuilder => + { + tracerProviderBuilder + .AddOtlpExporter() + .AddGxAspNetInstrumentation(); + }); + } + + envvar = Environment.GetEnvironmentVariable(OTEL_METRICS_EXPORTER); + if (envvar.IsNullOrEmpty() || !envvar.ToLower().Equals("none")) { + services.AddOpenTelemetry().WithMetrics(metricsProviderBuilder => + { + metricsProviderBuilder + .AddGxMeterAspNetInstrumentation(); + }); + } return true; } } From afc3d1e19eb459f64e48d2dd5a9adf9eaa34f574 Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Tue, 30 Jan 2024 10:12:52 -0300 Subject: [PATCH 098/164] Add Logs for Opentelemetry (#951) --- .../Services/LogService/GXLogService.cs | 23 +++++-- .../OtelLogProvider.cs} | 64 +++++++++++++------ .../GxClasses/Diagnostics/Log.cs | 12 ++-- 3 files changed, 71 insertions(+), 28 deletions(-) rename dotnet/src/dotnetcore/GxClasses/Services/LogService/{AzureAppInsights/AzureAppInsightsLogProvider.cs => OpenTelemetry/OtelLogProvider.cs} (65%) diff --git a/dotnet/src/dotnetcore/GxClasses/Services/LogService/GXLogService.cs b/dotnet/src/dotnetcore/GxClasses/Services/LogService/GXLogService.cs index cc455dbdc..a015eca6d 100644 --- a/dotnet/src/dotnetcore/GxClasses/Services/LogService/GXLogService.cs +++ b/dotnet/src/dotnetcore/GxClasses/Services/LogService/GXLogService.cs @@ -1,3 +1,4 @@ +using System; using GeneXus.Configuration; using Microsoft.Extensions.Logging; @@ -7,15 +8,25 @@ public static class GXLogService { private static string AZURE_APPLICATION_INSIGHTS_LOG = "AZUREAPPLICATIONINSIGHTS"; const string OTEL_AZUREMONITOR_EXPORTER = "OTEL_AZUREMONITOR_EXPORTER"; + const string OPENTELEMETRY = "OPENTELEMETRY"; + internal static string OTEL_LOGS_EXPORTER = "OTEL_LOGS_EXPORTER"; const string LOG_OUTPUT = "LOG_OUTPUT"; + public static ILoggerFactory GetLogFactory() { - if (Config.GetValueOf(LOG_OUTPUT, out string logProvider)) - { - if (logProvider == OTEL_AZUREMONITOR_EXPORTER) - return AzureAppInsightsLogProvider.GetAzureMonitorLoggerFactory(); - else if (logProvider == AZURE_APPLICATION_INSIGHTS_LOG) - return AzureAppInsightsLogProvider.GetLoggerFactory(); + string otelLogEnvVar = Environment.GetEnvironmentVariable(OTEL_LOGS_EXPORTER); + if (string.IsNullOrEmpty(otelLogEnvVar) || !otelLogEnvVar.ToLower().Equals("none")) + { + if (Config.GetValueOf(LOG_OUTPUT, out string logProvider)) + { + if (logProvider == OTEL_AZUREMONITOR_EXPORTER) + return OpentelemetryLogProvider.GetAzureMonitorLoggerFactory(); + else if (logProvider == AZURE_APPLICATION_INSIGHTS_LOG) + return OpentelemetryLogProvider.GetAzureAppInsightsLoggerFactory(); + else + if (logProvider == OPENTELEMETRY) + return OpentelemetryLogProvider.GetOpentelemetryLoggerFactory(); + } } return null; } diff --git a/dotnet/src/dotnetcore/GxClasses/Services/LogService/AzureAppInsights/AzureAppInsightsLogProvider.cs b/dotnet/src/dotnetcore/GxClasses/Services/LogService/OpenTelemetry/OtelLogProvider.cs similarity index 65% rename from dotnet/src/dotnetcore/GxClasses/Services/LogService/AzureAppInsights/AzureAppInsightsLogProvider.cs rename to dotnet/src/dotnetcore/GxClasses/Services/LogService/OpenTelemetry/OtelLogProvider.cs index 8a1e4318c..21bb3d8f3 100644 --- a/dotnet/src/dotnetcore/GxClasses/Services/LogService/AzureAppInsights/AzureAppInsightsLogProvider.cs +++ b/dotnet/src/dotnetcore/GxClasses/Services/LogService/OpenTelemetry/OtelLogProvider.cs @@ -1,11 +1,14 @@ using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; using Azure.Monitor.OpenTelemetry.Exporter; using Microsoft.Extensions.Logging; using OpenTelemetry.Logs; +using OpenTelemetry.Resources; namespace GeneXus.Services.Log { - public class AzureAppInsightsLogProvider : ILoggerFactory + public class OpentelemetryLogProvider : ILoggerFactory { private static string APPLICATIONINSIGHTS_CONNECTION_STRING = "APPLICATIONINSIGHTS_CONNECTION_STRING"; private const string LOG_LEVEL_ENVVAR = "GX_LOG_LEVEL"; @@ -25,7 +28,8 @@ public static ILoggerFactory GetAzureMonitorLoggerFactory() builder.AddOpenTelemetry(options => { options.AddAzureMonitorLogExporter(o => o.ConnectionString = appInsightsConnection); - options.AddConsoleExporter(); + if (GenerateOtelLogsToConsole()) + options.AddConsoleExporter(); }).SetMinimumLevel(loglevel); }); } @@ -42,7 +46,7 @@ public static ILoggerFactory GetAzureMonitorLoggerFactory() return loggerFactory; } - public static ILoggerFactory GetLoggerFactory() + public static ILoggerFactory GetAzureAppInsightsLoggerFactory() { string appInsightsConnection = Environment.GetEnvironmentVariable(APPLICATIONINSIGHTS_CONNECTION_STRING); try @@ -71,6 +75,23 @@ public static ILoggerFactory GetLoggerFactory() return loggerFactory; } + + public static ILoggerFactory GetOpentelemetryLoggerFactory() + { + LogLevel loglevel = GetLogLevel(); + loggerFactory = LoggerFactory.Create(builder => builder.AddOpenTelemetry(logging => + { + var resourceBuilder = ResourceBuilder.CreateDefault() + .AddTelemetrySdk(); + + logging.SetResourceBuilder(resourceBuilder); + if (GenerateOtelLogsToConsole()) + logging.AddConsoleExporter(); + + }) + .SetMinimumLevel(loglevel)); + return loggerFactory; + } private static LogLevel GetLogLevel() { string loglevelvalue = Environment.GetEnvironmentVariable(LOG_LEVEL_ENVVAR); @@ -79,7 +100,7 @@ private static LogLevel GetLogLevel() { if (!Enum.TryParse(loglevelvalue, out loglevel)) { - CustomLogLevel customLogLevel = CustomLogLevel.Info; + CustomLogLevel customLogLevel = CustomLogLevel.info; if (Enum.TryParse(loglevelvalue, out customLogLevel)) { loglevel = toLogLevel(customLogLevel); @@ -91,6 +112,13 @@ private static LogLevel GetLogLevel() return loglevel; } + private static bool GenerateOtelLogsToConsole() + { + string otelLogsEnvVar = Environment.GetEnvironmentVariable(GXLogService.OTEL_LOGS_EXPORTER); + if (string.IsNullOrEmpty(otelLogsEnvVar)) { return false; } + return otelLogsEnvVar.ToLower().Contains("console") || otelLogsEnvVar.ToLower().Contains("logging"); + } + public void AddProvider(ILoggerProvider provider) { loggerFactory.AddProvider(provider); @@ -105,25 +133,25 @@ public ILogger CreateLogger(string name) } private enum CustomLogLevel { - None, - All, - Debug, - Info, - Warn, - Error, - Fatal + none, + all, + debug, + info, + warn, + error, + fatal } private static LogLevel toLogLevel(CustomLogLevel customLogLevel) { switch (customLogLevel) { - case CustomLogLevel.None: return LogLevel.None; - case CustomLogLevel.All: return LogLevel.Trace; - case CustomLogLevel.Debug: return LogLevel.Debug; - case CustomLogLevel.Info: return LogLevel.Information; - case CustomLogLevel.Warn: return LogLevel.Warning; - case CustomLogLevel.Error: return LogLevel.Error; - case CustomLogLevel.Fatal: return LogLevel.Critical; + case CustomLogLevel.none: return LogLevel.None; + case CustomLogLevel.all: return LogLevel.Trace; + case CustomLogLevel.debug: return LogLevel.Debug; + case CustomLogLevel.info: return LogLevel.Information; + case CustomLogLevel.warn: return LogLevel.Warning; + case CustomLogLevel.error: return LogLevel.Error; + case CustomLogLevel.fatal: return LogLevel.Critical; default: return LogLevel.Information; } } diff --git a/dotnet/src/dotnetframework/GxClasses/Diagnostics/Log.cs b/dotnet/src/dotnetframework/GxClasses/Diagnostics/Log.cs index 96b430062..078672fcc 100644 --- a/dotnet/src/dotnetframework/GxClasses/Diagnostics/Log.cs +++ b/dotnet/src/dotnetframework/GxClasses/Diagnostics/Log.cs @@ -3,6 +3,7 @@ using log4net; using System.Collections.Concurrent; + #if NETCORE using GeneXus.Services.Log; using Microsoft.Extensions.Logging; @@ -25,10 +26,8 @@ private enum LogLevel } private const string LoggerPrefix = "$"; - private static readonly string DefaultRepository = LogManager.GetRepository().Name; private static readonly string DefaultUserLogNamespace = Config.GetValueOf("USER_LOG_NAMESPACE", LogConfiguration.USER_LOG_TOPIC); - private static readonly IGXLogger GlobalLog = new GXLoggerLog4Net(LogManager.GetLogger(DefaultRepository, DefaultUserLogNamespace)); - private static ConcurrentDictionary LoggerDictionary = new ConcurrentDictionary() { [string.Empty] = GlobalLog }; + private static ConcurrentDictionary LoggerDictionary = new ConcurrentDictionary() {}; internal static IGXLogger GetLogger(string topic) { if (LoggerDictionary.TryGetValue(topic, out IGXLogger logger)) @@ -37,7 +36,12 @@ internal static IGXLogger GetLogger(string topic) } else { - string loggerName = topic.StartsWith(LoggerPrefix) ? topic.Substring(1) : $"{DefaultUserLogNamespace}.{topic.Trim()}"; + string loggerName; + if (!string.IsNullOrEmpty(topic)) + loggerName = topic.StartsWith(LoggerPrefix) ? topic.Substring(1) : $"{DefaultUserLogNamespace}.{topic.Trim()}"; + else + loggerName = DefaultUserLogNamespace; + logger = GXLoggerFactory.GetLogger(loggerName); LoggerDictionary.TryAdd(topic, logger); return logger; From 7968b35e8b1a6a10c96b95a48d24a006a4fea053 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 30 Jan 2024 10:19:18 -0300 Subject: [PATCH 099/164] The key length is increased from 16 to 32 bits. (#954) --- .../GxClasses/Security/WebSecurity.cs | 2 +- .../DotNetUnitTest/Crypto/SignatureTest.cs | 22 +++++++++++++++++++ .../test/DotNetUnitTest/DotNetUnitTest.csproj | 3 +++ dotnet/test/DotNetUnitTest/application.key | 2 ++ dotnet/test/DotNetUnitTest/client.exe.config | 7 +++--- 5 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 dotnet/test/DotNetUnitTest/Crypto/SignatureTest.cs create mode 100644 dotnet/test/DotNetUnitTest/application.key diff --git a/dotnet/src/dotnetframework/GxClasses/Security/WebSecurity.cs b/dotnet/src/dotnetframework/GxClasses/Security/WebSecurity.cs index 79c37b6de..89c24b083 100644 --- a/dotnet/src/dotnetframework/GxClasses/Security/WebSecurity.cs +++ b/dotnet/src/dotnetframework/GxClasses/Security/WebSecurity.cs @@ -18,7 +18,7 @@ public static class WebSecurityHelper { static readonly IGXLogger _log = GXLoggerFactory.GetLogger(typeof(WebSecurityHelper).FullName); - const int SecretKeyMinimumLength = 16; + const int SecretKeyMinimumLength = 32; public static string StripInvalidChars(string input) { diff --git a/dotnet/test/DotNetUnitTest/Crypto/SignatureTest.cs b/dotnet/test/DotNetUnitTest/Crypto/SignatureTest.cs new file mode 100644 index 000000000..c84ba792b --- /dev/null +++ b/dotnet/test/DotNetUnitTest/Crypto/SignatureTest.cs @@ -0,0 +1,22 @@ +using System; +using System.Diagnostics; +using System.Web.Configuration; +using GeneXus.Application; +using GeneXus.Utils; +using GeneXus.Web.Security; +using Xunit; + +namespace UnitTesting +{ + public class SignatureTest + { + [Fact] + public void SignSecurityToken() + { + GxContext context = new GxContext(); + string signed = WebSecurityHelper.Sign("WFPROTOTYPER", string.Empty, "Customer.CustomerRegistration", SecureTokenHelper.SecurityMode.Sign, context); + Assert.NotEmpty(signed); + + } + } +} diff --git a/dotnet/test/DotNetUnitTest/DotNetUnitTest.csproj b/dotnet/test/DotNetUnitTest/DotNetUnitTest.csproj index 76f536242..a38f9452e 100644 --- a/dotnet/test/DotNetUnitTest/DotNetUnitTest.csproj +++ b/dotnet/test/DotNetUnitTest/DotNetUnitTest.csproj @@ -70,6 +70,9 @@ + + PreserveNewest + PreserveNewest diff --git a/dotnet/test/DotNetUnitTest/application.key b/dotnet/test/DotNetUnitTest/application.key new file mode 100644 index 000000000..5f6a84812 --- /dev/null +++ b/dotnet/test/DotNetUnitTest/application.key @@ -0,0 +1,2 @@ +7E2E22D26FF2989E2444852A85E57867 +7E2E22D26FF2989E2444852A85E57867 \ No newline at end of file diff --git a/dotnet/test/DotNetUnitTest/client.exe.config b/dotnet/test/DotNetUnitTest/client.exe.config index 0351277f5..bbccba89c 100644 --- a/dotnet/test/DotNetUnitTest/client.exe.config +++ b/dotnet/test/DotNetUnitTest/client.exe.config @@ -90,9 +90,10 @@ - - - + + + + From a75f21a2b28e803cd1e63405d0a1eac57b376f3f Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Fri, 2 Feb 2024 10:44:37 -0300 Subject: [PATCH 100/164] Fix error "System.ArgumentException: Illegal characters in path" when adding an image from URL to report. (#947) Path.IsPathRooted validates the path for valid charactersPath (only in .NET Framework) --- .../dotnetframework/GxClasses/Printer/GxPrinter.cs | 12 +++++++++++- dotnet/test/DotNetUnitTest/FileIO/FileIOTests.cs | 10 ++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Printer/GxPrinter.cs b/dotnet/src/dotnetframework/GxClasses/Printer/GxPrinter.cs index e47f48096..8c3044799 100644 --- a/dotnet/src/dotnetframework/GxClasses/Printer/GxPrinter.cs +++ b/dotnet/src/dotnetframework/GxClasses/Printer/GxPrinter.cs @@ -16,6 +16,7 @@ namespace GeneXus.Printer using System.Threading; using System.Threading.Tasks; using GeneXus.Configuration; + using GeneXus.Utils; using GeneXus.XML; public interface IPrintHandler @@ -2162,10 +2163,19 @@ public class ReportUtils { static public string AddPath(string name, string path) { - if (Path.IsPathRooted(name) || name.IndexOf(":") != -1 || + if (name.IndexOf(":") != -1 || (name.Length >=2 && (name.Substring( 0,2) == "//" || name.Substring( 0,2) == @"\\")) || (name.StartsWith("http:" ) || name.StartsWith("https:" ))) return name; +#if NETCORE + if (Path.IsPathRooted (name)) + return name; +#else + if (PathUtil.IsValidFilePath(name) && Path.IsPathRooted(name)) + { + return name; + } +#endif return Path.Combine(path, name); } } diff --git a/dotnet/test/DotNetUnitTest/FileIO/FileIOTests.cs b/dotnet/test/DotNetUnitTest/FileIO/FileIOTests.cs index 28decb1d7..91d2f9c8e 100644 --- a/dotnet/test/DotNetUnitTest/FileIO/FileIOTests.cs +++ b/dotnet/test/DotNetUnitTest/FileIO/FileIOTests.cs @@ -117,5 +117,15 @@ public void ReportUtilAddPathHttp() string fullPath = ReportUtils.AddPath(name, path); Assert.Equal(name, fullPath); } + [Fact] + public void ReportUtilAddPathWithIllegalCharacters() + { + string name = "https://chart.googleapis.com/chart?chs=400x400&cht=qr&chl=http://sistemas.gov/nfceweb/consultarNFCe.jsp?p=13231205514674000128650020009504049878593990|2|1|09|1337.07|4558626967746769617A304E4B7A6D34504B4E61524A474F4D32513D|1|14D0A30916C6C7EA709E7E33E330EE3F290FE25D"; + string path = "C:/Models/Report/NETModel/Web/"; + string fullPath = ReportUtils.AddPath(name, path); + + Assert.Equal(name, fullPath); + } + } } From 9f796439fa4791bbcd0c89f401b9ebd5786747f5 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 6 Feb 2024 15:45:43 -0300 Subject: [PATCH 101/164] Upgrade Microsoft.Data.SqlClient from 2.1.2 to 2.1.7 due to vulnerability issue. (#946) --- dotnet/src/dotnetcore/GxClasses/GxClasses.csproj | 2 +- dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj | 2 +- .../Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj | 2 +- .../mocking/test/TestMockDBAccess/TestMockDBAccess.csproj | 2 +- dotnet/test/DotNetCoreChunkedTest/DotNetCoreChunkedTest.csproj | 2 +- .../DotNetCoreOpenTelemetryTest.csproj | 2 +- dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj | 2 +- dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj index 7efd344ff..3c17e8211 100644 --- a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj +++ b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj @@ -151,7 +151,7 @@ - + all diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj b/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj index 42af849da..4a770c6bc 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj @@ -12,7 +12,7 @@ - + diff --git a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj b/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj index 7a1c905c7..485379f5f 100644 --- a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj +++ b/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj @@ -72,7 +72,7 @@ - + diff --git a/dotnet/src/extensions/mocking/test/TestMockDBAccess/TestMockDBAccess.csproj b/dotnet/src/extensions/mocking/test/TestMockDBAccess/TestMockDBAccess.csproj index 94877d3c3..60c55c99a 100644 --- a/dotnet/src/extensions/mocking/test/TestMockDBAccess/TestMockDBAccess.csproj +++ b/dotnet/src/extensions/mocking/test/TestMockDBAccess/TestMockDBAccess.csproj @@ -10,7 +10,7 @@ - + diff --git a/dotnet/test/DotNetCoreChunkedTest/DotNetCoreChunkedTest.csproj b/dotnet/test/DotNetCoreChunkedTest/DotNetCoreChunkedTest.csproj index 6340919c6..09b55c7b9 100644 --- a/dotnet/test/DotNetCoreChunkedTest/DotNetCoreChunkedTest.csproj +++ b/dotnet/test/DotNetCoreChunkedTest/DotNetCoreChunkedTest.csproj @@ -18,7 +18,7 @@ - + diff --git a/dotnet/test/DotNetCoreOpenTelemetryTest/DotNetCoreOpenTelemetryTest.csproj b/dotnet/test/DotNetCoreOpenTelemetryTest/DotNetCoreOpenTelemetryTest.csproj index d14b29d86..6b8ae9e00 100644 --- a/dotnet/test/DotNetCoreOpenTelemetryTest/DotNetCoreOpenTelemetryTest.csproj +++ b/dotnet/test/DotNetCoreOpenTelemetryTest/DotNetCoreOpenTelemetryTest.csproj @@ -16,7 +16,7 @@ - + diff --git a/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj b/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj index 29f1c66a3..fd445e3c2 100644 --- a/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj +++ b/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj @@ -59,7 +59,7 @@ - + diff --git a/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj b/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj index 47a5713c7..789e4b132 100644 --- a/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj +++ b/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj @@ -18,7 +18,7 @@ - + From d4d36283f8ce595c738ec8b19598912467a19e9d Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 7 Feb 2024 23:06:45 -0300 Subject: [PATCH 102/164] Bump version to 1.29 after creating branch for v18u8 --- dotnet/Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/Directory.Build.props b/dotnet/Directory.Build.props index 46a3897d3..8c49dd095 100644 --- a/dotnet/Directory.Build.props +++ b/dotnet/Directory.Build.props @@ -3,7 +3,7 @@ 11.0.0.0 1 $([MSBuild]::Add($(MajorFileVersion), 100)) - 28 + 29 $(COMMIT_NUMBER) 0 $(MajorFileVersion).$(MinorFileVersion).$(PatchFileVersion) From abb78b74f2586fb551f71b57054b32c465cce130 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Thu, 8 Feb 2024 09:00:34 -0300 Subject: [PATCH 103/164] GeneXus.Deploy.AzureFunctions.Handlers.runtimeconfig.json was duplicated in package. (#957) --- .../Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj b/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj index 485379f5f..c73042c0c 100644 --- a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj +++ b/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj @@ -101,7 +101,7 @@ - + ./lib/$(TargetFramework)/ true From b4fac7db98821b5c3bf65bb8cdbaf39f93e15862 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Thu, 8 Feb 2024 11:22:42 -0300 Subject: [PATCH 104/164] Mark MockDBAccess.csproj as not packable. (#958) --- .../src/extensions/mocking/src/MockDBAccess/MockDBAccess.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/dotnet/src/extensions/mocking/src/MockDBAccess/MockDBAccess.csproj b/dotnet/src/extensions/mocking/src/MockDBAccess/MockDBAccess.csproj index c193f0b38..631daf306 100644 --- a/dotnet/src/extensions/mocking/src/MockDBAccess/MockDBAccess.csproj +++ b/dotnet/src/extensions/mocking/src/MockDBAccess/MockDBAccess.csproj @@ -4,6 +4,7 @@ net6.0;net462 net462 618;1607;1698 + false From 37385be4c9af056eab7f02adfa03915efc9eab8a Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Mon, 12 Feb 2024 14:49:50 -0300 Subject: [PATCH 105/164] Json options optimization in .NET (#959) * Performance optimization for ajax communication: Reuse JSONoptions defined for ReadJSON and SerializeToJayrockCompatibleJson. * Fix mistake in converter added to DeserializationOptions * Force build. --- .../GxClasses/Helpers/JSONHelper.cs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/JSONHelper.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/JSONHelper.cs index 846101bf8..aa22bc428 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/JSONHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/JSONHelper.cs @@ -56,7 +56,6 @@ public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonS } } } - public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options) { throw new NotImplementedException(); @@ -91,12 +90,10 @@ internal override bool IsJsonNull(object jobject) { return jobject == null; } + static JsonSerializerOptions DeserializationOptions = new JsonSerializerOptions() { Converters = { new GxJsonConverter() }, AllowTrailingCommas=true }; internal override T ReadJSON(string json) { - JsonSerializerOptions opts = new JsonSerializerOptions(); - opts.Converters.Add(new GxJsonConverter()); - opts.AllowTrailingCommas = true; - return JsonSerializer.Deserialize(json, opts); + return JsonSerializer.Deserialize(json, DeserializationOptions); } internal override string WriteJSON(T kbObject) { @@ -106,13 +103,13 @@ internal override string WriteJSON(T kbObject) } return null; } + static JsonSerializerOptions JayrockCompatibleOptions = new JsonSerializerOptions() { + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, + Converters = { new CustomDateTimeConverter() }, + NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals }; internal static string SerializeToJayrockCompatibleJson(T value) where T : IJayrockCompatible { - JsonSerializerOptions opts = new JsonSerializerOptions(); - opts.Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping; - opts.Converters.Add(new CustomDateTimeConverter()); - opts.NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals; - return JsonSerializer.Serialize(value, opts); + return JsonSerializer.Serialize(value, JayrockCompatibleOptions); } } #else From b80cf49cb7a8eb3486d7795066dde95774927951 Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Wed, 14 Feb 2024 19:43:19 -0300 Subject: [PATCH 106/164] Add missing export to OTL exporter for Opentelemetry logging (#963) --- dotnet/src/dotnetcore/GxClasses/GxClasses.csproj | 1 + .../Services/LogService/OpenTelemetry/OtelLogProvider.cs | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj index 3c17e8211..37eb56d95 100644 --- a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj +++ b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj @@ -161,6 +161,7 @@ + diff --git a/dotnet/src/dotnetcore/GxClasses/Services/LogService/OpenTelemetry/OtelLogProvider.cs b/dotnet/src/dotnetcore/GxClasses/Services/LogService/OpenTelemetry/OtelLogProvider.cs index 21bb3d8f3..20fef179b 100644 --- a/dotnet/src/dotnetcore/GxClasses/Services/LogService/OpenTelemetry/OtelLogProvider.cs +++ b/dotnet/src/dotnetcore/GxClasses/Services/LogService/OpenTelemetry/OtelLogProvider.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.Logging; using OpenTelemetry.Logs; using OpenTelemetry.Resources; +using OpenTelemetry.Exporter; namespace GeneXus.Services.Log { @@ -84,7 +85,9 @@ public static ILoggerFactory GetOpentelemetryLoggerFactory() var resourceBuilder = ResourceBuilder.CreateDefault() .AddTelemetrySdk(); - logging.SetResourceBuilder(resourceBuilder); + logging.SetResourceBuilder(resourceBuilder) + .AddOtlpExporter(); + if (GenerateOtelLogsToConsole()) logging.AddConsoleExporter(); From 8e4727eec41b33c72e0ec3fb91b81010660844e8 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Mon, 19 Feb 2024 10:15:45 -0300 Subject: [PATCH 107/164] Remove unused package reference Microsoft.Data.SqlClient (#964) --- .../Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj b/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj index c73042c0c..1903997a9 100644 --- a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj +++ b/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj @@ -72,7 +72,6 @@ - From 6cc29e1d7364f98e5888ef66354e37c073e3bd28 Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Mon, 26 Feb 2024 13:13:51 -0300 Subject: [PATCH 108/164] Enable metrics for AWSOtel Provider (#961) --- .../OpenTelemetryAWSOtel/AWSOtelProvider.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAWSOtel/AWSOtelProvider.cs b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAWSOtel/AWSOtelProvider.cs index 2aae5321f..7de8b29f1 100644 --- a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAWSOtel/AWSOtelProvider.cs +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAWSOtel/AWSOtelProvider.cs @@ -1,12 +1,11 @@ using System; +using GeneXus.Services; using GeneXus.Services.OpenTelemetry; using Microsoft.Extensions.DependencyInjection; using OpenTelemetry; -using OpenTelemetry.Trace; using OpenTelemetry.Contrib.Extensions.AWSXRay.Trace; -using GeneXus.Services; -using GeneXus.Services.Common; -using GeneXus.Diagnostics; +using OpenTelemetry.Metrics; +using OpenTelemetry.Trace; namespace GeneXus.OpenTelemetry.AWS { @@ -33,6 +32,10 @@ public bool InstrumentAspNetCoreApplication(IServiceCollection _) .AddGxAspNetInstrumentation() .Build(); + Sdk.CreateMeterProviderBuilder() + .AddGxMeterAspNetInstrumentation() + .Build(); + Sdk.SetDefaultTextMapPropagator(new AWSXRayPropagator()); return true; From 47e6c87ae3bda4b51bb9f9a8f5a6b09a6af78104 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 27 Feb 2024 10:20:21 -0300 Subject: [PATCH 109/164] Unit test for Forwarded Headers Middleware (#967) * Enabled Forwarded Headers Middleware. * Consider the scheme in the unit test. * Remove Forward headers Middleware as it is enabled by default when ASPNETCORE_FORWARDEDHEADERS_ENABLED environment variable is true. --- .../dotnetcore/GxNetCoreStartup/Startup.cs | 1 + .../DotNetCoreWebUnitTest.csproj | 3 + .../Middleware/HeadersTest.cs | 40 +++++++++++++ .../DotNetCoreWebUnitTest/apps/httpheaders.cs | 57 +++++++++++++++++++ .../apps/httpheaders.svc | 1 + 5 files changed, 102 insertions(+) create mode 100644 dotnet/test/DotNetCoreWebUnitTest/Middleware/HeadersTest.cs create mode 100644 dotnet/test/DotNetCoreWebUnitTest/apps/httpheaders.cs create mode 100644 dotnet/test/DotNetCoreWebUnitTest/apps/httpheaders.svc diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs index e86d3bf46..c6bcff2d0 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs @@ -18,6 +18,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; +using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Rewrite; using Microsoft.AspNetCore.Routing; diff --git a/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj b/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj index 789e4b132..61a57b2f2 100644 --- a/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj +++ b/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj @@ -59,6 +59,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/dotnet/test/DotNetCoreWebUnitTest/Middleware/HeadersTest.cs b/dotnet/test/DotNetCoreWebUnitTest/Middleware/HeadersTest.cs new file mode 100644 index 000000000..cc26e10e5 --- /dev/null +++ b/dotnet/test/DotNetCoreWebUnitTest/Middleware/HeadersTest.cs @@ -0,0 +1,40 @@ +using System; +using System.Net.Http; +using System.Reflection; +using System.Threading.Tasks; +using GeneXus.Metadata; +using Xunit; +namespace xUnitTesting +{ + public class HeadersTest : MiddlewareTest + { + public HeadersTest() : base() + { + ClassLoader.FindType("apps.httpheaders", "GeneXus.Programs.apps", "httpheaders", Assembly.GetExecutingAssembly(), true);//Force loading assembly for append procedure + server.AllowSynchronousIO = true; + + } + protected override void SetEnvironmentVars() + { + Environment.SetEnvironmentVariable("ASPNETCORE_FORWARDEDHEADERS_ENABLED", "true", EnvironmentVariableTarget.Process); + + } + [Fact] + public async Task TestForwardedHeaders() + { + const string host = "192.168.1.100"; + const string scheme = "https"; + const string remoteUrl = $"{scheme}:\\/\\/{host}"; + HttpClient client = server.CreateClient(); + client.DefaultRequestHeaders.Add("X-Forwarded-For", host); + client.DefaultRequestHeaders.Add("X-Forwarded-Proto", scheme); + + HttpResponseMessage response = await client.GetAsync("/rest/apps/httpheaders"); + response.EnsureSuccessStatusCode(); + string resp = await response.Content.ReadAsStringAsync(); + Assert.Contains(remoteUrl, resp, System.StringComparison.OrdinalIgnoreCase); + Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); + } + + } +} \ No newline at end of file diff --git a/dotnet/test/DotNetCoreWebUnitTest/apps/httpheaders.cs b/dotnet/test/DotNetCoreWebUnitTest/apps/httpheaders.cs new file mode 100644 index 000000000..5e8a8fef4 --- /dev/null +++ b/dotnet/test/DotNetCoreWebUnitTest/apps/httpheaders.cs @@ -0,0 +1,57 @@ +using GeneXus.Application; +using GeneXus.Data.NTier; +using GeneXus.Procedure; + +namespace GeneXus.Programs.apps +{ + public class httpheaders : GXWebProcedure + { + + public httpheaders() + { + context = new GxContext(); + DataStoreUtil.LoadDataStores(context); + IsMain = true; + context.SetDefaultTheme("Carmine"); + } + + public httpheaders(IGxContext context) + { + this.context = context; + IsMain = false; + } + + public void execute(out string result) + { + initialize(); + executePrivate(out result); + } + + void executePrivate(out string result) + { + result = (context.GetHttpSecure() == 1 ? "https://" : "http://") + context.GetRemoteAddress(); + + cleanup(); + } + + public override void cleanup() + { + CloseOpenCursors(); + base.cleanup(); + if (IsMain) + { + context.CloseConnections(); + } + ExitApp(); + } + + protected void CloseOpenCursors() + { + } + + public override void initialize() + { + } + } + +} diff --git a/dotnet/test/DotNetCoreWebUnitTest/apps/httpheaders.svc b/dotnet/test/DotNetCoreWebUnitTest/apps/httpheaders.svc new file mode 100644 index 000000000..bbfa49ec1 --- /dev/null +++ b/dotnet/test/DotNetCoreWebUnitTest/apps/httpheaders.svc @@ -0,0 +1 @@ +<%@ServiceHost Service= "GeneXus.Programs.apps.httpheaders,apps.httpheaders" %> From 06421ddb265829ca1e9c07d25c1900d9ddf30651 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 28 Feb 2024 06:04:17 -0300 Subject: [PATCH 110/164] Unify the Azure.Identity package version with the one used in other Azure components. (#970) --- .../GeneXus.OpenTelemetry.Azure.AppInsights.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/GeneXus.OpenTelemetry.Azure.AppInsights.csproj b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/GeneXus.OpenTelemetry.Azure.AppInsights.csproj index bda60f087..6fcea0822 100644 --- a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/GeneXus.OpenTelemetry.Azure.AppInsights.csproj +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/GeneXus.OpenTelemetry.Azure.AppInsights.csproj @@ -11,7 +11,7 @@ - + From 492620c433b4c24f561241248fb50c2038ffe4c1 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 28 Feb 2024 10:25:27 -0300 Subject: [PATCH 111/164] Fix Content-Disposition header for HTTP reports with non-ASCII output file names. (#965) --- .../GxClasses/Model/GXWebProcedure.cs | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Model/GXWebProcedure.cs b/dotnet/src/dotnetframework/GxClasses/Model/GXWebProcedure.cs index fc01e6f12..295e553e0 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/GXWebProcedure.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/GXWebProcedure.cs @@ -6,6 +6,7 @@ namespace GeneXus.Procedure using System.Globalization; using GeneXus.Http; using GeneXus.Mime; + using System.Net.Mime; #if NETCORE using Microsoft.AspNetCore.Http; #else @@ -14,6 +15,7 @@ namespace GeneXus.Procedure public class GXWebProcedure : GXHttpHandler { + static readonly IGXLogger log = GXLoggerFactory.GetLogger(); protected int handle; protected GXReportMetadata reportMetadata; @@ -137,8 +139,19 @@ private void setOuputFileName() { fileType = outputType.ToLower(); } - - context.HttpContext.Response.AddHeader(HttpHeader.CONTENT_DISPOSITION, $"inline; filename={fileName}.{fileType}"); + try + { + ContentDisposition contentDisposition = new ContentDisposition + { + Inline = true, + FileName = $"{fileName}.{fileType}" + }; + context.HttpContext.Response.AddHeader(HttpHeader.CONTENT_DISPOSITION, contentDisposition.ToString()); + } + catch (Exception ex) + { + GXLogging.Warn(log, $"{HttpHeader.CONTENT_DISPOSITION} couldn't be set for {fileName}.{fileType}", ex); + } } } @@ -152,9 +165,9 @@ protected bool initPrinter(String output, int gxXPage, int gxYPage, String iniFi if (!Config.GetValueOf("LANGUAGE", out idiom)) idiom = "eng"; fileContentInline = true; -#if NETCORE + setOuputFileName(); -#endif + getPrinter().GxRVSetLanguage(idiom); int xPage = gxXPage; int yPage = gxYPage; From 29f587642872ed3c99881d50da2e4a99999ebe37 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 28 Feb 2024 10:39:46 -0300 Subject: [PATCH 112/164] Direct project references were not checking the version number between them (#968) --- .../ProjectHealthTest/PackageVersionsConsistency.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/dotnet/test/ProjectHealthTest/PackageVersionsConsistency.cs b/dotnet/test/ProjectHealthTest/PackageVersionsConsistency.cs index 29be3c9ad..bce4ec15e 100644 --- a/dotnet/test/ProjectHealthTest/PackageVersionsConsistency.cs +++ b/dotnet/test/ProjectHealthTest/PackageVersionsConsistency.cs @@ -216,9 +216,18 @@ private bool AnyDirectReferenceLessThanTransitiveVersion(ICollection GetVersion(k.Version) > directVersion); + return value.Any(k => DirectReferenceLessThanTransitiveVersion(directVersion, k) || DiferentDirectReferences(directVersion, k)); } } + private bool DiferentDirectReferences(Version directVersion, PackageVersionItem k) + { + return (!k.Transitive && GetVersion(k.Version) != directVersion); + } + private bool DirectReferenceLessThanTransitiveVersion(Version directVersion, PackageVersionItem k) + { + return (k.Transitive && GetVersion(k.Version) > directVersion); + } + private Version GetVersion(String versionString) { return Version.Parse(Regex.Match(versionString, VersionPattern).Value); From fe0e851f2fb6f63a54d516a596f040e43a7c4333 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 28 Feb 2024 16:02:44 -0300 Subject: [PATCH 113/164] The cookie header was not parsed correctly (#943) * The cookie header was not parsed correctly; it failed when the value had a blank space before the cookie name. * Minor to force build process. --- .../GxClasses/Domain/GxHttpClient.cs | 17 +++++++++++- .../DotNetUnitTest/Domain/GxHttpClientTest.cs | 27 ++++++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs index b536ad6c1..712dcee1d 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs @@ -584,7 +584,12 @@ void setHeaders(HttpRequestMessage request, CookieContainer cookies) { if (cookie.Contains("=")) { - cookies.Add(new Uri(request.RequestUri.Host), new Cookie(cookie.Split('=')[0], cookie.Split('=')[1]) { Domain = request.RequestUri.Host }); + UriBuilder uriBuilder = new UriBuilder(request.RequestUri.Scheme, request.RequestUri.Host); + Cookie pCookie = ParseCookie(cookie, request.RequestUri.Host); + if (pCookie != null) + { + cookies.Add(uriBuilder.Uri, pCookie); + } } } break; @@ -608,6 +613,16 @@ void setHeaders(HttpRequestMessage request, CookieContainer cookies) } InferContentType(contentType, request); } + Cookie ParseCookie(string cookie, string domain) + { + string[] values = cookie.TrimEnd(';').Split('='); + if (values.Length >= 2) { + string cookieName = values[0].Trim(); + string cookieValue = values[1]; + return new Cookie(cookieName, cookieValue) { Domain = domain }; + } + return null; + } void AddHeader(HttpRequestHeaders headers, string headerName, string headerValue) { headers.TryAddWithoutValidation(headerName, headerValue); diff --git a/dotnet/test/DotNetUnitTest/Domain/GxHttpClientTest.cs b/dotnet/test/DotNetUnitTest/Domain/GxHttpClientTest.cs index 4dd50cdd7..cb9547c4a 100644 --- a/dotnet/test/DotNetUnitTest/Domain/GxHttpClientTest.cs +++ b/dotnet/test/DotNetUnitTest/Domain/GxHttpClientTest.cs @@ -27,7 +27,6 @@ public void AddHeaderWithSpecialCharactersDoesNotThrowException() httpclient.Execute("GET", string.Empty); Assert.NotEqual(((int)HttpStatusCode.InternalServerError), httpclient.StatusCode); } - } [Fact] @@ -45,6 +44,32 @@ public void HttpClientInvalidURLWithCustomPort() Assert.NotEqual(((int)HttpStatusCode.InternalServerError), httpclient.StatusCode); } } + + [Fact] + public void HttpClientCookieHeader() + { + string headerValue = "CognitoIdentityServiceProvider.3tgmin25m9bkg6vgi7vpavu7a9.M00000936.refreshToken=eyJjdHkiOiJKV1QiLCJlbmMiSkRCAmMpYqndvORnWLTfHw; CognitoIdentityServiceProvider.3tgmin25m9bkg6vgi7vpavu7a9.LastAuthUser=M00000936"; + string headerName = "Cookie"; + using (GxHttpClient httpclient = new GxHttpClient()) + { + httpclient.AddHeader(headerName, headerValue); + httpclient.Host = "localhost"; + httpclient.Port = 80; + httpclient.BaseURL = @"NotFound/NotFound.php"; + httpclient.HttpClientExecute("GET", string.Empty); + Assert.NotEqual(((int)HttpStatusCode.InternalServerError), httpclient.StatusCode); + } + using (GxHttpClient oldHttpclient = new GxHttpClient()) + { + oldHttpclient.AddHeader(headerName, headerValue); + oldHttpclient.Host = "localhost"; + oldHttpclient.Port = 80; + oldHttpclient.BaseURL = @"NotFound/NotFound.php"; + oldHttpclient.Execute("GET", string.Empty); + Assert.NotEqual(((int)HttpStatusCode.InternalServerError), oldHttpclient.StatusCode); + } + + } #if !NETCORE [Fact] public void NoStoreHeader() From 07e1dae731579f8c807b806bff70bbbeff76fa54 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Fri, 1 Mar 2024 10:24:20 -0300 Subject: [PATCH 114/164] Adjusted the maximum token size dynamically based on the token length to prevent 403 Forbidden errors when handling large tokens. (#971) --- dotnet/src/dotnetframework/GxClasses/Security/WebSecurity.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dotnet/src/dotnetframework/GxClasses/Security/WebSecurity.cs b/dotnet/src/dotnetframework/GxClasses/Security/WebSecurity.cs index 89c24b083..27eb82564 100644 --- a/dotnet/src/dotnetframework/GxClasses/Security/WebSecurity.cs +++ b/dotnet/src/dotnetframework/GxClasses/Security/WebSecurity.cs @@ -129,6 +129,10 @@ internal static WebSecureToken getWebSecureToken(string signedToken, string secr using (var hmac = new System.Security.Cryptography.HMACSHA256(bSecretKey)) { var handler = new JwtSecurityTokenHandler(); + if (signedToken.Length >= handler.MaximumTokenSizeInBytes) + { + handler.MaximumTokenSizeInBytes = signedToken.Length + 1; + } var validationParameters = new TokenValidationParameters { ClockSkew = TimeSpan.FromMinutes(1), From 96e2a977b96eb64fe0182e51dce66713bce51300 Mon Sep 17 00:00:00 2001 From: sgrampone <30872877+sgrampone@users.noreply.github.com> Date: Fri, 1 Mar 2024 12:32:02 -0300 Subject: [PATCH 115/164] SecurityAPI PKCS7/CMS standard signature implementation (#966) * SecurityAPI PKCS7/CMS standard signature implementation * Fix Scrypt test --- .../GeneXusCryptographyNetCore.csproj | 12 +- .../GeneXusJWTNetCore.csproj | 2 +- .../GeneXusXmlSignatureNetCore.csproj | 2 +- .../SecurityAPICommonsNetCore.csproj | 2 +- .../Asymmetric/StandardSigner.cs | 202 ++++++++++ .../AsymmetricSigningAlgorithm.cs | 16 + .../SignatureStandardOptions.cs | 57 +++ .../AsymmetricUtils/SignatureStandardUtils.cs | 47 +++ .../Commons/IStandardSignerObject.cs | 12 + .../Keys/PrivateKeyManager.cs | 22 +- .../SecurityAPITestNetCore.csproj | 1 + .../Asymmetric/TestRSAStandardSigning.cs | 349 ++++++++++++++++++ .../TestPasswordDerivation.cs | 14 +- 13 files changed, 724 insertions(+), 14 deletions(-) create mode 100644 dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/Asymmetric/StandardSigner.cs create mode 100644 dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/AsymmetricUtils/SignatureStandardOptions.cs create mode 100644 dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/AsymmetricUtils/SignatureStandardUtils.cs create mode 100644 dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/Commons/IStandardSignerObject.cs create mode 100644 dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Cryptography/Asymmetric/TestRSAStandardSigning.cs diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusCryptographyNetCore/GeneXusCryptographyNetCore.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusCryptographyNetCore/GeneXusCryptographyNetCore.csproj index 15ab5514c..b3d135f44 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusCryptographyNetCore/GeneXusCryptographyNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusCryptographyNetCore/GeneXusCryptographyNetCore.csproj @@ -15,8 +15,11 @@ + + + @@ -30,6 +33,7 @@ + @@ -45,10 +49,6 @@ - - - - @@ -67,4 +67,8 @@ + + + + diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj index 8cebbad16..299927dd2 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj @@ -33,11 +33,11 @@ + - diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusXmlSignatureNetCore/GeneXusXmlSignatureNetCore.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusXmlSignatureNetCore/GeneXusXmlSignatureNetCore.csproj index fddff7894..b6e1601c5 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusXmlSignatureNetCore/GeneXusXmlSignatureNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusXmlSignatureNetCore/GeneXusXmlSignatureNetCore.csproj @@ -26,7 +26,7 @@ - + diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/SecurityAPICommonsNetCore/SecurityAPICommonsNetCore.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/SecurityAPICommonsNetCore/SecurityAPICommonsNetCore.csproj index faba4af3b..64daf268f 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/SecurityAPICommonsNetCore/SecurityAPICommonsNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/SecurityAPICommonsNetCore/SecurityAPICommonsNetCore.csproj @@ -34,7 +34,7 @@ - + diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/Asymmetric/StandardSigner.cs b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/Asymmetric/StandardSigner.cs new file mode 100644 index 000000000..d9049dac3 --- /dev/null +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/Asymmetric/StandardSigner.cs @@ -0,0 +1,202 @@ +using System; +using System.Collections.Generic; +using System.Security; +using GeneXusCryptography.AsymmetricUtils; +using GeneXusCryptography.Commons; +using Org.BouncyCastle.Cms; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using SecurityAPICommons.Commons; +using SecurityAPICommons.Config; +using SecurityAPICommons.Keys; +using SecurityAPICommons.Utils; +using Org.BouncyCastle.Utilities.Collections; + + +namespace GeneXusCryptography.Asymmetric +{ + [SecuritySafeCritical] + public class StandardSigner : SecurityAPIObject, IStandardSignerObject + { + + public StandardSigner() : base() + { + + } + + /******** EXTERNAL OBJECT PUBLIC METHODS - BEGIN ********/ + + [SecuritySafeCritical] + public string Sign(string plainText, SignatureStandardOptions options) + { + this.error.cleanError(); + + /******* INPUT VERIFICATION - BEGIN *******/ + SecurityUtils.validateObjectInput("signatureStandardOptions", options, this.error); + SecurityUtils.validateObjectInput("private key", options.GetPrivateKey(), this.error); + SecurityUtils.validateObjectInput("certificate", options.GetCertificate(), this.error); + SecurityUtils.validateStringInput("plainText", plainText, this.error); + if (this.HasError()) + { + return ""; + } + + /******* INPUT VERIFICATION - END *******/ + + EncodingUtil eu = new EncodingUtil(); + byte[] inputText = eu.getBytes(plainText); + if (eu.HasError()) + { + this.error = eu.GetError(); + return ""; + } + + string result = ""; + try + { + result = Sign_internal(inputText, options.GetPrivateKey(), options.GetCertificate(), options.GetSignatureStandard(), options.GetEncapsulated()); + } + catch (Exception e) + { + error.setError("SS002", e.Message); + result = ""; + } + + return result; + } + + [SecuritySafeCritical] + + public bool Verify(string signed, string plainText, SignatureStandardOptions options) + { + this.error.cleanError(); + + /******* INPUT VERIFICATION - BEGIN *******/ + SecurityUtils.validateObjectInput("signatureStandardOptions", options, this.error); + //SecurityUtils.validateStringInput("plainText", plainText, this.error); + SecurityUtils.validateStringInput("signed", signed, this.error); + if (this.HasError()) + { + return false; + } + + + /******* INPUT VERIFICATION - END *******/ + + EncodingUtil eu = new EncodingUtil(); + byte[] plainText_bytes = eu.getBytes(plainText); + if (eu.HasError()) + { + this.error = eu.GetError(); + return false; + } + + bool result = false; + try + { + result = Verify_internal(Base64.Decode(signed), plainText_bytes, options.GetEncapsulated()); + } + catch (Exception e) + { + error.setError("SS002", e.Message); + result = false; + } + + return result; + } + + /******** EXTERNAL OBJECT PUBLIC METHODS - END ********/ + + private string Sign_internal(byte[] input, PrivateKeyManager key, CertificateX509 cert, SignatureStandard signatureStandard, bool encapsulated) + { + + PrivateKeyManager keyMan = (PrivateKeyManager)key; + if (keyMan.HasError()) + { + this.error = keyMan.GetError(); + return ""; + } + CertificateX509 certificate = (CertificateX509)cert; + if (certificate.HasError()) + { + + this.error = certificate.GetError(); + return ""; + } + AsymmetricSigningAlgorithm asymmetricSigningAlgorithm = AsymmetricSigningAlgorithmUtils + .GetAsymmetricSigningAlgorithm(keyMan.getAlgorithm(), this.error); + string encryptAlg = AsymmetricSigningAlgorithmUtils.GetCMSSigningAlgortithm(asymmetricSigningAlgorithm, this.error); + if (this.HasError()) { return ""; } + + Org.BouncyCastle.X509.X509Certificate cert2 = DotNetUtilities.FromX509Certificate(certificate.Cert); + + CmsSignedDataGenerator generator = new CmsSignedDataGenerator(); + string digest = asymmetricSigningAlgorithm == AsymmetricSigningAlgorithm.ECDSA ? CmsSignedGenerator.DigestSha1 : DigestCalculator(certificate); + + generator.AddSigner(keyMan.getAsymmetricKeyParameter(), cert2, encryptAlg, digest); + + List certList = new List(); + certList.Add(cert2); + + IStore certStore = CollectionUtilities.CreateStore(certList); + + generator.AddCertificates(certStore); + + CmsSignedData signedData = generator.Generate(new CmsProcessableByteArray(input), encapsulated); + + + return Base64.ToBase64String(signedData.GetEncoded()); + + } + + + private bool Verify_internal(byte[] cmsSignedData, byte[] data, bool encapsulated) + { + CmsSignedData cms = encapsulated ? new CmsSignedData(cmsSignedData) : new CmsSignedData(new CmsProcessableByteArray(data), cmsSignedData); + + SignerInformationStore signers = cms.GetSignerInfos(); + + IStore certificates = cms.GetCertificates(); + var signerInfos = signers.GetSigners(); + foreach (SignerInformation signer in signerInfos) + { + var certCollection = certificates.EnumerateMatches(signer.SignerID); + var certEnum = certCollection.GetEnumerator(); + + certEnum.MoveNext(); + Org.BouncyCastle.X509.X509Certificate cert = certEnum.Current; + var publicKey = cert.GetPublicKey(); + bool res = false; + + res = signer.Verify(publicKey); + + if (!res) + { + return false; + } + } + return true; + } + + + + private string DigestCalculator(CertificateX509 cert) + { + string value = cert.getPublicKeyHash(); + switch (value) + { + case "SHA1": + return CmsSignedGenerator.DigestSha1; + case "SHA256": + return CmsSignedGenerator.DigestSha256; + case "SHA512": + return CmsSignedGenerator.DigestSha512; + default: + this.error.setError("SS003", "Unrecognizable certificate hash algorithm"); + return ""; + } + + } + + } +} diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/AsymmetricUtils/AsymmetricSigningAlgorithm.cs b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/AsymmetricUtils/AsymmetricSigningAlgorithm.cs index b68931b14..3624f125b 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/AsymmetricUtils/AsymmetricSigningAlgorithm.cs +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/AsymmetricUtils/AsymmetricSigningAlgorithm.cs @@ -1,4 +1,5 @@ +using Org.BouncyCastle.Cms; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Signers; using SecurityAPICommons.Commons; @@ -97,6 +98,21 @@ public static ISigner GetSigner(AsymmetricSigningAlgorithm asymmetricSigningAlgo return sig; } + public static string GetCMSSigningAlgortithm(AsymmetricSigningAlgorithm asymmetricSigningAlgorithm, Error error) + { + if (error == null) return null; + switch (asymmetricSigningAlgorithm) + { + case AsymmetricSigningAlgorithm.RSA: + return CmsSignedDataGenerator.EncryptionRsa; + case AsymmetricSigningAlgorithm.ECDSA: + return CmsSignedDataGenerator.EncryptionECDsa; + default: + error.setError("AE008", "Not recogrnized AsymmetricSigningAlgorithm"); + return ""; + } + } + /// /// Manage Enumerable enum /// diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/AsymmetricUtils/SignatureStandardOptions.cs b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/AsymmetricUtils/SignatureStandardOptions.cs new file mode 100644 index 000000000..c1b59e98a --- /dev/null +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/AsymmetricUtils/SignatureStandardOptions.cs @@ -0,0 +1,57 @@ +using System; +using System.Security; +using SecurityAPICommons.Commons; +using SecurityAPICommons.Keys; + +namespace GeneXusCryptography.AsymmetricUtils +{ + [SecuritySafeCritical] + public class SignatureStandardOptions : SecurityAPIObject + { + private CertificateX509 certificate; + private PrivateKeyManager privateKey; + + private SignatureStandard signatureStandard; + + private bool encapsulated; + + [SecuritySafeCritical] + public SignatureStandardOptions() : base() + { + this.signatureStandard = SignatureStandard.CMS; + this.encapsulated = false; + } + + /******** EXTERNAL OBJECT PUBLIC METHODS - BEGIN ********/ + public void SetPrivateKey(PrivateKeyManager key) + { + this.privateKey = key; + } + + public void SetCertificate(CertificateX509 cert) + { + this.certificate = cert; + } + + public bool SetSignatureStandard(String standard) + { + this.signatureStandard = SignatureStandardUtils.getSignatureStandard(standard, this.error); + return this.HasError() ? false : true; + } + + public void SetEncapsulated(bool value) { this.encapsulated = value; } + + /******** EXTERNAL OBJECT PUBLIC METHODS - END ********/ + + public PrivateKeyManager GetPrivateKey() + { + return this.privateKey; + } + + public CertificateX509 GetCertificate() { return this.certificate; } + + public SignatureStandard GetSignatureStandard() { return this.signatureStandard; } + + public bool GetEncapsulated() { return this.encapsulated; } + } +} diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/AsymmetricUtils/SignatureStandardUtils.cs b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/AsymmetricUtils/SignatureStandardUtils.cs new file mode 100644 index 000000000..4796f18ee --- /dev/null +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/AsymmetricUtils/SignatureStandardUtils.cs @@ -0,0 +1,47 @@ +using System.Security; +using SecurityAPICommons.Commons; + +namespace GeneXusCryptography.AsymmetricUtils +{ + [SecuritySafeCritical] + public enum SignatureStandard + { + NONE, CMS, + } + + [SecuritySafeCritical] + public static class SignatureStandardUtils + { + public static SignatureStandard getSignatureStandard(string signatureStandard, + Error error) + { + if (error == null) return SignatureStandard.NONE; + if (signatureStandard == null) + { + error.setError("SS001", "Unrecognized SignatureStandard"); + return SignatureStandard.NONE; + } + switch (signatureStandard.ToUpper(System.Globalization.CultureInfo.InvariantCulture).Trim()) + { + case "CMS": + return SignatureStandard.CMS; + default: + error.setError("SS001", "Unrecognized SignatureStandard"); + return SignatureStandard.NONE; + } + } + + public static string valueOf(SignatureStandard signatureStandard, Error error) + { + if (error == null) return ""; + switch (signatureStandard) + { + case SignatureStandard.CMS: + return "CMS"; + default: + error.setError("SS002", "Unrecognized SignatureStandard"); + return ""; + } + } + } +} diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/Commons/IStandardSignerObject.cs b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/Commons/IStandardSignerObject.cs new file mode 100644 index 000000000..14fe60cd0 --- /dev/null +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/Commons/IStandardSignerObject.cs @@ -0,0 +1,12 @@ +using System.Security; +using GeneXusCryptography.AsymmetricUtils; + +namespace GeneXusCryptography.Commons +{ + [SecuritySafeCritical] + public interface IStandardSignerObject + { + string Sign(string plaintText, SignatureStandardOptions signatureStandardOptions); + bool Verify(string signed, string plainText, SignatureStandardOptions signatureStandardOptions); + } +} diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/Keys/PrivateKeyManager.cs b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/Keys/PrivateKeyManager.cs index 968c884e0..bbef4ad24 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/Keys/PrivateKeyManager.cs +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/Keys/PrivateKeyManager.cs @@ -20,6 +20,7 @@ using Org.BouncyCastle.Utilities.Encoders; using System.Security.AccessControl; using System.Globalization; +using System.Runtime.InteropServices; namespace SecurityAPICommons.Keys { @@ -220,8 +221,27 @@ public AsymmetricAlgorithm getPrivateKeyForXML() byte[] serializedPrivateBytes = this.privateKeyInfo.ToAsn1Object().GetDerEncoded(); string serializedPrivate = Convert.ToBase64String(serializedPrivateBytes); RsaPrivateCrtKeyParameters privateKey = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(serializedPrivate)); + + #if NETCORE - return DotNetUtilities.ToRSA(privateKey); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return DotNetUtilities.ToRSA(privateKey); + } + else + { + try + { + RSA rsa = RSA.Create(); + rsa.ImportPkcs8PrivateKey(serializedPrivateBytes, out int outthing); + return rsa; + }catch(Exception e ) + { + this.error.setError("PK026", e.Message); + return null; + } + } + #else diff --git a/dotnet/src/extensions/SecurityAPI/test/dotnetcore/SecurityAPITestNetCore/SecurityAPITestNetCore.csproj b/dotnet/src/extensions/SecurityAPI/test/dotnetcore/SecurityAPITestNetCore/SecurityAPITestNetCore.csproj index afda7fe55..a0786cbb3 100644 --- a/dotnet/src/extensions/SecurityAPI/test/dotnetcore/SecurityAPITestNetCore/SecurityAPITestNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/test/dotnetcore/SecurityAPITestNetCore/SecurityAPITestNetCore.csproj @@ -15,6 +15,7 @@ + diff --git a/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Cryptography/Asymmetric/TestRSAStandardSigning.cs b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Cryptography/Asymmetric/TestRSAStandardSigning.cs new file mode 100644 index 000000000..5d96be2f5 --- /dev/null +++ b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Cryptography/Asymmetric/TestRSAStandardSigning.cs @@ -0,0 +1,349 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using GeneXusCryptography.Asymmetric; +using GeneXusCryptography.AsymmetricUtils; +using NUnit.Framework; +using SecurityAPICommons.Config; +using SecurityAPICommons.Keys; +using SecurityAPITest.SecurityAPICommons.commons; + +namespace SecurityAPITest.Cryptography.Asymmetric +{ + [TestFixture] + public class TestRSAStandardSigning: SecurityAPITestObject + { + private static string path_RSA_sha1_1024; + private static string path_RSA_sha256_1024; + private static string path_RSA_sha256_2048; + private static string path_RSA_sha512_2048; + private static string[] encodings; + private static EncodingUtil eu; + + private static string plainText; + + public static string alias; + public static string password; + + [SetUp] + public virtual void SetUp() + { + + path_RSA_sha1_1024 = Path.Combine(BASE_PATH, "dummycerts", "RSA_sha1_1024"); + path_RSA_sha256_1024 = Path.Combine(BASE_PATH, "dummycerts", "RSA_sha256_1024"); + path_RSA_sha256_2048 = Path.Combine(BASE_PATH, "dummycerts", "RSA_sha256_2048"); + path_RSA_sha512_2048 = Path.Combine(BASE_PATH, "dummycerts", "RSA_sha512_2048"); + + //arrayPaddings = new String[] { "OAEPPADDING", "PCKS1PADDING", "ISO97961PADDING" }; + + plainText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam venenatis ex sit amet risus pellentesque, a faucibus quam ultrices. Ut tincidunt quam eu aliquam maximus. Quisque posuere risus at erat blandit eleifend. Curabitur viverra rutrum volutpat. Donec quis quam tellus. Aenean fermentum elementum augue, a semper risus scelerisque sit amet. Nullam vitae sapien vitae dui ullamcorper dapibus quis quis leo. Sed neque felis, pellentesque in risus et, lobortis ultricies nulla. Quisque quis quam risus. Donec vestibulum, lectus vel vestibulum eleifend, velit ante volutpat lacus, ut mattis quam ligula eget est. Sed et pulvinar lectus. In mollis turpis non ipsum vehicula, sit amet rutrum nibh dictum. Duis consectetur convallis ex, eu ultricies enim bibendum vel. Vestibulum vel libero nibh. Morbi nec odio mattis, vestibulum quam blandit, pretium orci.Aenean pellentesque tincidunt nunc a malesuada. Etiam gravida fermentum mi, at dignissim dui aliquam quis. Nullam vel lobortis libero. Phasellus non gravida posuere"; + + + alias = "1"; + password = "dummy"; + + encodings = new string[] { "UTF_8", "UTF_16", "UTF_16BE", "UTF_16LE", "UTF_32", "UTF_32BE", "UTF_32LE", "SJIS", "GB2312" }; + + eu = new EncodingUtil(); + } + + private void bulkTest(SignatureStandardOptions options) + { + for (int i = 0; i < encodings.Length; i++) + { + eu.setEncoding(encodings[i]); + test(options); + } + } + private void test(SignatureStandardOptions options) + { + options.SetEncapsulated(true); + StandardSigner signer = new StandardSigner(); + string signed_encapsulated = signer.Sign(plainText, options); + bool result_encapsulated = signer.Verify(signed_encapsulated, "", options); + Assert.IsTrue(result_encapsulated); + True(result_encapsulated, signer); + + options.SetEncapsulated(false); + string signed = signer.Sign(plainText, options); + bool result = signer.Verify(signed, plainText, options); + Assert.IsTrue(result); + True(result, signer); + } + + [Test] + public void Test_sha1_1024_DER() + { + + string pathKey = Path.Combine(path_RSA_sha1_1024, "sha1d_key.pem"); + string pathCert = Path.Combine(path_RSA_sha1_1024, "sha1_cert.crt"); + PrivateKeyManager key = new PrivateKeyManager(); + key.Load(pathKey); + CertificateX509 cert = new CertificateX509(); + cert.Load(pathCert); + SignatureStandardOptions options = new SignatureStandardOptions(); + options.SetCertificate(cert); + options.SetPrivateKey(key); + bulkTest(options); + } + + [Test] + public void Test_sha1_1024_PEM() + { + string pathKey = Path.Combine(path_RSA_sha1_1024, "sha1d_key.pem"); + string pathCert = Path.Combine(path_RSA_sha1_1024, "sha1_cert.pem"); + PrivateKeyManager key = new PrivateKeyManager(); + key.Load(pathKey); + CertificateX509 cert = new CertificateX509(); + cert.Load(pathCert); + SignatureStandardOptions options = new SignatureStandardOptions(); + options.SetCertificate(cert); + options.SetPrivateKey(key); + bulkTest(options); + + } + + [Test] + public void Test_sha1_1024_PKCS12() + { + string pathKey = Path.Combine(path_RSA_sha1_1024, "sha1_cert.p12"); + string pathCert = Path.Combine(path_RSA_sha1_1024, "sha1_cert.p12"); + PrivateKeyManager key = new PrivateKeyManager(); + key.LoadPKCS12(pathKey, alias, password); + CertificateX509 cert = new CertificateX509(); + cert.LoadPKCS12(pathCert, alias, password); + SignatureStandardOptions options = new SignatureStandardOptions(); + options.SetCertificate(cert); + options.SetPrivateKey(key); + bulkTest(options); + + } + + [Test] + public void Test_sha256_1024_DER() + { + string pathKey = Path.Combine(path_RSA_sha256_1024, "sha256d_key.pem"); + string pathCert = Path.Combine(path_RSA_sha256_1024, "sha256_cert.crt"); + PrivateKeyManager key = new PrivateKeyManager(); + key.Load(pathKey); + CertificateX509 cert = new CertificateX509(); + cert.Load(pathCert); + SignatureStandardOptions options = new SignatureStandardOptions(); + options.SetCertificate(cert); + options.SetPrivateKey(key); + bulkTest(options); + + } + + [Test] + public void Test_sha256_1024_PEM() + { + string pathKey = Path.Combine(path_RSA_sha256_1024, "sha256d_key.pem"); + string pathCert = Path.Combine(path_RSA_sha256_1024, "sha256_cert.pem"); + PrivateKeyManager key = new PrivateKeyManager(); + key.Load(pathKey); + CertificateX509 cert = new CertificateX509(); + cert.Load(pathCert); + SignatureStandardOptions options = new SignatureStandardOptions(); + options.SetCertificate(cert); + options.SetPrivateKey(key); + bulkTest(options); + + } + + [Test] + public void Test_sha256_1024_PKCS12() + { + string pathKey = Path.Combine(path_RSA_sha256_1024, "sha256_cert.p12"); + string pathCert = Path.Combine(path_RSA_sha256_1024, "sha256_cert.p12"); + PrivateKeyManager key = new PrivateKeyManager(); + key.LoadPKCS12(pathKey, alias, password); + CertificateX509 cert = new CertificateX509(); + cert.LoadPKCS12(pathCert, alias, password); + SignatureStandardOptions options = new SignatureStandardOptions(); + options.SetCertificate(cert); + options.SetPrivateKey(key); + bulkTest(options); + + } + + [Test] + public void Test_sha256_2048_DER() + { + string pathKey = Path.Combine(path_RSA_sha256_2048, "sha256d_key.pem"); + string pathCert = Path.Combine(path_RSA_sha256_2048, "sha256_cert.crt"); + PrivateKeyManager key = new PrivateKeyManager(); + key.Load(pathKey); + CertificateX509 cert = new CertificateX509(); + cert.Load(pathCert); + SignatureStandardOptions options = new SignatureStandardOptions(); + options.SetCertificate(cert); + options.SetPrivateKey(key); + bulkTest(options); + + } + + [Test] + public void Test_sha256_2048_PEM() + { + string pathKey = Path.Combine(path_RSA_sha256_2048, "sha256d_key.pem"); + string pathCert = Path.Combine(path_RSA_sha256_2048, "sha256_cert.pem"); + PrivateKeyManager key = new PrivateKeyManager(); + key.Load(pathKey); + CertificateX509 cert = new CertificateX509(); + cert.Load(pathCert); + SignatureStandardOptions options = new SignatureStandardOptions(); + options.SetCertificate(cert); + options.SetPrivateKey(key); + bulkTest(options); + + } + + + [Test] + public void Test_sha256_2048_PKCS12() + { + string pathKey = Path.Combine(path_RSA_sha256_2048, "sha256_cert.p12"); + string pathCert = Path.Combine(path_RSA_sha256_2048, "sha256_cert.p12"); + PrivateKeyManager key = new PrivateKeyManager(); + key.LoadPKCS12(pathKey, alias, password); + CertificateX509 cert = new CertificateX509(); + cert.LoadPKCS12(pathCert, alias, password); + SignatureStandardOptions options = new SignatureStandardOptions(); + options.SetCertificate(cert); + options.SetPrivateKey(key); + bulkTest(options); + + } + + [Test] + public void Test_sha512_2048_DER() + { + string pathKey = Path.Combine(path_RSA_sha512_2048, "sha512d_key.pem"); + string pathCert = Path.Combine(path_RSA_sha512_2048, "sha512_cert.crt"); + PrivateKeyManager key = new PrivateKeyManager(); + key.Load(pathKey); + CertificateX509 cert = new CertificateX509(); + cert.Load(pathCert); + SignatureStandardOptions options = new SignatureStandardOptions(); + options.SetCertificate(cert); + options.SetPrivateKey(key); + bulkTest(options); + + } + + [Test] + public void Test_sha512_2048_PEM() + { + string pathKey = Path.Combine(path_RSA_sha512_2048, "sha512d_key.pem"); + string pathCert = Path.Combine(path_RSA_sha512_2048, "sha512_cert.pem"); + PrivateKeyManager key = new PrivateKeyManager(); + key.Load(pathKey); + CertificateX509 cert = new CertificateX509(); + cert.Load(pathCert); + SignatureStandardOptions options = new SignatureStandardOptions(); + options.SetCertificate(cert); + options.SetPrivateKey(key); + bulkTest(options); + + } + + + [Test] + public void Test_sha512_2048_PKCS12() + { + string pathKey = Path.Combine(path_RSA_sha512_2048, "sha512_cert.p12"); + string pathCert = Path.Combine(path_RSA_sha512_2048, "sha512_cert.p12"); + PrivateKeyManager key = new PrivateKeyManager(); + key.LoadPKCS12(pathKey, alias, password); + CertificateX509 cert = new CertificateX509(); + cert.LoadPKCS12(pathCert, alias, password); + SignatureStandardOptions options = new SignatureStandardOptions(); + options.SetCertificate(cert); + options.SetPrivateKey(key); + bulkTest(options); + } + + [Test] + public void Test_base64() + { + string base64stringCert = "MIIC/DCCAmWgAwIBAgIJAPmCVmfcc0IXMA0GCSqGSIb3DQEBCwUAMIGWMQswCQYDVQQGEwJVWTETMBEGA1UECAwKTW9udGV2aWRlbzETMBEGA1UEBwwKTW9udGV2aWRlbzEQMA4GA1UECgwHR2VuZVh1czERMA8GA1UECwwIU2VjdXJpdHkxEjAQBgNVBAMMCXNncmFtcG9uZTEkMCIGCSqGSIb3DQEJARYVc2dyYW1wb25lQGdlbmV4dXMuY29tMB4XDTIwMDcwODE4NDkxNVoXDTI1MDcwNzE4NDkxNVowgZYxCzAJBgNVBAYTAlVZMRMwEQYDVQQIDApNb250ZXZpZGVvMRMwEQYDVQQHDApNb250ZXZpZGVvMRAwDgYDVQQKDAdHZW5lWHVzMREwDwYDVQQLDAhTZWN1cml0eTESMBAGA1UEAwwJc2dyYW1wb25lMSQwIgYJKoZIhvcNAQkBFhVzZ3JhbXBvbmVAZ2VuZXh1cy5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMZ8m4ftIhfrdugi5kEszRZr5IRuqGDLTex+CfVnhnBYXyQgJXeCI0eyRYUAbNzw/9MPdFN//pV26AXeH/ajORVu1JVoOACZdNOIPFnwXXh8oBxNxLAYlqoK2rAL+/tns8rKqqS4p8HSat9tj07TUXnsYJmmbXJM/eB94Ex66D1ZAgMBAAGjUDBOMB0GA1UdDgQWBBTfXY8eOfDONCZpFE0V34mJJeCYtTAfBgNVHSMEGDAWgBTfXY8eOfDONCZpFE0V34mJJeCYtTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GBAAPv7AFlCSpJ32c/VYowlbk6UBhOKmVWBQlrAtvVQYtCKO/y9CEB8ikG19c8lHM9axnsbZR+G7g04Rfuiea3T7VPkSmUXPpz5fl6Zyk4LZg5Oji7MMMXGmr+7cpYWRhifCVwoxSgZEXt3d962IZ1Wei0LMO+4w4gnzPxqr8wVHnT"; + string base64stringKey = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAMZ8m4ftIhfrdugi5kEszRZr5IRuqGDLTex+CfVnhnBYXyQgJXeCI0eyRYUAbNzw/9MPdFN//pV26AXeH/ajORVu1JVoOACZdNOIPFnwXXh8oBxNxLAYlqoK2rAL+/tns8rKqqS4p8HSat9tj07TUXnsYJmmbXJM/eB94Ex66D1ZAgMBAAECgYA1xrTs0taV3HnO0wXHSrgWBw1WxBRihTKLjGpuTqoh7g943izIgD3GwwoKyt6zzafCK0G9DcSQAjNCw7etPvPL3FxwhDl+AHSv9JcChk/auICtMWwjurG4npto+s3byj/N00Idpz1xuOgKd8k9sdoPBGKa8l+LL+adSXzoivLG8QJBAPDvbOLSs9petB2iM6w5/DiC8EoxqDaBc7I1JFCvPOfB7i1GFFxkQ7hlgxpvaPX3NHXjAZpgdOW68P/SjU0izKsCQQDS5bjrNo3xn/MbYKojzwprR/Bo8Kvbi4/2M9NE3GwHegVmx5I+df+J0aObrbBNPLs/rhrFtt12OtgxJaac+FYLAkEA8DUUbvO4wj7m/iBnug65irHo1V+6oFThv0tCIHsFkt4DEvoqdI62AZKbafCnSYqjr+CaCYqfIScG/Vay77OBLwJBAI8EYAmKPmn7+SW4wMh1z+/+ogbYJwNEOoVQkdXh0JSlZ+JSNleLN5ajhtq8x5EpPSYrEFbB8p8JurBhgwJx2g8CQQDrp9scoK8eKBJ2p/63xqLGYSN6OZQo/4Lkq3983rmHoDCAp3Bz1zUyxQB3UVyrOj4U44C7RtDNiMSZuCwvjYAI"; + PrivateKeyManager key = new PrivateKeyManager(); + key.FromBase64(base64stringKey); + CertificateX509 cert = new CertificateX509(); + cert.FromBase64(base64stringCert); + SignatureStandardOptions options = new SignatureStandardOptions(); + options.SetCertificate(cert); + options.SetPrivateKey(key); + bulkTest(options); + } + + [Test] + public void Test_sha1_1024_PEM_Encrypted() + { + string pathKey = Path.Combine(path_RSA_sha1_1024, "sha1_key.pem"); + string pathCert = Path.Combine(path_RSA_sha1_1024, "sha1_cert.pem"); + PrivateKeyManager key = new PrivateKeyManager(); + key.LoadEncrypted(pathKey, password); + CertificateX509 cert = new CertificateX509(); + cert.Load(pathCert); + SignatureStandardOptions options = new SignatureStandardOptions(); + options.SetCertificate(cert); + options.SetPrivateKey(key); + bulkTest(options); + + } + + [Test] + public void Test_sha256_1024_PEM_Encrypted() + { + string pathKey = Path.Combine(path_RSA_sha256_1024, "sha256_key.pem"); + string pathCert = Path.Combine(path_RSA_sha256_1024, "sha256_cert.pem"); + PrivateKeyManager key = new PrivateKeyManager(); + key.LoadEncrypted(pathKey, password); + CertificateX509 cert = new CertificateX509(); + cert.Load(pathCert); + SignatureStandardOptions options = new SignatureStandardOptions(); + options.SetCertificate(cert); + options.SetPrivateKey(key); + bulkTest(options); + + } + + [Test] + public void Test_sha256_2048_PEM_Encrypted() + { + string pathKey = Path.Combine(path_RSA_sha256_2048, "sha256_key.pem"); + string pathCert = Path.Combine(path_RSA_sha256_2048, "sha256_cert.pem"); + PrivateKeyManager key = new PrivateKeyManager(); + key.LoadEncrypted(pathKey, password); + CertificateX509 cert = new CertificateX509(); + cert.Load(pathCert); + SignatureStandardOptions options = new SignatureStandardOptions(); + options.SetCertificate(cert); + options.SetPrivateKey(key); + bulkTest(options); + + } + + [Test] + public void Test_sha512_2048_PEM_Encrypted() + { + string pathKey = Path.Combine(path_RSA_sha512_2048, "sha512_key.pem"); + string pathCert = Path.Combine(path_RSA_sha512_2048, "sha512_cert.pem"); + PrivateKeyManager key = new PrivateKeyManager(); + key.LoadEncrypted(pathKey, password); + CertificateX509 cert = new CertificateX509(); + cert.Load(pathCert); + SignatureStandardOptions options = new SignatureStandardOptions(); + options.SetCertificate(cert); + options.SetPrivateKey(key); + bulkTest(options); + + } + } +} diff --git a/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Cryptography/PasswordDerivation/TestPasswordDerivation.cs b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Cryptography/PasswordDerivation/TestPasswordDerivation.cs index a87fa9079..296801d38 100644 --- a/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Cryptography/PasswordDerivation/TestPasswordDerivation.cs +++ b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Cryptography/PasswordDerivation/TestPasswordDerivation.cs @@ -1,4 +1,4 @@ -using SecurityAPITest.SecurityAPICommons.commons; +using SecurityAPITest.SecurityAPICommons.commons; using System; using NUnit.Framework; using SecurityAPICommons.Config; @@ -78,15 +78,17 @@ public void TestScrypt() string derivated = pd.DoGenerateSCrypt(password, saltScrypt, N, r, p, keyLenght); Assert.AreEqual(expectedScrypt, derivated); Equals(expectedScrypt, derivated, pd); + } - [Test] + /*[Test] public void TestDefaultScrypt() { - string derivated = pd.DoGenerateDefaultSCrypt(password, saltScrypt); - Assert.AreEqual(expectedScrypt, derivated); - Equals(expectedScrypt, derivated, pd); - } + string derivated1 = pd.DoGenerateDefaultSCrypt(password, saltScrypt); + Assert.AreEqual(expectedScrypt, derivated1); + Equals(expectedScrypt, derivated1, pd); + + }*/ [Test] public void TestBcrypt() From d9882e056e13a7bfc31fef5cbb2fb52111a08035 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Sexenian?= <99925035+tomas-sexenian@users.noreply.github.com> Date: Mon, 4 Mar 2024 12:54:28 -0300 Subject: [PATCH 116/164] PDFPig support (#962) * Initial commit for PDF Pig support Issue: 105642 * Move PDFPig implementation to dotnetcore folder * Add exception catching in GxStartPage * Fix class naming error * Move the first 'documentBuilder.AddPage' to the init method to ensure the proper initialization of 'pageBuilder,' which is required for initializing 'gxXPage' * Support standard page size. * Fix System.NotSupportedException: Stream does not support reading. * Various PDF Pig report implementation fixes * Provide logging for not supported features * Read chosen report implementation from property value * Try create AddedImage from url and try create Type1 font from font name * Constructor with two arguments in GxReportBuilderPdf8 ended up invoking the default constructor of the base class which itext4. * Constructor with two arguments in GxReportBuilderPdf8 ended up invoking the default constructor of the base class which itext4. * _appPath was not being properly initialized. * Unify the PdfPig version with the one used in GxPdfReportsCS. * Remove and sort usings. Force build action. * Avoid NullReferenceException when handling unknown fonts just as Bold fonts. --------- Co-authored-by: Claudia Murialdo --- .../GxPdfReportsCS/GlobalSuppressions.cs | 4 +- .../GxPdfReportsCS/GxPdfReportsCS.csproj | 3 + .../GxPdfReportsCS/PDFReportItext8.cs | 4 +- .../GxPdfReportsCS/PDFReportPDFPig.cs | 1044 +++++++++++++++++ .../src/dotnetcore/GxSearch/GxSearch.csproj | 2 +- .../dotnetframework/GxClasses/Model/gxproc.cs | 9 +- .../GxPdfReportsCS/PDFReportCommon.cs | 11 +- .../GxPdfReportsCS/PDFReportItext4.cs | 2 +- .../GxPdfReportsCS/PdfReportInterface.cs | 7 +- .../DotNetPdfTest/DotNetPDFUnitTest.csproj | 1 + 10 files changed, 1073 insertions(+), 14 deletions(-) create mode 100644 dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportPDFPig.cs diff --git a/dotnet/src/dotnetcore/GxPdfReportsCS/GlobalSuppressions.cs b/dotnet/src/dotnetcore/GxPdfReportsCS/GlobalSuppressions.cs index dc00e11aa..74e1befce 100644 --- a/dotnet/src/dotnetcore/GxPdfReportsCS/GlobalSuppressions.cs +++ b/dotnet/src/dotnetcore/GxPdfReportsCS/GlobalSuppressions.cs @@ -16,5 +16,5 @@ [assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:com.genexus.reports.NativeSharpFunctionsMS.getRegistrySubValues(System.String,System.String)~System.Collections.ArrayList")] [assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:com.genexus.reports.NativeSharpFunctionsMS.ReadRegKey(System.String)~System.String")] [assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:com.genexus.reports.MSPDFFontDescriptor.getTrueTypeFontLocation(System.String)~System.String")] -[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:com.genexus.reports.PDFReportItextBase.getAcrobatLocation~System.String")] -[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:com.genexus.reports.PDFReportItextBase.loadSubstituteTable")] +[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:com.genexus.reports.PDFReportBase.getAcrobatLocation~System.String")] +[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:com.genexus.reports.PDFReportBase.loadSubstituteTable")] diff --git a/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj b/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj index ab6fb41c6..95fa355b4 100644 --- a/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj +++ b/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj @@ -15,6 +15,9 @@ + + + diff --git a/dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportItext8.cs b/dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportItext8.cs index bad1d5e68..c927b8281 100644 --- a/dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportItext8.cs +++ b/dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportItext8.cs @@ -35,7 +35,7 @@ public class GxReportBuilderPdf8 : GxReportBuilderPdf public GxReportBuilderPdf8() { } public GxReportBuilderPdf8(string appPath, Stream outputStream) { - + _appPath = appPath; _pdfReport = new com.genexus.reports.PDFReportItext8(appPath); if (outputStream != null) { @@ -49,7 +49,7 @@ public GxReportBuilderPdf8(string appPath, Stream outputStream) namespace com.genexus.reports { - public class PDFReportItext8 : PDFReportItextBase + public class PDFReportItext8 : PDFReportBase { static IGXLogger log = GXLoggerFactory.GetLogger(); diff --git a/dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportPDFPig.cs b/dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportPDFPig.cs new file mode 100644 index 000000000..0f1a30120 --- /dev/null +++ b/dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportPDFPig.cs @@ -0,0 +1,1044 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using System.Drawing.Text; +using System.IO; +using System.Net.Http; +using System.Text; +using GeneXus; +using UglyToad.PdfPig.Core; +using UglyToad.PdfPig.Fonts.Standard14Fonts; +using UglyToad.PdfPig.Writer; +using static GeneXus.Utils.StringUtil; +using static UglyToad.PdfPig.Writer.PdfDocumentBuilder; +using static UglyToad.PdfPig.Writer.PdfPageBuilder; +using Color = System.Drawing.Color; +using Font = System.Drawing.Font; +using PageSize = UglyToad.PdfPig.Content.PageSize; +using PdfRectangle = UglyToad.PdfPig.Core.PdfRectangle; + +namespace GeneXus.Printer +{ + public class GxReportBuilderPDFPig : GxReportBuilderPdf + { + static IGXLogger log = GXLoggerFactory.GetLogger(); + public GxReportBuilderPDFPig() { } + public GxReportBuilderPDFPig(string appPath, Stream outputStream) + { + _appPath = appPath; + _pdfReport = new com.genexus.reports.PDFReportPDFPig(appPath); + if (outputStream != null) + { + _pdfReport.setOutputStream(outputStream); + GXLogging.Debug(log, "GxReportBuilderPdf outputStream: binaryWriter"); + } + } + } + +} + +namespace com.genexus.reports +{ + public class PDFReportPDFPig : PDFReportBase + { + static IGXLogger log = GXLoggerFactory.GetLogger(); + + private PdfDocumentBuilder documentBuilder; + private PdfPageBuilder pageBuilder; + private ExtendedPageSize pageSize; + + private AddedFont baseFont; + private string baseFontPath; + private string baseFontName; + private Color backColor, foreColor; + + private string barcodeType = null; + + private Dictionary documentImages; + + protected override void init(ref int gxYPage, ref int gxXPage, int pageWidth, int pageLength) + { + try + { + pageSize = ComputePageSize(leftMargin, topMargin, pageWidth, pageLength, props.getBooleanGeneralProperty(Const.MARGINS_INSIDE_BORDER, Const.DEFAULT_MARGINS_INSIDE_BORDER)); + documentBuilder = new PdfDocumentBuilder(); + + pageBuilder = pageSize.IsCustomPageSize() ? documentBuilder.AddPage(pageSize.Width, pageSize.Height) : documentBuilder.AddPage(pageSize.PageSize); + + gxXPage = (int) pageBuilder.PageSize.TopRight.X; + if (props.getBooleanGeneralProperty(Const.FIX_SAC24437, true)) + gxYPage = (int)(pageLength / GX_PAGE_SCALE_Y); + else + gxYPage = (int)(pageLength / GX_PAGE_SCALE_Y_OLD); + + } + catch (Exception e) + { + GXLogging.Error(log, "GxPrintInit failed", e); + } + } + + public PDFReportPDFPig(string appPath) : base(appPath) + { + documentBuilder = null; + documentImages = new Dictionary(); + } + + public override void GxStartPage() + { + try + { + if (pages > 0) + { + pageBuilder = pageSize.IsCustomPageSize() ? documentBuilder.AddPage(pageSize.Width, pageSize.Height) : documentBuilder.AddPage(pageSize.PageSize); + } + pages = pages + 1; + } + catch (Exception de) + { + GXLogging.Error(log, "GxStartPage error", de); + } + } + + internal override bool SetComplainceLevel(PdfConformanceLevel level) + { + return false; + } + + public override void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue, + int styleTop, int styleBottom, int styleRight, int styleLeft, int cornerRadioTL, int cornerRadioTR, int cornerRadioBL, int cornerRadioBR) + { + float penAux = (float)convertScale(pen); + float rightAux = (float)convertScale(right); + float bottomAux = (float)convertScale(bottom); + float leftAux = (float)convertScale(left); + float topAux = (float)convertScale(top); + + float x1, y1, x2, y2; + x1 = leftAux + leftMargin; + y1 = (float)pageBuilder.PageSize.TopRight.Y - bottomAux - topMargin - bottomMargin; + x2 = rightAux + leftMargin; + y2 = (float)pageBuilder.PageSize.TopRight.Y - topAux - topMargin - bottomMargin; + + GXLogging.Info(log, "Corner styling and radio are not taken into consideration because the PDFPig " + + "API provides no way to render rounded rectangles or style them"); + + if (pen > 0) + pageBuilder.SetStrokeColor( (byte)foreRed, (byte)foreGreen, (byte)foreBlue); + else + pageBuilder.SetStrokeColor( (byte)backRed, (byte)backGreen, (byte)backBlue); + + GXLogging.Info(log, "The PDFPig API provides no way of setting the line cap style"); + + if (backMode != 0) + { + pageBuilder.SetTextAndFillColor((byte)backRed, (byte)backGreen, (byte)backBlue); + pageBuilder.DrawRectangle(new PdfPoint(x1, y1), (decimal)(x2 - x1), (decimal)(y2 - y1), (decimal)penAux, true); + } + else + { + pageBuilder.DrawRectangle(new PdfPoint(x1, y1), (decimal)(x2 - x1), (decimal)(y2 - y1), (decimal) penAux, false); + } + pageBuilder.ResetColor(); + } + + public override void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue, int style) + { + try + { + float widthAux = (float)convertScale(width); + float rightAux = (float)convertScale(right); + float bottomAux = (float)convertScale(bottom); + float leftAux = (float)convertScale(left); + float topAux = (float)convertScale(top); + + GXLogging.Debug(log, "GxDrawLine -> (" + left + "," + top + ") - (" + right + "," + bottom + ") Width: " + width); + + float x1, y1, x2, y2; + + x1 = leftAux + leftMargin; + y1 = (float)pageBuilder.PageSize.TopRight.Y - bottomAux - topMargin - bottomMargin; + x2 = rightAux + leftMargin; + y2 = (float)pageBuilder.PageSize.TopRight.Y - topAux - topMargin - bottomMargin; + + pageBuilder.SetStrokeColor((byte)foreRed, (byte)foreGreen, (byte)foreBlue); + + if (style != 0) + { + GXLogging.Info(log, "The PDFPig API provides no way of creating a dashed line"); + float[] dashPattern = getDashedPattern(style); + } + + pageBuilder.DrawLine(new PdfPoint(x1, y1), new PdfPoint(x2, y2), (decimal)widthAux); + pageBuilder.ResetColor(); + } + catch (Exception e) + { + GXLogging.Error(log, "GxDrawLine error", e); + } + } + + public override void GxDrawBitMap(string bitmap, int left, int top, int right, int bottom, int aspectRatio) + { + try + { + string imageType = Path.GetExtension(bitmap).Substring(1); + + float rightAux = (float)convertScale(right); + float bottomAux = (float)convertScale(bottom); + float leftAux = (float)convertScale(left); + float topAux = (float)convertScale(top); + + float llx = leftAux + leftMargin; + float lly = (float) pageBuilder.PageSize.TopRight.Y - bottomAux - topMargin - bottomMargin; + float width; + float height; + if (aspectRatio == 0) + { + width = rightAux - leftAux; + height = bottomAux - topAux; + } + else + { + width = (rightAux - leftAux) * aspectRatio; + height = (bottomAux - topAux) * aspectRatio; + } + + PdfRectangle position = new PdfRectangle(llx, lly, llx + width, lly + height); + + AddedImage image = null; + AddedImage imageRef; + if (documentImages != null && documentImages.TryGetValue(bitmap, out imageRef)) + { + image = imageRef; + } + else + { + try + { + if (!Path.IsPathRooted(bitmap)) + { + + image = imageType == "jpeg" ? pageBuilder.AddJpeg(File.ReadAllBytes(defaultRelativePrepend + bitmap), position) : pageBuilder.AddPng(File.ReadAllBytes(defaultRelativePrepend + bitmap), position); + if (image == null) + { + bitmap = webAppDir + bitmap; + image = imageType == "jpeg" ? pageBuilder.AddJpeg(File.ReadAllBytes(bitmap), position) : pageBuilder.AddPng(File.ReadAllBytes(bitmap), position); + } + else + { + bitmap = defaultRelativePrepend + bitmap; + } + } + else + { + image = imageType == "jpeg" ? pageBuilder.AddJpeg(File.ReadAllBytes(bitmap), position) : pageBuilder.AddPng(File.ReadAllBytes(bitmap), position); + } + } + catch (Exception) + { + image = AddImageFromURL(bitmap, position); + } + if (image == null) + { + image = AddImageFromURL(bitmap, position); + } + + if (documentImages == null) + { + documentImages = new Dictionary(); + } + documentImages[bitmap] = image; + } + GXLogging.Debug(log, "GxDrawBitMap -> '" + bitmap + "' [" + left + "," + top + "] - Size: (" + (right - left) + "," + (bottom - top) + ")"); + } + catch (Exception e) + { + GXLogging.Error(log, "GxDrawBitMap error", e); + } + } + + private AddedImage AddImageFromURL(string url, PdfRectangle position) + { + AddedImage image = null; + using (HttpClient httpClient = new HttpClient()) + { + byte[] imageBytes = httpClient.GetByteArrayAsync(url).Result; + try + { + image = pageBuilder.AddJpeg(imageBytes, position); + } + catch (Exception) + { + pageBuilder.AddPng(imageBytes, position); + } + } + if (image == null) + { + GXLogging.Error(log, "GxDrawBitMap : PDFPig only supports adding jpeg or png images to documents"); + } + return image; + } + + public override void GxAttris(string fontName, int fontSize, bool fontBold, bool fontItalic, bool fontUnderline, bool fontStrikethru, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue) + { + bool isCJK = false; + bool embedFont = IsEmbeddedFont(fontName); + string originalFontName = fontName; + if (!embedFont) + { + fontName = getSubstitute(fontName); + } + + string fontSubstitute = originalFontName != fontName ? $"Original Font: {originalFontName} Substitute" : ""; + + GXLogging.Debug(log, $"GxAttris: "); + GXLogging.Debug(log, $"\\-> Font: {fontName} ({fontSize})" + + (fontBold ? " BOLD" : "") + + (fontItalic ? " ITALIC" : "") + + (fontStrikethru ? " Strike" : "")); + GXLogging.Debug(log, $"\\-> Fore ({foreRed}, {foreGreen}, {foreBlue})"); + GXLogging.Debug(log, $"\\-> Back ({backRed}, {backGreen}, {backBlue})"); + + this.fontUnderline = fontUnderline; + this.fontStrikethru = fontStrikethru; + this.fontSize = fontSize; + foreColor = Color.FromArgb(foreRed, foreGreen, foreBlue); + backColor = Color.FromArgb(backRed, backGreen, backBlue); + + backFill = backMode != 0; + + try + { + string fontNameLower = fontName.ToLower(); + if (PDFFont.isType1(fontName)) + { + foreach (string[] cjkName in Type1FontMetrics.CJKNames) + { + if (cjkName[0].ToLower().Equals(fontNameLower) || cjkName[1].ToLower().Equals(fontNameLower)) + { + string style = fontBold && fontItalic ? "BoldItalic" : fontItalic ? "Italic" : fontBold ? "Bold" : ""; + setAsianFont(fontName, style); + isCJK = true; + break; + } + } + if (!isCJK) + { + int style = (fontBold && fontItalic ? 3 : 0) + (fontItalic && !fontBold ? 2 : 0) + (fontBold && !fontItalic ? 1 : 0); + foreach (string[] base14Font in PDFFont.base14) + { + if (base14Font[0].ToLower().Equals(fontNameLower)) + { + fontName = base14Font[1 + style].Substring(1); + break; + } + } + ProcessBaseFont(fontName); + } + } + else + { + string style = (fontBold && fontItalic ? ",BoldItalic" : "") + (fontItalic && !fontBold ? ",Italic" : "") + (fontBold && !fontItalic ? ",Bold" : ""); + fontName += style; + ProcessBaseFont(fontName); + } + + if (barcode128AsImage && ( + fontName.ToLower().Contains("barcode 128") || fontName.ToLower().Contains("barcode128") + || + (!string.IsNullOrEmpty(baseFontPath) && (baseFontPath.ToLower().Contains("3of9") || baseFontPath.ToLower().Contains("3 of 9"))) + ) + ) + { + barcodeType = "barcode128"; + } + } + catch (Exception e) + { + GXLogging.Debug(log, "GxAttris DocumentException", e); + throw; + } + } + + private void ProcessBaseFont(string fontName) + { + string fontLocation = GetFontLocation(fontName); + if (string.IsNullOrEmpty(fontLocation)) + { + fontLocation = new MSPDFFontDescriptor().getTrueTypeFontLocation(fontName); + } + + if (!string.IsNullOrEmpty(fontLocation)) + { + byte[] fontBytes = File.ReadAllBytes(fontLocation); + baseFont = documentBuilder.AddTrueTypeFont(fontBytes); + } + else + { + baseFont = createType1FontFromName(fontName); + if (baseFont == null) + baseFont = documentBuilder.AddStandard14Font(Standard14Font.TimesRoman); + } + + baseFontName = fontName; + baseFontPath = fontLocation; + } + + private AddedFont createType1FontFromName(string fontName) + { + switch (fontName.ToLower()) + { + case "times-roman": + return documentBuilder.AddStandard14Font(Standard14Font.TimesRoman); + case "times-bold": + return documentBuilder.AddStandard14Font(Standard14Font.TimesBold); + case "times-italic": + return documentBuilder.AddStandard14Font(Standard14Font.TimesItalic); + case "times-bolditalic": + return documentBuilder.AddStandard14Font(Standard14Font.TimesBoldItalic); + case "helvetica": + return documentBuilder.AddStandard14Font(Standard14Font.Helvetica); + case "helvetica-bold": + return documentBuilder.AddStandard14Font(Standard14Font.HelveticaBold); + case "helvetica-oblique": + return documentBuilder.AddStandard14Font(Standard14Font.HelveticaOblique); + case "helvetica-boldoblique": + return documentBuilder.AddStandard14Font(Standard14Font.HelveticaBoldOblique); + case "courier": + return documentBuilder.AddStandard14Font(Standard14Font.Courier); + case "courier-bold": + return documentBuilder.AddStandard14Font(Standard14Font.CourierBold); + case "courier-oblique": + return documentBuilder.AddStandard14Font(Standard14Font.CourierOblique); + case "courier-boldoblique": + return documentBuilder.AddStandard14Font(Standard14Font.CourierBoldOblique); + case "symbol": + return documentBuilder.AddStandard14Font(Standard14Font.Symbol); + case "zapfdingbats": + return documentBuilder.AddStandard14Font(Standard14Font.ZapfDingbats); + default: + return null; + } + } + + public override void setAsianFont(string fontName, string style) + { + try + { + string fontPath = GetFontLocation(fontName); + if (string.IsNullOrEmpty(fontPath)) + { + MSPDFFontDescriptor fontDescriptor = new MSPDFFontDescriptor(); + fontPath = fontDescriptor.getTrueTypeFontLocation(fontName); + } + byte[] fontBytes = File.ReadAllBytes(fontPath); + baseFont = documentBuilder.AddTrueTypeFont(fontBytes); + } + catch (IOException de) + { + GXLogging.Debug(log, "setAsianFont error", de); + } + } + + public override void GxDrawText(string sTxt, int left, int top, int right, int bottom, int align, int htmlformat, int border, int valign) + { + bool printRectangle = false; + if (props.getBooleanGeneralProperty(Const.BACK_FILL_IN_CONTROLS, true)) + printRectangle = true; + + if (printRectangle && (border == 1 || backFill)) + { + GxDrawRect(left, top, right, bottom, border, foreColor.R, foreColor.G, foreColor.B, backFill ? 1 : 0, backColor.R, backColor.G, backColor.B, 0, 0); + } + + sTxt = RTrim(sTxt); + + AddedFont font = createType1FontFromName(baseFontName); + if (font == null) + { + try + { + byte[] fontBytes = File.ReadAllBytes(baseFontPath); + font = documentBuilder.AddTrueTypeFont(fontBytes); + } + catch + { + font = baseFont; + } + } + + float captionHeight = CalculateFontCaptionHeight(baseFontPath, fontSize); + float rectangleWidth = MeasureTextWidth(sTxt, baseFontPath, fontSize); + float lineHeight = MeasureTextHeight(sTxt, baseFontPath, fontSize); + float textBlockHeight = (float)convertScale(bottom - top); + int linesCount = (int)(textBlockHeight / lineHeight); + int bottomOri = bottom; + int topOri = top; + + if (linesCount >= 2 && !((align & 16) == 16) && htmlformat != 1) + { + if (valign == (int)VerticalAlign.TOP) + bottom = top + (int)reconvertScale(lineHeight); + else if (valign == (int)VerticalAlign.BOTTOM) + top = bottom - (int)reconvertScale(lineHeight); + } + + float bottomAux = (float)convertScale(bottom) - ((float)convertScale(bottom - top)) / 2; + float topAux = (float)convertScale(top) + ((float)convertScale(bottom - top)) / 2; + + float startHeight = bottomAux - topAux - captionHeight; + + float leftAux = (float)convertScale(left); + float rightAux = (float)convertScale(right); + int alignment = align & 3; + bool autoResize = (align & 256) == 256; + + if (htmlformat == 1) + { + GXLogging.Error(log, "GxDrawText: PDFPig report implementation does not support rendering HTML content into PDF reports"); + } + + if (barcodeType != null) + { + PdfRectangle barcodeRectangle; + switch (alignment) + { + case 1: // Center Alignment + barcodeRectangle = new PdfRectangle( + (leftAux + rightAux) / 2 + leftMargin - rectangleWidth / 2, + pageBuilder.PageSize.TopRight.Y - (float)convertScale(bottom) - topMargin - bottomMargin, + (leftAux + rightAux) / 2 + leftMargin + rectangleWidth / 2, + pageBuilder.PageSize.TopRight.Y - (float)convertScale(top) - topMargin - bottomMargin + ); + break; + case 2: // Right Alignment + barcodeRectangle = new PdfRectangle( + rightAux + leftMargin - rectangleWidth, + pageBuilder.PageSize.TopRight.Y - (float)convertScale(bottom) - topMargin - bottomMargin, + rightAux + leftMargin, + pageBuilder.PageSize.TopRight.Y - (float)convertScale(top) - topMargin - bottomMargin + ); + break; + default: // Left Alignment (Corresponds to alignment = 0 but used as default) + barcodeRectangle = new PdfRectangle( + leftAux + leftMargin, + pageBuilder.PageSize.TopRight.Y - (float)convertScale(bottom) - topMargin - bottomMargin, + leftAux + leftMargin + rectangleWidth, + pageBuilder.PageSize.TopRight.Y - (float)convertScale(top) - topMargin - bottomMargin + ); + break; + + } + Image barcodeImage = CreateBarcodeImage((float)barcodeRectangle.Width, (float)barcodeRectangle.Height, baseFontPath, sTxt); + using (MemoryStream ms = new MemoryStream()) + { + barcodeImage.Save(ms, ImageFormat.Png); + pageBuilder.AddPng(ms.ToArray(), barcodeRectangle); + } + return; + } + + if (backFill) + { + PdfPoint rectangleStartingPoint; + switch (alignment) + { + case 1: // Center Alignment + rectangleStartingPoint = new PdfPoint( + (leftAux + rightAux) / 2 + leftMargin - rectangleWidth / 2, + pageBuilder.PageSize.TopRight.Y - bottomAux - topMargin - bottomMargin + ); + break; + case 2: // Right Alignment + rectangleStartingPoint = new PdfPoint( + rightAux + leftMargin - rectangleWidth, + pageBuilder.PageSize.TopRight.Y - bottomAux - topMargin - bottomMargin + ); + break; + default: // Left Alignment (Corresponds to alignment = 0 but used as default) + rectangleStartingPoint = new PdfPoint( + leftAux + leftMargin, + pageBuilder.PageSize.TopRight.Y - bottomAux - topMargin - bottomMargin + ); + break; + + } + + decimal width = (decimal)(((leftAux + rightAux) / 2 + leftMargin + rectangleWidth / 2) - ((leftAux + rightAux) / 2 + leftMargin - rectangleWidth / 2)); + decimal height = (decimal)((pageBuilder.PageSize.TopRight.Y - topAux - topMargin - bottomMargin) - (pageBuilder.PageSize.TopRight.Y - bottomAux - topMargin - bottomMargin)); + + pageBuilder.SetTextAndFillColor(backColor.R, backColor.G, backColor.B); + pageBuilder.DrawRectangle(rectangleStartingPoint, width, height, 1, true); + } + + pageBuilder.SetTextAndFillColor(foreColor.R, foreColor.G, foreColor.B); + + if (fontUnderline) + { + float underlineSeparation = lineHeight / 5; + int underlineHeight = (int)underlineSeparation + (int)(underlineSeparation / 4); + + PdfPoint underlineStartingPoint; + PdfPoint underlineEndingPoint; + switch (alignment) + { + case 1: // Center Alignment + underlineStartingPoint = new PdfPoint( + (leftAux + rightAux) / 2 + leftMargin - rectangleWidth / 2, + pageBuilder.PageSize.TopRight.Y - bottomAux - topMargin - bottomMargin + startHeight + ); + underlineEndingPoint = new PdfPoint( + (leftAux + rightAux) / 2 + leftMargin + rectangleWidth / 2, + pageBuilder.PageSize.TopRight.Y - bottomAux - topMargin - bottomMargin + startHeight + ); + break; + case 2: // Right Alignment + underlineStartingPoint = new PdfPoint( + rightAux + leftMargin - rectangleWidth, + pageBuilder.PageSize.TopRight.Y - bottomAux - topMargin - bottomMargin + startHeight + ); + underlineEndingPoint = new PdfPoint( + rightAux + leftMargin, + pageBuilder.PageSize.TopRight.Y - bottomAux - topMargin - bottomMargin + startHeight + ); + break; + default: // Left Alignment (Corresponds to alignment = 0 but used as default) + underlineStartingPoint = new PdfPoint( + leftAux + leftMargin, + pageBuilder.PageSize.TopRight.Y - bottomAux - topMargin - bottomMargin + startHeight + ); + underlineEndingPoint = new PdfPoint( + leftAux + leftMargin + rectangleWidth, + pageBuilder.PageSize.TopRight.Y - bottomAux - topMargin - bottomMargin + startHeight + ); + break; + + } + + pageBuilder.DrawLine(underlineStartingPoint, underlineEndingPoint, underlineHeight); + } + + if (fontStrikethru) + { + float strikethruSeparation = (float)(lineHeight / 1.5); + PdfPoint strikethruStartingPoint; + PdfPoint strikethruEndingPoint; + switch (alignment) + { + case 1: // Center Alignment + strikethruStartingPoint = new PdfPoint( + (leftAux + rightAux) / 2 + leftMargin - rectangleWidth / 2, + pageBuilder.PageSize.TopRight.Y - bottomAux - topMargin - bottomMargin + startHeight + strikethruSeparation + ); + strikethruEndingPoint = new PdfPoint( + (leftAux + rightAux) / 2 + leftMargin + rectangleWidth / 2, + pageBuilder.PageSize.TopRight.Y - bottomAux - topMargin - bottomMargin + startHeight + strikethruSeparation + ); + break; + case 2: // Right Alignment + strikethruStartingPoint = new PdfPoint( + rightAux + leftMargin - rectangleWidth, + pageBuilder.PageSize.TopRight.Y - bottomAux - topMargin - bottomMargin + startHeight + strikethruSeparation + ); + strikethruEndingPoint = new PdfPoint( + rightAux + leftMargin, + pageBuilder.PageSize.TopRight.Y - bottomAux - topMargin - bottomMargin + startHeight + strikethruSeparation + ); + break; + default: // Left Alignment (Corresponds to alignment = 0 but used as default) + strikethruStartingPoint = new PdfPoint( + leftAux + leftMargin, + pageBuilder.PageSize.TopRight.Y - bottomAux - topMargin - bottomMargin + startHeight + strikethruSeparation + ); + strikethruEndingPoint = new PdfPoint( + leftAux + leftMargin + rectangleWidth, + pageBuilder.PageSize.TopRight.Y - bottomAux - topMargin - bottomMargin + startHeight + strikethruSeparation + ); + break; + + } + pageBuilder.DrawLine(strikethruStartingPoint, strikethruEndingPoint, (decimal)convertScale(fontSize) / 10); + } + + float textBlockWidth = rightAux - leftAux; + float TxtWidth = MeasureTextWidth(sTxt, baseFontPath, fontSize); + bool justified = (alignment == 3) && textBlockWidth < TxtWidth; + bool wrap = ((align & 16) == 16); + + if (wrap || justified) + { + bottomAux = (float)convertScale(bottomOri); + topAux = (float)convertScale(topOri); + + float llx = leftAux + leftMargin; + float lly = (float)(pageBuilder.PageSize.TopRight.Y - bottomAux - topMargin - bottomMargin); + float urx = rightAux + leftMargin; + float ury = (float)(pageBuilder.PageSize.TopRight.Y - topAux - topMargin - bottomMargin); + + ShowWrappedTextAligned(font, alignment, sTxt, llx, lly, urx, ury); + } + else + { + if (!autoResize) + { + string newsTxt = sTxt; + while (TxtWidth > textBlockWidth && (newsTxt.Length - 1 >= 0)) + { + sTxt = newsTxt; + newsTxt = newsTxt.Substring(0, newsTxt.Length - 1); + TxtWidth = MeasureTextWidth(sTxt, baseFontPath, fontSize); + } + } + switch (alignment) + { + case 1: // Center Alignment + ShowTextAligned(font, alignment, sTxt, ((leftAux + rightAux) / 2) + leftMargin, (float)(pageBuilder.PageSize.TopRight.Y - bottomAux - topMargin - bottomMargin)); + break; + case 2: // Right Alignment + ShowTextAligned(font, alignment, sTxt, rightAux + leftMargin, (float)(pageBuilder.PageSize.TopRight.Y - bottomAux - topMargin - bottomMargin)); + break; + case 0: // Left Alignment + case 3: // Justified, only one text line + ShowTextAligned(font, alignment, sTxt, leftAux + leftMargin, (float)(pageBuilder.PageSize.TopRight.Y - bottomAux - topMargin - bottomMargin)); + break; + } + } + } + + public Image CreateBarcodeImage(float width, float height, string fontPath, string text) + { + PrivateFontCollection fontCollection = new PrivateFontCollection(); + fontCollection.AddFontFile(fontPath); + FontFamily fontFamily = fontCollection.Families[0]; + + int bitmapWidth = (int)Math.Ceiling(width); + int bitmapHeight = (int)Math.Ceiling(height); + + float fontSize = Math.Min(width, height); + Font font; + SizeF textSize; + + using (Bitmap tempBitmap = new Bitmap(1, 1)) + { + using (Graphics tempGraphics = Graphics.FromImage(tempBitmap)) + { + do + { + font = new Font(fontFamily, fontSize, GraphicsUnit.Pixel); + textSize = tempGraphics.MeasureString(text, font); + fontSize--; + } while (textSize.Width > width || textSize.Height > height); + } + } + + Bitmap bitmap = new Bitmap(bitmapWidth, bitmapHeight); + bitmap.SetResolution(600, 600); + using (Graphics graphics = Graphics.FromImage(bitmap)) + { + graphics.Clear(Color.White); + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; + graphics.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit; + StringFormat format = new StringFormat + { + Alignment = StringAlignment.Center, + LineAlignment = StringAlignment.Center + }; + graphics.DrawString(text, font, Brushes.Black, new RectangleF(0, 0, width, height), format); + } + font.Dispose(); + fontCollection.Dispose(); + + return bitmap; + } + + private float MeasureTextWidth(string text, string fontPath, float fontSize) + { + Font font; + if (string.IsNullOrEmpty(fontPath)) + { + font = new Font("Times New Roman", fontSize, GraphicsUnit.Point); + } + else + { + PrivateFontCollection pfc = new PrivateFontCollection(); + pfc.AddFontFile(fontPath); + font = new Font(pfc.Families[0], fontSize, GraphicsUnit.Point); + } + + using (font) + { + using (var fakeImage = new Bitmap(1, 1)) + { + using (var graphics = Graphics.FromImage(fakeImage)) + { + graphics.PageUnit = GraphicsUnit.Point; + graphics.TextRenderingHint = TextRenderingHint.AntiAlias; + var sizeF = graphics.MeasureString(text, font); + return sizeF.Width; + } + } + } + } + + private float MeasureTextHeight(string text, string fontPath, float fontSize) + { + Font font; + if (string.IsNullOrEmpty(fontPath)) + { + font = new Font("Times New Roman", fontSize, GraphicsUnit.Point); + } + else + { + PrivateFontCollection pfc = new PrivateFontCollection(); + pfc.AddFontFile(fontPath); + font = new Font(pfc.Families[0], fontSize, GraphicsUnit.Point); + } + + using (font) + { + using (var fakeImage = new Bitmap(1, 1)) + { + using (var graphics = Graphics.FromImage(fakeImage)) + { + graphics.PageUnit = GraphicsUnit.Point; + graphics.TextRenderingHint = TextRenderingHint.AntiAlias; + var sizeF = graphics.MeasureString(text, font); + return sizeF.Height; + } + } + } + } + + private float CalculateFontCaptionHeight(string fontPath, float fontSize, FontStyle fontStyle = FontStyle.Regular) + { + Font font; + if (string.IsNullOrEmpty(fontPath)) + { + font = new Font("Times New Roman", fontSize, GraphicsUnit.Point); + } + else + { + PrivateFontCollection pfc = new PrivateFontCollection(); + pfc.AddFontFile(fontPath); + font = new Font(pfc.Families[0], fontSize, GraphicsUnit.Point); + } + using (font) + { + FontFamily ff = font.FontFamily; + + float ascent = ff.GetCellAscent(fontStyle); + float descent = ff.GetCellDescent(fontStyle); + float lineSpacing = ff.GetLineSpacing(fontStyle); + + float height = fontSize * (ascent + descent) / ff.GetEmHeight(fontStyle); + + return height; + } + } + + private void ShowTextAligned(AddedFont font, int alignment, string text, float x, float y) + { + try + { + float textWidth = MeasureTextWidth(text, baseFontPath, fontSize); + switch (alignment) + { + case 0: // Left-aligned + case 3: // Justified, only one text line + break; + case 1: // Center-aligned + x = x - textWidth / 2; + break; + case 2: // Right-aligned + x = x - textWidth; + break; + } + y = (float)(y - fontSize * 0.5); + pageBuilder.AddText(text, fontSize, new PdfPoint(x, y), font); + } + catch (IOException ioe) + { + GXLogging.Error(log, "failed to draw aligned text: ", ioe); + } + } + + private void ShowWrappedTextAligned(AddedFont font, int alignment, string text, float llx, float lly, float urx, float ury) + { + try + { + List lines = new List(); + string[] words = text.Split(' '); + StringBuilder currentLine = new StringBuilder(); + foreach (string word in words) + { + float currentLineWidth = MeasureTextWidth(currentLine + " " + word, baseFontPath, fontSize); + if (currentLineWidth < urx - llx) + { + if (currentLine.Length > 0) + { + currentLine.Append(" "); + } + currentLine.Append(word); + } + else + { + lines.Add(currentLine.ToString()); + currentLine.Clear(); + currentLine.Append(word); + } + } + lines.Add(currentLine.ToString()); + + float leading = (float)(lines.Count == 1 ? fontSize : 1.2 * fontSize); + float totalTextHeight = fontSize * lines.Count + leading * (lines.Count - 1); + float startY = lines.Count == 1 ? lly + (ury - lly - totalTextHeight) / 2 : lly + (ury - lly - totalTextHeight) / 2 + (lines.Count - 1) * (fontSize + leading); + + foreach (string line in lines) + { + float lineWidth = MeasureTextWidth(line, baseFontPath, fontSize); + float startX; + + switch (alignment) + { + case 1: // Center-aligned + startX = llx + (urx - llx - lineWidth) / 2; + break; + case 2: // Right-aligned + startX = urx - lineWidth; + break; + default: // Left-aligned & Justified, only one text line + startX = llx; + break; + } + + pageBuilder.AddText(line, fontSize, new PdfPoint(startX, startY), font); + startY -= leading; + } + } + catch (IOException ioe) + { + GXLogging.Error(log, "Failed to draw wrapped text", ioe); + } + } + + private ExtendedPageSize ComputePageSize(float leftMargin, float topMargin, int width, int length, bool marginsInsideBorder) + { + if ((leftMargin == 0 && topMargin == 0) || marginsInsideBorder) + { + if (length == 23818 && width == 16834) + return new ExtendedPageSize(PageSize.A3); + else if (length == 16834 && width == 11909) + return new ExtendedPageSize(PageSize.A4); + else if (length == 11909 && width == 8395) + return new ExtendedPageSize(PageSize.A5); + else if (length == 15120 && width == 10440) + return new ExtendedPageSize(PageSize.Executive); + else if (length == 20160 && width == 12240) + return new ExtendedPageSize(PageSize.Legal); + else if (length == 15840 && width == 12240) + return new ExtendedPageSize(PageSize.Letter); + else + return new ExtendedPageSize((width / PAGE_SCALE_X), (length / PAGE_SCALE_Y)); + } + return new ExtendedPageSize((width / PAGE_SCALE_X) + leftMargin, (length / PAGE_SCALE_Y) + topMargin); + + } + + public override void GxEndDocument() + { + if (pages == 0) + { + GxStartPage(); + } + + GXLogging.Info(log, "The PDFPig API provides no way of setting the number of copies and the duplex value for the viewer preferences"); + + GXLogging.Info(log, "The PDFPig API provides no way of embedding javascript into the document"); + + try + { + byte[] documentBytes = documentBuilder.Build(); + outputStream.Write(documentBytes, 0, documentBytes.Length); + } + catch (IOException e) + { + GXLogging.Debug(log,"GxEndDocument: failed to write document to the output stream", e); + } + + string serverPrinting = props.getGeneralProperty(Const.SERVER_PRINTING); + bool printingScript = (outputType == Const.OUTPUT_PRINTER || outputType == Const.OUTPUT_STREAM_PRINTER) && serverPrinting.Equals("false"); + switch (outputType) + { + case Const.OUTPUT_SCREEN: + try + { + outputStream.Close(); + GXLogging.Debug(log, "GxEndDocument OUTPUT_SCREEN outputstream length" + outputStream.ToString().Length); + } + catch (IOException e) + { + GXLogging.Error(log, "GxEndDocument OUTPUT_SCREEN error", e); + } + try { showReport(docName, modal); } + catch (Exception) { } + break; + + case Const.OUTPUT_PRINTER: + try { outputStream.Close(); } + catch (IOException) { } + try + { + if (!serverPrinting.Equals("false") && !printingScript) + { + printReport(docName, this.printerOutputMode == 0, printerSettings.getProperty(form, Const.PRINTER)); + } + } + catch (Exception) { } + break; + + case Const.OUTPUT_FILE: + try + { + outputStream.Close(); + GXLogging.Debug(log, "GxEndDocument OUTPUT_FILE outputstream length" + outputStream.ToString().Length); + } + catch (IOException e) + { + GXLogging.Error(log, "GxEndDocument OUTPUT_FILE error", e); + } + break; + + case Const.OUTPUT_STREAM: + case Const.OUTPUT_STREAM_PRINTER: + default: break; + } + outputStream = null; + } + + } + + internal class ExtendedPageSize + { + internal double Width; + internal double Height; + internal PageSize PageSize; + internal ExtendedPageSize(double w, double h) + { + Width = w; + Height = h; + PageSize = PageSize.Custom; + } + internal ExtendedPageSize(PageSize pageSize) + { + PageSize = pageSize; + } + internal bool IsCustomPageSize() + { + return PageSize == PageSize.Custom; + } + } +} diff --git a/dotnet/src/dotnetcore/GxSearch/GxSearch.csproj b/dotnet/src/dotnetcore/GxSearch/GxSearch.csproj index 0b3f8ae7d..8588e6c64 100644 --- a/dotnet/src/dotnetcore/GxSearch/GxSearch.csproj +++ b/dotnet/src/dotnetcore/GxSearch/GxSearch.csproj @@ -24,7 +24,7 @@ - + diff --git a/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs b/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs index 9df552904..088c2f917 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs @@ -437,6 +437,7 @@ public class GxReportUtils #if NETCORE const string PDF_LIBRARY_ITEXT8 = "ITEXT8"; + const string PDF_LIBRARY_PDFPIG = "PDFPIG"; #endif static public IReportHandler GetPrinter( int outputType, string path, Stream reportOutputStream) { @@ -470,7 +471,13 @@ static public IReportHandler GetPrinter( int outputType, string path, Stream rep Type classType = assem.GetType( "GeneXus.Printer.GxReportBuilderPdf", false, true); reportHandler = (IReportHandler) Activator.CreateInstance(classType,new Object[]{path, reportOutputStream}); #else - string reportBuidler = Preferences.PdfReportLibrary().Equals(PDF_LIBRARY_ITEXT8, StringComparison.OrdinalIgnoreCase) ? "GxReportBuilderPdf8" : "GxReportBuilderPdf"; + string reportBuidler; + if (Preferences.PdfReportLibrary().Equals(PDF_LIBRARY_ITEXT8, StringComparison.OrdinalIgnoreCase)) + reportBuidler = "GxReportBuilderPdf8"; + else if (Preferences.PdfReportLibrary().Equals(PDF_LIBRARY_PDFPIG, StringComparison.OrdinalIgnoreCase)) + reportBuidler = "GxReportBuilderPDFPig"; + else + reportBuidler = "GxReportBuilderPdf"; reportHandler = (IReportHandler)(ClassLoader.FindInstance("GxPdfReportsCS", "GeneXus.Printer", reportBuidler, new Object[] { path, reportOutputStream }, null)); #endif } diff --git a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs index 265d865c1..ce88fa4ec 100644 --- a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs +++ b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs @@ -26,11 +26,11 @@ internal enum VerticalAlign BOTTOM = 2, } - public abstract class PDFReportItextBase : IReportHandler + public abstract class PDFReportBase : IReportHandler { protected int lineHeight, pageLines; - static IGXLogger log = GXLoggerFactory.GetLogger(); + static IGXLogger log = GXLoggerFactory.GetLogger(); protected bool fontUnderline; protected bool fontStrikethru; @@ -227,7 +227,7 @@ public static void showReport(String filename1, bool modal) } private static char alternateSeparator = Path.DirectorySeparatorChar == '/' ? '\\' : '/'; - public PDFReportItextBase(String appPath) + public PDFReportBase(String appPath) { try { @@ -894,6 +894,11 @@ protected float reconvertScale(float value) return result; } + bool PageHeightExceeded(float bottomAux, float drawingPageHeight) + { + return bottomAux > drawingPageHeight; + } + internal abstract bool SetComplainceLevel(PdfConformanceLevel level); } diff --git a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext4.cs b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext4.cs index c84601f6b..bfa28eb7f 100644 --- a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext4.cs +++ b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext4.cs @@ -13,7 +13,7 @@ namespace com.genexus.reports { - public class PDFReportItextSharp : PDFReportItextBase + public class PDFReportItextSharp : PDFReportBase { static IGXLogger log = GXLoggerFactory.GetLogger(); diff --git a/dotnet/src/dotnetframework/GxPdfReportsCS/PdfReportInterface.cs b/dotnet/src/dotnetframework/GxPdfReportsCS/PdfReportInterface.cs index 2081bb475..cd4c73ad3 100644 --- a/dotnet/src/dotnetframework/GxPdfReportsCS/PdfReportInterface.cs +++ b/dotnet/src/dotnetframework/GxPdfReportsCS/PdfReportInterface.cs @@ -6,15 +6,14 @@ namespace GeneXus.Printer public class GxReportBuilderPdf : IReportHandler { static IGXLogger log = GXLoggerFactory.GetLogger(); - string _appPath; + protected string _appPath; protected IReportHandler _pdfReport; public GxReportBuilderPdf(string appPath, Stream outputStream) { _appPath = appPath; - { _pdfReport = new com.genexus.reports.PDFReportItextSharp(appPath); - } + if (outputStream != null) { @@ -22,7 +21,7 @@ public GxReportBuilderPdf(string appPath, Stream outputStream) GXLogging.Debug(log,"GxReportBuilderPdf outputStream: binaryWriter"); } } - public GxReportBuilderPdf() : this( "", null) + public GxReportBuilderPdf() { } public bool GxPrintInit(string output, ref int gxXPage, ref int gxYPage, string iniFile, string form, string printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) diff --git a/dotnet/test/DotNetPdfTest/DotNetPDFUnitTest.csproj b/dotnet/test/DotNetPdfTest/DotNetPDFUnitTest.csproj index 970f681b1..1b5cd1bed 100644 --- a/dotnet/test/DotNetPdfTest/DotNetPDFUnitTest.csproj +++ b/dotnet/test/DotNetPdfTest/DotNetPDFUnitTest.csproj @@ -18,6 +18,7 @@ + From 48cbde16fa3ae2176bf7b32f9152054dd485f43a Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Mon, 11 Mar 2024 14:55:08 -0300 Subject: [PATCH 117/164] Improve the routing mechanism for GAM services (#974) * Improve the routing mechanism for GAM services using the appropriate namespace for each service. * Refactored minor improvements * Store names in HttpHelper.GamServicesInternalName without extension. --- .../Middleware/HandlerFactory.cs | 31 ++--- .../GxClasses/Helpers/HttpHelper.cs | 25 +++- .../GxClasses/Middleware/HandlerFactory.cs | 119 +++++++++--------- 3 files changed, 92 insertions(+), 83 deletions(-) diff --git a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/HandlerFactory.cs b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/HandlerFactory.cs index d9eb0b14a..e71b29279 100644 --- a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/HandlerFactory.cs +++ b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/HandlerFactory.cs @@ -37,25 +37,6 @@ public class HandlerFactory {"gxoauthuserinfo",typeof(GXOAuthUserInfo)}, {"gxoauthaccesstoken",typeof(GXOAuthAccessToken)}, {"gxmulticall",typeof(GXMultiCall)}}; - static Dictionary _aspxRewrite = new Dictionary(){ - {"oauth/access_token","gxoauthaccesstoken.aspx"}, - {"oauth/logout","gxoauthlogout.aspx"}, - {"oauth/userinfo","gxoauthuserinfo.aspx"}, - {"oauth/gam/signin","agamextauthinput.aspx"}, - {"oauth/gam/callback","agamextauthinput.aspx"}, - {"oauth/gam/access_token","agamoauth20getaccesstoken.aspx"}, - {"oauth/gam/userinfo","agamoauth20getuserinfo.aspx"}, - {"oauth/gam/signout","agamextauthinput.aspx"}, - {"saml/gam/signin","Saml2/SignIn"}, - {"saml/gam/callback","gamexternalauthenticationinputsaml20_ws.aspx"}, - {"saml/gam/signout","Saml2/Logout"}, - {"oauth/requesttokenservice","agamstsauthappgetaccesstoken.aspx"}, - {"oauth/queryaccesstoken","agamstsauthappvalidaccesstoken.aspx"}, - {"oauth/gam/v2.0/access_token","agamoauth20getaccesstoken_v20.aspx"}, - {"oauth/gam/v2.0/userinfo","agamoauth20getuserinfo_v20.aspx"}, - {"oauth/gam/v2.0/requesttokenanduserinfo","aGAMSSORestRequestTokenAndUserInfo_v20.aspx"}}; - private const string QUERYVIEWER_NAMESPACE = "QueryViewer.Services"; - private const string GXFLOW_NSPACE = "GXflow.Programs"; private static List GxNamespaces; public HandlerFactory() @@ -122,9 +103,9 @@ private static string ObjectUrl(string requestPath, string basePath) } lastSegment = CleanUploadUrlSuffix(lastSegment.TrimStart('/').ToLower()); GXLogging.Debug(log, "ObjectUrl:", lastSegment); - if (_aspxRewrite.ContainsKey(lastSegment)) + if (HttpHelper.GAMServices.ContainsKey(lastSegment)) { - return _aspxRewrite[lastSegment]; + return HttpHelper.GAMServices[lastSegment]; } return lastSegment; } @@ -167,11 +148,15 @@ public IHttpHandler GetHandler(HttpContext context, string requestType, string u string className; if (cname.StartsWith("agxpl_", StringComparison.OrdinalIgnoreCase) || cname.Equals("gxqueryviewerforsd", StringComparison.OrdinalIgnoreCase)) { - className = $"{QUERYVIEWER_NAMESPACE}.{cname}"; + className = $"{HttpHelper.QUERYVIEWER_NAMESPACE}.{cname}"; } else if (Preferences.GxpmEnabled && (cname.StartsWith("awf", StringComparison.OrdinalIgnoreCase) || cname.StartsWith("wf", StringComparison.OrdinalIgnoreCase) || cname.StartsWith("apwf", StringComparison.OrdinalIgnoreCase))) { - className = $"{GXFLOW_NSPACE}.{cname}"; + className = $"{HttpHelper.GXFLOW_NSPACE}.{cname}"; + } + else if (HttpHelper.GamServicesInternalName.Contains(cname)) + { + className = $"{HttpHelper.GAM_NSPACE}.{cname}"; } else { diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs index a0e94c333..dc282f196 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs @@ -27,6 +27,7 @@ using Microsoft.Net.Http.Headers; using System.Net.Http; using System.Globalization; +using System.Linq; namespace GeneXus.Http { @@ -72,10 +73,32 @@ public class WrappedJsonError [DataMember(Name = "error")] public HttpJsonError Error; } - public class HttpHelper { static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + + internal static Dictionary GAMServices = new Dictionary(){ + {"oauth/access_token","gxoauthaccesstoken.aspx"}, + {"oauth/logout","gxoauthlogout.aspx"}, + {"oauth/userinfo","gxoauthuserinfo.aspx"}, + {"oauth/gam/signin","agamextauthinput.aspx"}, + {"oauth/gam/callback","agamextauthinput.aspx"}, + {"oauth/gam/access_token","agamoauth20getaccesstoken.aspx"}, + {"oauth/gam/userinfo","agamoauth20getuserinfo.aspx"}, + {"oauth/gam/signout","agamextauthinput.aspx"}, + {"saml/gam/signin","Saml2/SignIn"}, + {"saml/gam/callback","gamexternalauthenticationinputsaml20_ws.aspx"}, + {"saml/gam/signout","Saml2/Logout"}, + {"oauth/requesttokenservice","agamstsauthappgetaccesstoken.aspx"}, + {"oauth/queryaccesstoken","agamstsauthappvalidaccesstoken.aspx"}, + {"oauth/gam/v2.0/access_token","agamoauth20getaccesstoken_v20.aspx"}, + {"oauth/gam/v2.0/userinfo","agamoauth20getuserinfo_v20.aspx"}, + {"oauth/gam/v2.0/requesttokenanduserinfo","agamssorequesttokenanduserinfo_v20.aspx"}}; + internal static HashSet GamServicesInternalName = new HashSet(GAMServices.Values.Select(value => value.Replace(ASPX, string.Empty))); + internal const string QUERYVIEWER_NAMESPACE = "QueryViewer.Services"; + internal const string GXFLOW_NSPACE = "GXflow.Programs"; + internal const string GAM_NSPACE = "GeneXus.Security.API"; + /* * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control * Specifying no-cache or max-age=0 indicates that diff --git a/dotnet/src/dotnetframework/GxClasses/Middleware/HandlerFactory.cs b/dotnet/src/dotnetframework/GxClasses/Middleware/HandlerFactory.cs index ae00618d6..76d1410bb 100644 --- a/dotnet/src/dotnetframework/GxClasses/Middleware/HandlerFactory.cs +++ b/dotnet/src/dotnetframework/GxClasses/Middleware/HandlerFactory.cs @@ -67,88 +67,89 @@ public IHttpHandler GetHandler(HttpContext context, string requestType, string u string relativeURL = context.Request.AppRelativeCurrentExecutionFilePath; string fname = relativeURL.Substring(relativeURL.LastIndexOf('~') + 2); - String cname1 = (fname.Contains(".")) ? fname.Substring(0, fname.LastIndexOf('.')) : fname; + string cname1 = (fname.Contains(".")) ? fname.Substring(0, fname.LastIndexOf('.')) : fname; string cname0 = cname1.ToLower(); - string actualPath = ""; - + string mainNamespace; + string assemblyName, cname; + string actualPath; if (cname0 == "gxoauthlogout") { - return new GeneXus.Http.GXOAuthLogout(); + return new GXOAuthLogout(); } else if (cname0 == "gxoauthuserinfo") { - return new GeneXus.Http.GXOAuthUserInfo(); + return new GXOAuthUserInfo(); } else if (cname0 == "gxoauthaccesstoken") { - return new GeneXus.Http.GXOAuthAccessToken(); + return new GXOAuthAccessToken(); } else if (cname0 == "gxmulticall") { - return new GeneXus.Http.GXMultiCall(); + return new GXMultiCall(); } - string assemblyName, cname; - if (GXAPIModule.serviceInPath(pathTranslated, actualPath: out actualPath)) + else if (HttpHelper.GamServicesInternalName.Contains(cname0)) + { + mainNamespace = HttpHelper.GAM_NSPACE; + } + else { - string nspace; - Config.GetValueOf("AppMainNamespace", out nspace); - String objClass = GXAPIModule.servicesBase[actualPath]; - // - String objectName = GetObjFromPath(cname0, actualPath); - String objectNameUp = GetObjFromPath(cname1, actualPath); - // - Dictionary routeParms; - if (GXAPIModule.servicesMapData.ContainsKey(actualPath)) + if (!Config.GetValueOf("AppMainNamespace", out mainNamespace)) + mainNamespace = "GeneXus.Programs."; + + if (GXAPIModule.serviceInPath(pathTranslated, actualPath: out actualPath)) { - bool IsServiceCall = GetSMap(actualPath, objectName, objectNameUp, requestType, out string mapName, out string mapRegExp, out routeParms); - if (IsServiceCall) + string nspace; + Config.GetValueOf("AppMainNamespace", out nspace); + string objClass = GXAPIModule.servicesBase[actualPath]; + // + string objectName = GetObjFromPath(cname0, actualPath); + string objectNameUp = GetObjFromPath(cname1, actualPath); + // + Dictionary routeParms; + if (GXAPIModule.servicesMapData.ContainsKey(actualPath)) { - if (!String.IsNullOrEmpty(mapName) && GXAPIModule.servicesMap[actualPath].TryGetValue(mapName, out SingleMap value)) + bool IsServiceCall = GetSMap(actualPath, objectName, objectNameUp, requestType, out string mapName, out string mapRegExp, out routeParms); + if (IsServiceCall) { - String tmpController = objClass; - String asssemblycontroller = tmpController; - if (objClass.Contains("\\")) + if (!string.IsNullOrEmpty(mapName) && GXAPIModule.servicesMap[actualPath].TryGetValue(mapName, out SingleMap value)) { - tmpController = objClass.Substring(objClass.LastIndexOf("\\") + 1); - String addNspace = objClass.Substring(0, objClass.LastIndexOf("\\")).Replace("\\", "."); - asssemblycontroller = addNspace + "." + tmpController; - nspace += "." + addNspace; + string tmpController = objClass; + string asssemblycontroller = tmpController; + if (objClass.Contains("\\")) + { + tmpController = objClass.Substring(objClass.LastIndexOf("\\") + 1); + string addNspace = objClass.Substring(0, objClass.LastIndexOf("\\")).Replace("\\", "."); + asssemblycontroller = addNspace + "." + tmpController; + nspace += "." + addNspace; + } + GxContext gxContext = GxContext.CreateDefaultInstance(); + object handler = ClassLoader.FindInstance(asssemblycontroller, nspace, tmpController, new Object[] { gxContext }, null); + + gxContext.HttpContext = context; + GxRestWrapper restWrapper = new Application.GxRestWrapper(handler as GXBaseObject, context, gxContext, value.ServiceMethod, value.VariableAlias, routeParms); + return restWrapper; } - GxContext gxContext = GxContext.CreateDefaultInstance(); - object handler = ClassLoader.FindInstance(asssemblycontroller, nspace, tmpController, new Object[] { gxContext }, null); - - gxContext.HttpContext = context; - GxRestWrapper restWrapper = new Application.GxRestWrapper(handler as GXBaseObject, context, gxContext, value.ServiceMethod, value.VariableAlias, routeParms); - return restWrapper; } - } - else - { - if (requestType.Equals(HttpMethod.Options.Method) && !String.IsNullOrEmpty(actualPath) && GXAPIModule.servicesMapData.ContainsKey(actualPath)) + else { - return new OptionsApiObjectRequestHandler(actualPath, objectName, mapRegExp); + if (requestType.Equals(HttpMethod.Options.Method) && !string.IsNullOrEmpty(actualPath) && GXAPIModule.servicesMapData.ContainsKey(actualPath)) + { + return new OptionsApiObjectRequestHandler(actualPath, objectName, mapRegExp); + } } - } + } + return null; } - return null; } - else + assemblyName = cname0; + cname = cname0; + if (cname.EndsWith("_bc_ws")) { - { - assemblyName = cname0; - cname = cname0; - } - if (cname.EndsWith("_bc_ws")) - { - cname = cname.Substring(0, cname.Length - 3); - assemblyName = cname; - } + cname = cname.Substring(0, cname.Length - 3); + assemblyName = cname; } - string mainNamespace, className; - if (Config.GetValueOf("AppMainNamespace", out mainNamespace)) - className = mainNamespace + "." + cname; - else - className = "GeneXus.Programs." + cname; + string className = mainNamespace + "." + cname; Type objType = GetHandlerType(assemblyName, className); if (objType == null) @@ -190,7 +191,7 @@ public IHttpHandler GetHandler(HttpContext context, string requestType, string u } else { - handlerToReturn = (IHttpHandler)System.Web.UI.PageParser.GetCompiledPageInstance(url, pathTranslated, context); + handlerToReturn = System.Web.UI.PageParser.GetCompiledPageInstance(url, pathTranslated, context); } return handlerToReturn; } @@ -199,7 +200,7 @@ public string GetObjFromPath(string cname, string apath) { if (cname.LastIndexOf("/") == (cname.Length - 1)) cname = cname.Substring(0, cname.Length - 1); - String objectName = cname.Remove(0, apath.Length); + string objectName = cname.Remove(0, apath.Length); return objectName; } @@ -302,7 +303,7 @@ internal static Type GetHandlerType(string assemblyName, string className) try { - objType = GeneXus.Metadata.ClassLoader.FindType(assemblyName, className, null); + objType = ClassLoader.FindType(assemblyName, className, null); if (objType == null) objType = Assembly.Load(assemblyName).GetType(className); } From ec9cdd07bb34dc94c8c05127c576d3aeed4074e8 Mon Sep 17 00:00:00 2001 From: Ana Berta <31777352+anaiberta@users.noreply.github.com> Date: Wed, 13 Mar 2024 15:11:54 -0300 Subject: [PATCH 118/164] Add CodeQL badge (#976) Show CodeQL status at Readme --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 04de49d5b..6f4534743 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # GeneXus Standard Classes for .NET and .NET Framework GeneXus Standard Classes for .NET and .NET Framework generators. -## Build status -| Branch | Status -|---|--- -|master|[![](https://github.com/genexuslabs/dotnetclasses/workflows/Build/badge.svg?branch=master)](https://github.com/genexuslabs/dotnetclasses/actions?query=workflow%3ABuild+branch%3Amaster) -|beta|[![](https://github.com/genexuslabs/dotnetclasses/workflows/Build/badge.svg?branch=beta)](https://github.com/genexuslabs/dotnetclasses/actions?query=workflow%3ABuild+branch%3Abeta) +## Repo status +| Branch | Build | Security +|---|---|--- +|master|[![](https://github.com/genexuslabs/dotnetclasses/workflows/Build/badge.svg?branch=master)](https://github.com/genexuslabs/dotnetclasses/actions?query=workflow%3ABuild+branch%3Amaster)|[![CodeQL](https://github.com/genexuslabs/DotNetClasses/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/genexuslabs/DotNetClasses/actions/workflows/codeql-analysis.yml) +|beta|[![](https://github.com/genexuslabs/dotnetclasses/workflows/Build/badge.svg?branch=beta)](https://github.com/genexuslabs/dotnetclasses/actions?query=workflow%3ABuild+branch%3Abeta)|[![CodeQL](https://github.com/genexuslabs/DotNetClasses/actions/workflows/codeql-analysis.yml/badge.svg?branch=beta)](https://github.com/genexuslabs/DotNetClasses/actions/workflows/codeql-analysis.yml) ## Modules From 4ffc4f05d392db626f874f20dce14832ff3c1561 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Thu, 14 Mar 2024 13:50:46 -0300 Subject: [PATCH 119/164] Improve ajax deserialization performance at BeforeInvoke. (#960) * Improve ajax deserialization performance at BeforeInvoke. * Revert changes in GxCollections.cs. Static variables must be defined in generated code. * Enhance the performance of getFromJSONObjectOrderIterator, particularly during the deserialization of SDT collections. * Maintain compatibility with SDTs generated without the TypeInfo method. * Remove GXCompatibilityTypeInfo class. Enhance the performance of BC dirties handling. Avoid performing 'ToLower' operations on 'GxUpload' attribute searches and instead utilize a case-insensitive dictionary --- .../GxClasses/Core/Web/HttpAjaxContext.cs | 6 +- .../GxClasses/Domain/GxCollections.cs | 92 ++++--- .../StringUtil/JsonUtilTest.cs | 13 + .../StringUtil/type_SdtSDTTwoLevels.cs | 227 ++++++++++++++++++ .../type_SdtSDTTwoLevels_LevelItem.cs | 170 +++++++++++++ 5 files changed, 471 insertions(+), 37 deletions(-) create mode 100644 dotnet/test/DotNetCoreUnitTest/StringUtil/type_SdtSDTTwoLevels.cs create mode 100644 dotnet/test/DotNetCoreUnitTest/StringUtil/type_SdtSDTTwoLevels_LevelItem.cs diff --git a/dotnet/src/dotnetframework/GxClasses/Core/Web/HttpAjaxContext.cs b/dotnet/src/dotnetframework/GxClasses/Core/Web/HttpAjaxContext.cs index ad3055ad2..7092be321 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/Web/HttpAjaxContext.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/Web/HttpAjaxContext.cs @@ -85,7 +85,7 @@ public void ClearParmsMetadata() public bool isInputParm(string key) { - return inParmsMetadataHash.Contains(key); + return (inParmsMetadataHash!=null && inParmsMetadataHash.Contains(key)); } public void Clear() @@ -105,7 +105,7 @@ public bool isParmModified(string fieldName, object value) IGxJSONSerializable jsonValue = value as IGxJSONSerializable; if (jsonValue!=null) { - if (!inParmsHashValue.ContainsKey(fieldName)) + if (inParmsHashValue!=null && !inParmsHashValue.ContainsKey(fieldName)) return true; return GXUtil.GetHash(jsonValue.ToJSonString()) != inParmsHashValue[fieldName]; } @@ -346,7 +346,7 @@ public void ajax_rsp_assign_sdt_attri(String CmpContext, bool IsMasterPage, Stri try { JObject obj = GetGxObject(AttValues, CmpContext, IsMasterPage); - if (obj != null && (DynAjaxEventContext.isParmModified(AttName, SdtObj) || !isUndefinedOutParam( AttName, SdtObj))) + if (obj != null && (!isUndefinedOutParam(AttName, SdtObj) || DynAjaxEventContext.isParmModified(AttName, SdtObj))) { IGxJSONAble SdtObjJson = SdtObj as IGxJSONAble; if (SdtObjJson != null) diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs index 10e24713f..8e372a3c8 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs @@ -19,6 +19,7 @@ namespace GeneXus.Utils using System.Xml.Serialization; using GeneXus.Application; using GeneXus.Configuration; + using GeneXus.Data; using GeneXus.Http; using GeneXus.Metadata; using GeneXus.XML; @@ -1044,8 +1045,8 @@ public string Name public class GxUserType : IGxXMLSerializable, ICloneable, IGxJSONAble, IGxJSONSerializable, IGXAssigned { static readonly IGXLogger log = GXLoggerFactory.GetLogger(); - protected GXProperties dirties = new GXProperties(); - + protected ConcurrentDictionary dirties = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + private const string PROPERTY_PREFIX = "gxtpr_"; static object setupChannelObject = null; static bool setupChannelInitialized; [XmlIgnore] @@ -1103,11 +1104,11 @@ public GxUserType() public virtual void SetDirty(string fieldName) { - dirties[fieldName.ToLower()] = "true"; + dirties[fieldName] = 1; } public virtual bool IsDirty(string fieldName) { - if (dirties.ContainsKey(fieldName.ToLower())) + if (dirties.ContainsKey(fieldName)) return true; return false; } @@ -1605,24 +1606,27 @@ public Object GetJSONObject() private ICollection getFromJSONObjectOrderIterator(ICollection it) { - List v = new List(); + if (GxUploadAttrs.IsEmpty && !typeof(GxSilentTrnSdt).IsAssignableFrom(this.GetType())) + { + return it; + } + List _JsonObjectOrderIterator = new List(); + List vAtEnd = new List(); foreach (string name in it) { - string map = JsonMap(name); - PropertyInfo objProperty = GetTypeProperty("gxtpr_" + (!string.IsNullOrEmpty(map) ? map : name).ToLower()); - if (name.EndsWith("_N") || objProperty != null && IsGxUploadAttribute(objProperty)) + if (name.EndsWith("_N") || IsGxUploadAttribute(name)) { vAtEnd.Add(name); } else { - v.Add(name);//keep the order of attributes that do not end with _N. + _JsonObjectOrderIterator.Add(name);//keep the order of attributes that do not end with _N. } } if (vAtEnd.Count > 0) - v.AddRange(vAtEnd); - return v; + _JsonObjectOrderIterator.AddRange(vAtEnd); + return _JsonObjectOrderIterator; } public void FromJSONObject(dynamic obj) @@ -1635,9 +1639,7 @@ public void FromJSONObject(dynamic obj) foreach (string name in jsonIterator) { object currObj = jobj[name]; - string map = JsonMap(name); - PropertyInfo objProperty = GetTypeProperty("gxtpr_" + (map != null ? map : name).ToLower()); - + PropertyInfo objProperty = GetTypeProperty(JsonNameToInternalName(name)); if (objProperty != null) { if (!JSONHelper.IsJsonNull(currObj)) @@ -1897,32 +1899,51 @@ private bool TryConvertValueToProperty(object Value, PropertyInfo property, out return success; } - [System.Diagnostics.CodeAnalysis.SuppressMessage("GxFxCopRules", "CR1000:EnforceThreadSafeType")] - private Dictionary gxuploadAttrs = new Dictionary(); - private bool IsGxUploadAttribute(PropertyInfo property) + private GXTypeInfo _compatibilityGxuploadAttrs = null; + private bool IsGxUploadAttribute(string jsonPropertyName) { - string key = property.Name; - if (!gxuploadAttrs.ContainsKey(key)) - { - bool hasAtt = property.IsDefined(typeof(GxUpload), false); - gxuploadAttrs.Add(key, hasAtt); - } - return gxuploadAttrs[key]; + return GxUploadAttrs.ContainsKey(JsonNameToInternalName(jsonPropertyName)); } - - private Hashtable props; - - private PropertyInfo GetTypeProperty(string propName) + private bool IsGxUploadAttribute(PropertyInfo propertyInfo) + { + return GxUploadAttrs.ContainsKey(propertyInfo.Name); + } + private string JsonNameToInternalName(string jsonPropertyName) + { + string map = JsonMap(jsonPropertyName); + if (!string.IsNullOrEmpty(map)) + return $"{PROPERTY_PREFIX}{map}"; + else + return $"{PROPERTY_PREFIX}{jsonPropertyName}"; + } + protected virtual GXTypeInfo TypeInfo { get { return _compatibilityGxuploadAttrs; } set { _compatibilityGxuploadAttrs = value; } } + private ConcurrentDictionary GxUploadAttrs { - if (props == null) + get { - props = new Hashtable(); - foreach (PropertyInfo prop in this.GetType().GetProperties()) + if (TypeInfo == null) { - props.Add(prop.Name.ToLower(), prop); + TypeInfo = new GXTypeInfo(); + + TypeInfo.UploadAttrs = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + foreach (PropertyInfo property in this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) + { + if (property.Name.StartsWith(PROPERTY_PREFIX, StringComparison.OrdinalIgnoreCase)) + { + bool hasAtt = property.IsDefined(typeof(GxUpload), false); + if (hasAtt) + { + TypeInfo.UploadAttrs.TryAdd(property.Name, 1); + } + } + } } + return TypeInfo.UploadAttrs; } - return (PropertyInfo)props[propName]; + } + private PropertyInfo GetTypeProperty(string propName) + { + return this.GetType().GetProperty(propName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); } private Hashtable methods; @@ -2004,7 +2025,10 @@ public void SetPropertyValue(string propertyName, object propertyValue) GetType().GetProperty($"gxTpr_{propertyName}").SetValue(this, propertyValue); } } - + public class GXTypeInfo + { + public ConcurrentDictionary UploadAttrs { get; set; } + } public interface IGxJSONAble { void AddObjectProperty(string name, object prop); diff --git a/dotnet/test/DotNetCoreUnitTest/StringUtil/JsonUtilTest.cs b/dotnet/test/DotNetCoreUnitTest/StringUtil/JsonUtilTest.cs index 768153bd2..b40b38c43 100644 --- a/dotnet/test/DotNetCoreUnitTest/StringUtil/JsonUtilTest.cs +++ b/dotnet/test/DotNetCoreUnitTest/StringUtil/JsonUtilTest.cs @@ -190,6 +190,19 @@ public void DeserializationTrailingCommasCompatibility() JArray array = JSONHelper.ReadJSON(json); Assert.Equal(7, array.Count); } +#if NETCORE + [Fact] + public void DeserializationTwoLevels() + { + string json = "{\"Name\":\"MainName\",\"Level\":[{\"LevelName\":\"LevelName1\"}, {\"LevelName\":\"LevelName2\"}]}"; + GxContext context = new GxContext(); + SdtSDTTwoLevels sdt = new SdtSDTTwoLevels(context); + sdt.FromJSonString(json, null); + Assert.Equal("MainName", sdt.gxTpr_Name); + Assert.Equal("LevelName1",((SdtSDTTwoLevels_LevelItem)sdt.gxTpr_Level.Item(1)).gxTpr_Levelname); + Assert.Equal("LevelName2", ((SdtSDTTwoLevels_LevelItem)sdt.gxTpr_Level.Item(2)).gxTpr_Levelname); + } +#endif } [XmlSerializerFormat] diff --git a/dotnet/test/DotNetCoreUnitTest/StringUtil/type_SdtSDTTwoLevels.cs b/dotnet/test/DotNetCoreUnitTest/StringUtil/type_SdtSDTTwoLevels.cs new file mode 100644 index 000000000..7b7b2a2dc --- /dev/null +++ b/dotnet/test/DotNetCoreUnitTest/StringUtil/type_SdtSDTTwoLevels.cs @@ -0,0 +1,227 @@ +/* + File: type_SdtSDTTwoLevels + Description: SDTTwoLevels + Author: Nemo 🐠 for C# (.NET) version 18.0.9.180423 + Program type: Callable routine + Main DBMS: +*/ +using System; +using System.Collections; +using System.Collections.Concurrent; +using System.Reflection; +using System.Runtime.Serialization; +using System.Xml.Serialization; +using GeneXus.Application; +using GeneXus.Utils; + + +namespace GeneXus.Programs +{ + [XmlRoot(ElementName="SDTTwoLevels")] + [XmlType(TypeName="SDTTwoLevels" , Namespace="MassiveSearch" )] + [Serializable] + public class SdtSDTTwoLevels : GxUserType + { + public SdtSDTTwoLevels( ) + { + /* Constructor for serialization */ + gxTv_SdtSDTTwoLevels_Name = ""; + + } + + public SdtSDTTwoLevels(IGxContext context) + { + this.context = context; + initialize(); + } + + #region Json + private static Hashtable mapper; + public override string JsonMap(string value) + { + if (mapper == null) + { + mapper = new Hashtable(); + } + return (string)mapper[value]; ; + } + + public override void ToJSON() + { + ToJSON(true) ; + return; + } + + public override void ToJSON(bool includeState) + { + AddObjectProperty("Name", gxTpr_Name, false); + + if (gxTv_SdtSDTTwoLevels_Level != null) + { + AddObjectProperty("Level", gxTv_SdtSDTTwoLevels_Level, false); + } + return; + } + #endregion + + #region Properties + + [SoapElement(ElementName="Name")] + [XmlElement(ElementName="Name")] + public string gxTpr_Name + { + get { + return gxTv_SdtSDTTwoLevels_Name; + } + set { + gxTv_SdtSDTTwoLevels_Name = value; + SetDirty("Name"); + } + } + + + + + [SoapElement(ElementName="Level" )] + [XmlArray(ElementName="Level" )] + [XmlArrayItemAttribute(ElementName="LevelItem" , IsNullable=false )] + public GXBaseCollection gxTpr_Level + { + get { + if ( gxTv_SdtSDTTwoLevels_Level == null ) + { + gxTv_SdtSDTTwoLevels_Level = new GXBaseCollection( context, "SDTTwoLevels.LevelItem", ""); + } + return gxTv_SdtSDTTwoLevels_Level; + } + set { + gxTv_SdtSDTTwoLevels_Level_N = false; + gxTv_SdtSDTTwoLevels_Level = value; + SetDirty("Level"); + } + } + + public void gxTv_SdtSDTTwoLevels_Level_SetNull() + { + gxTv_SdtSDTTwoLevels_Level_N = true; + gxTv_SdtSDTTwoLevels_Level = null; + } + + public bool gxTv_SdtSDTTwoLevels_Level_IsNull() + { + return gxTv_SdtSDTTwoLevels_Level == null; + } + public bool ShouldSerializegxTpr_Level_GxSimpleCollection_Json() + { + return gxTv_SdtSDTTwoLevels_Level != null && gxTv_SdtSDTTwoLevels_Level.Count > 0; + + } + + + public override bool ShouldSerializeSdtJson() + { + return true; + } + + + + #endregion + + #region Static Type Properties + [SoapIgnore] + [XmlIgnore] + private static GXTypeInfo _typeProps; + protected override GXTypeInfo TypeInfo { get { return _typeProps; } set { _typeProps = value; } } + #endregion + + #region Initialization + + public void initialize( ) + { + gxTv_SdtSDTTwoLevels_Name = ""; + + gxTv_SdtSDTTwoLevels_Level_N = true; + + return ; + } + + + + #endregion + + #region Declaration + + protected string gxTv_SdtSDTTwoLevels_Name; + + protected bool gxTv_SdtSDTTwoLevels_Level_N; + protected GXBaseCollection gxTv_SdtSDTTwoLevels_Level = null; + + + + #endregion + } + #region Rest interface + [GxUnWrappedJson()] + [DataContract(Name=@"SDTTwoLevels", Namespace="MassiveSearch")] + public class SdtSDTTwoLevels_RESTInterface : GxGenericCollectionItem, System.Web.SessionState.IRequiresSessionState + { + public SdtSDTTwoLevels_RESTInterface( ) : base() + { + } + + public SdtSDTTwoLevels_RESTInterface( SdtSDTTwoLevels psdt ) : base(psdt) + { + } + + #region Rest Properties + [DataMember(Name="Name", Order=0)] + public string gxTpr_Name + { + get { + return StringUtil.RTrim( sdt.gxTpr_Name); + + } + set { + sdt.gxTpr_Name = value; + } + } + + [DataMember(Name="Level", Order=1, EmitDefaultValue=false)] + public GxGenericCollection gxTpr_Level + { + get { + if (sdt.ShouldSerializegxTpr_Level_GxSimpleCollection_Json()) + return new GxGenericCollection(sdt.gxTpr_Level); + else + return null; + + } + set { + value.LoadCollection(sdt.gxTpr_Level); + } + } + + + #endregion + + public SdtSDTTwoLevels sdt + { + get { + return (SdtSDTTwoLevels)Sdt; + } + set { + Sdt = value; + } + } + + [OnDeserializing] + void checkSdt( StreamingContext ctx ) + { + if ( sdt == null ) + { + sdt = new SdtSDTTwoLevels() ; + } + } + } + #endregion +} \ No newline at end of file diff --git a/dotnet/test/DotNetCoreUnitTest/StringUtil/type_SdtSDTTwoLevels_LevelItem.cs b/dotnet/test/DotNetCoreUnitTest/StringUtil/type_SdtSDTTwoLevels_LevelItem.cs new file mode 100644 index 000000000..76020f9ff --- /dev/null +++ b/dotnet/test/DotNetCoreUnitTest/StringUtil/type_SdtSDTTwoLevels_LevelItem.cs @@ -0,0 +1,170 @@ +/* + File: type_SdtSDTTwoLevels_LevelItem + Description: Level + Author: Nemo 🐠 for C# (.NET) version 18.0.9.180423 + Program type: Callable routine + Main DBMS: +*/ +using System; +using System.Collections; +using GeneXus.Utils; +using GeneXus.Resources; +using GeneXus.Application; +using GeneXus.Metadata; +using GeneXus.Cryptography; +using GeneXus.Encryption; +using GeneXus.Http.Client; +using GeneXus.Http.Server; +using System.Reflection; +using System.Xml.Serialization; +using System.Runtime.Serialization; +using System.Collections.Concurrent; + + +namespace GeneXus.Programs +{ + [XmlRoot(ElementName="SDTTwoLevels.LevelItem")] + [XmlType(TypeName="SDTTwoLevels.LevelItem" , Namespace="MassiveSearch" )] + [Serializable] + public class SdtSDTTwoLevels_LevelItem : GxUserType + { + public SdtSDTTwoLevels_LevelItem( ) + { + /* Constructor for serialization */ + gxTv_SdtSDTTwoLevels_LevelItem_Levelname = ""; + + } + + public SdtSDTTwoLevels_LevelItem(IGxContext context) + { + this.context = context; + initialize(); + } + + #region Json + private static Hashtable mapper; + public override string JsonMap(string value) + { + if (mapper == null) + { + mapper = new Hashtable(); + } + return (string)mapper[value]; ; + } + + public override void ToJSON() + { + ToJSON(true) ; + return; + } + + public override void ToJSON(bool includeState) + { + AddObjectProperty("LevelName", gxTpr_Levelname, false); + + return; + } + #endregion + + #region Properties + + [SoapElement(ElementName="LevelName")] + [XmlElement(ElementName="LevelName")] + public string gxTpr_Levelname + { + get { + return gxTv_SdtSDTTwoLevels_LevelItem_Levelname; + } + set { + gxTv_SdtSDTTwoLevels_LevelItem_Levelname = value; + SetDirty("Levelname"); + } + } + + + + public override bool ShouldSerializeSdtJson() + { + return true; + } + + + + #endregion + + #region Static Type Properties + [SoapIgnore] + [XmlIgnore] + private static GXTypeInfo _typeProps; + protected override GXTypeInfo TypeInfo { get { return _typeProps; } set { _typeProps = value; } } + #endregion + + #region Initialization + + public void initialize( ) + { + gxTv_SdtSDTTwoLevels_LevelItem_Levelname = ""; + return ; + } + + + + #endregion + + #region Declaration + + protected string gxTv_SdtSDTTwoLevels_LevelItem_Levelname; + + + + #endregion + } + #region Rest interface + [DataContract(Name=@"SDTTwoLevels.LevelItem", Namespace="MassiveSearch")] + public class SdtSDTTwoLevels_LevelItem_RESTInterface : GxGenericCollectionItem, System.Web.SessionState.IRequiresSessionState + { + public SdtSDTTwoLevels_LevelItem_RESTInterface( ) : base() + { + } + + public SdtSDTTwoLevels_LevelItem_RESTInterface( SdtSDTTwoLevels_LevelItem psdt ) : base(psdt) + { + } + + #region Rest Properties + [DataMember(Name="LevelName", Order=0)] + public string gxTpr_Levelname + { + get { + return StringUtil.RTrim( sdt.gxTpr_Levelname); + + } + set { + sdt.gxTpr_Levelname = value; + } + } + + + #endregion + + public SdtSDTTwoLevels_LevelItem sdt + { + get { + return (SdtSDTTwoLevels_LevelItem)Sdt; + } + set { + Sdt = value; + } + } + + [OnDeserializing] + void checkSdt( StreamingContext ctx ) + { + if ( sdt == null ) + { + sdt = new SdtSDTTwoLevels_LevelItem() ; + } + } + } + #endregion +} \ No newline at end of file From 70773cd945fe66a84e2ccf7c9e0c2d8df314244e Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Thu, 14 Mar 2024 14:53:51 -0300 Subject: [PATCH 120/164] Add new methods for collections. (#973) --- .../GxClasses/Domain/GxGenericCollections.cs | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxGenericCollections.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxGenericCollections.cs index b1d3a50fb..fd7f8234e 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxGenericCollections.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxGenericCollections.cs @@ -45,6 +45,54 @@ public GXBaseList() base.Insert(idx, TObject); IsAssigned = true; } + public bool AddRange(GXBaseList value, int? index) + { + if (!index.HasValue) + { + base.AddRange(value); + return true; + } + else if (index == 0) + { + base.InsertRange(index.Value, value); + return true; + } + else if (index > 0 && index <= Count+1) + { + base.InsertRange(index.Value - 1, value); + return true; + } + return false; + } + public bool RemoveRange(int index, int? countItemsToRemove) + { + if (index > 0 && index <= Count) + { + if (countItemsToRemove == null) + { + int countToRemove = Count - (index-1); + base.RemoveRange(index - 1, countToRemove); + return true; + } + else if (countItemsToRemove.Value < Count - index) + { + base.RemoveRange(index - 1, countItemsToRemove.Value); + return true; + } + } + return false; + } + + public bool Set(int index, T value) + { + if (index > 0 && index < Count) + { + this[index - 1] = value; + return true; + } + return false; + } + } [Serializable] From 24903cd3370527f84df856cd430f26fe856772c3 Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Sat, 16 Mar 2024 09:16:29 -0300 Subject: [PATCH 121/164] Opentelemetry Spans API (#975) --- .../OpenTelemetry/OpenTelemetryService.cs | 54 ++++- .../GXOtel.Diagnostics/OtelSpan.cs | 185 ++++++++++++------ .../GXOtel.Diagnostics/OtelTracer.cs | 86 +++++++- 3 files changed, 255 insertions(+), 70 deletions(-) diff --git a/dotnet/src/dotnetcore/GxClasses/Services/OpenTelemetry/OpenTelemetryService.cs b/dotnet/src/dotnetcore/GxClasses/Services/OpenTelemetry/OpenTelemetryService.cs index 3741c9a79..3dfdf2b00 100644 --- a/dotnet/src/dotnetcore/GxClasses/Services/OpenTelemetry/OpenTelemetryService.cs +++ b/dotnet/src/dotnetcore/GxClasses/Services/OpenTelemetry/OpenTelemetryService.cs @@ -1,4 +1,5 @@ using System; +using System.Text.RegularExpressions; using GxClasses.Helpers; namespace GeneXus.Services.OpenTelemetry @@ -12,9 +13,54 @@ public static class OpenTelemetryService { private static readonly IGXLogger log = GXLoggerFactory.GetLogger(typeof(OpenTelemetryService).FullName); - private static string OPENTELEMETRY_SERVICE = "Observability"; - public static string GX_ACTIVITY_SOURCE_NAME = "GeneXus.Tracing"; - + const string OTEL_RESOURCE_ATTRIBUTES = "OTEL_RESOURCE_ATTRIBUTES"; + const string OTEL_SERVICE_NAME = "OTEL_SERVICE_NAME"; + const string OTEL_SERVICE_VERSION = "OTEL_SERVICE_VERSION"; + const string OPENTELEMETRY_SERVICE = "Observability"; + + public static string GX_ACTIVITY_SOURCE_NAME= GetServiceNameValue(OTEL_RESOURCE_ATTRIBUTES); + public static string GX_ACTIVITY_SOURCE_VERSION= GetServiceVersionValue(OTEL_RESOURCE_ATTRIBUTES); + + private static string GetServiceNameValue(string input) + { + string otelServiceNameEnvVar = Environment.GetEnvironmentVariable(OTEL_SERVICE_NAME); + if (!string.IsNullOrEmpty(otelServiceNameEnvVar)) + return otelServiceNameEnvVar; + + string pattern = @"(?:\b\w+\b=\w+)(?:,(?:\b\w+\b=\w+))*"; + MatchCollection matches = Regex.Matches(input, pattern); + + foreach (Match match in matches) + { + string[] keyValue = match.Value.Split('='); + + if (keyValue[0] == "service.name") + { + return keyValue[1]; + } + } + return "GeneXus.Tracing"; + } + private static string GetServiceVersionValue(string input) + { + string otelServiceNameEnvVar = Environment.GetEnvironmentVariable(OTEL_SERVICE_VERSION); + if (!string.IsNullOrEmpty(otelServiceNameEnvVar)) + return otelServiceNameEnvVar; + + string pattern = @"(?:\b\w+\b=\w+)(?:,(?:\b\w+\b=\w+))*"; + MatchCollection matches = Regex.Matches(input, pattern); + + foreach (Match match in matches) + { + string[] keyValue = match.Value.Split('='); + + if (keyValue[0] == "service.version") + { + return keyValue[1]; + } + } + return string.Empty; + } private static IOpenTelemetryProvider GetOpenTelemetryProvider() { IOpenTelemetryProvider otelProvider = null; @@ -34,7 +80,7 @@ private static IOpenTelemetryProvider GetOpenTelemetryProvider() } catch (Exception e) { - GXLogging.Error(log, "Couldn´t create OpenTelemetry provider.", e.Message, e); + GXLogging.Error(log, "Couldn't create OpenTelemetry provider.", e.Message, e); throw e; } } diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/Diagnostics/GXOtel.Diagnostics/OtelSpan.cs b/dotnet/src/dotnetcore/Providers/OpenTelemetry/Diagnostics/GXOtel.Diagnostics/OtelSpan.cs index 4b35201d4..d05c93aa8 100644 --- a/dotnet/src/dotnetcore/Providers/OpenTelemetry/Diagnostics/GXOtel.Diagnostics/OtelSpan.cs +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/Diagnostics/GXOtel.Diagnostics/OtelSpan.cs @@ -1,112 +1,183 @@ using System; using System.Diagnostics; -using GeneXus.Application; +using GeneXus.Attributes; +using OpenTelemetry; using OpenTelemetry.Trace; -using static GeneXus.OpenTelemetry.Diagnostics.OtelTracer; namespace GeneXus.OpenTelemetry.Diagnostics { + [GXApi] public class OtelSpan { private Activity _activity; - public enum SpanStatusCode { Unset, Ok, Error } - public string Id - { get => _activity?.Id; } - public bool IsAllDataRequested + internal OtelSpan(Activity activity) { - get - { - if (_activity != null) - return _activity.IsAllDataRequested; - return false; - } + _activity = activity; } - public bool IsStopped - { get - { - if (_activity != null ) - return _activity.IsStopped; - return false; - } - } + public OtelSpan() + {} - public short Kind - { get => (short)_activity?.Kind; } + public Activity Activity => _activity; - public string ParentId - { get => _activity?.ParentId; } + #region EO Properties + public GXSpanContext SpanContext => _activity == null ? null : new GXSpanContext(_activity.Context); - public string ParentSpanId - { get => _activity?.ParentSpanId.ToString(); } + public GXTraceContext GetContext => _activity == null ? null : new GXTraceContext(_activity.Context); + public string SpanId => _activity?.Id; - public string TraceId - { get => _activity?.TraceId.ToString(); } + public string TraceId => _activity?.TraceId.ToHexString(); - public short Status - { get => (short)_activity?.Status; } - - internal OtelSpan(Activity activity) + #endregion + + #region Methods + public void Stop() { - _activity = activity; + _activity?.Stop(); + } + public void RecordException(string message) + { + _activity?.RecordException(new Exception(message)); } - public OtelSpan() + public void SetStringAttribute(string property, string value) { - _activity = Activity.Current; + _activity?.SetTag(property, value); + } - public void Start() + public void SetLongAttribute(string property, long value) { - _activity?.Start(); + _activity?.SetTag(property, value); + } + public void SetDoubleAttribute(string property, double value) + { + _activity?.SetTag(property, value); - public void Stop() + } + public void SetBooleanAttribute(string property, bool value) { - _activity?.Stop(); + _activity?.SetTag(property, value); + } - public void RecordException(string message) + public GXTraceContext AddBaggage(string property, string value) + { + Baggage.SetBaggage(property, value); + if (_activity != null) + return new GXTraceContext(_activity.Context); + else return null; + } + + public string GetBaggageItem(string property,GXTraceContext gXTraceContext) + { + return Baggage.GetBaggage(property); + } + public void SetStatus(SpanStatusCode spanStatusCode, string message) { - _activity.RecordException(new Exception(message)); + _activity?.SetStatus((ActivityStatusCode)spanStatusCode, message); } + public void SetStatus(SpanStatusCode spanStatusCode) + { + _activity?.SetStatus((ActivityStatusCode)spanStatusCode); + } + + #endregion - public void SetTag(string property, string value) + #region Private Methods + public bool IsRecording => IsSpanRecording(); + + private bool IsSpanRecording() { - _activity.SetTag(property, value); + if (_activity != null) + return _activity.IsAllDataRequested; + else + return false; } - public string GetTagItem(string property) + #endregion + + } + + public class GXTraceContext : GXSpanContext + { + //Dummy class to be compatible with Java. + //.NET does not requiere propagating the context explicitly in most of the cases. + //https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/src/OpenTelemetry.Api/README.md#baggage-api + + public GXTraceContext(ActivityContext activityContext):base(activityContext) { } + public GXTraceContext():base() { } + } + public class GXSpanContext + { + private ActivityContext _activityContext; + public GXSpanContext() { - return _activity.GetTagItem(property).ToString(); + _activityContext = Activity.Current.Context; } - public void AddBaggage(string property, string value) + + public GXSpanContext(ActivityContext activityContext) { - _activity.AddBaggage(property, value); + _activityContext = activityContext; } - public string GetBaggageItem(string property) + public ActivityContext ActivityContext { get { return _activityContext; } } + + public string TraceId => GetTraceId(); + + public string SpanId => GetSpanId(); + + private string GetTraceId() { - return _activity.GetBaggageItem(property).ToString(); + if (_activityContext != null) + { + ActivityTraceId activityTraceId = _activityContext.TraceId; + return activityTraceId.ToHexString(); + } else return null; + } + private string GetSpanId() + { + if (_activityContext != null) + { + ActivitySpanId activitySpanId = _activityContext.SpanId; + return activitySpanId.ToHexString(); + } else { return null; } } - public void SetStatus(SpanStatusCode spanStatusCode, string message) + private GXActivityTraceFlags TraceFlags() { - _activity.SetStatus((ActivityStatusCode)spanStatusCode, message); + if (_activityContext != null) { + ActivityTraceFlags activityTraceFlags = _activityContext.TraceFlags; + return (GXActivityTraceFlags)activityTraceFlags; + } + else { return GXActivityTraceFlags.None;} } - public SpanStatusCode GetStatus() + private string TraceState() { - return (SpanStatusCode)_activity.GetStatus().StatusCode; + if (_activityContext != null) + return _activityContext.TraceState; + else return null; } - //ToDO - //public void AddEvent() - //{ - //} + // + // Summary: + // Specifies flags defined by the W3C standard that are associated with an activity. + internal enum GXActivityTraceFlags + { + // + // Summary: + // The activity has not been marked. + None = 0, + // + // Summary: + // The activity (or more likely its parents) has been marked as useful to record. + Recorded = 1 + } } } diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/Diagnostics/GXOtel.Diagnostics/OtelTracer.cs b/dotnet/src/dotnetcore/Providers/OpenTelemetry/Diagnostics/GXOtel.Diagnostics/OtelTracer.cs index 8ce722bef..812b1ae28 100644 --- a/dotnet/src/dotnetcore/Providers/OpenTelemetry/Diagnostics/GXOtel.Diagnostics/OtelTracer.cs +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/Diagnostics/GXOtel.Diagnostics/OtelTracer.cs @@ -1,35 +1,103 @@ +using System; +using System.Collections.Generic; using System.Diagnostics; -using GeneXus.Application; +using System.Linq; using GeneXus.Attributes; +using GeneXus.Services.OpenTelemetry; namespace GeneXus.OpenTelemetry.Diagnostics { [GXApi] public class OtelTracer { + internal static ActivitySource activitySource; + internal static ActivitySource ActivitySource + { + get + { + if (activitySource == null) + { + activitySource = string.IsNullOrEmpty(OpenTelemetryService.GX_ACTIVITY_SOURCE_VERSION) ? new(OpenTelemetryService.GX_ACTIVITY_SOURCE_NAME) : new(OpenTelemetryService.GX_ACTIVITY_SOURCE_NAME, OpenTelemetryService.GX_ACTIVITY_SOURCE_VERSION); + } + return activitySource; + } + } public enum SpanType { - Client, - Consumer, Internal, + Server, + Client, Producer, - Server + Consumer + } + + public OtelSpan CreateSpan(string name) + { + //Returns null when the are no listeners. + Activity activity = ActivitySource.StartActivity(name); + if (activity != null) + return new OtelSpan(activity); + return null; } public OtelSpan CreateSpan(string name, SpanType kind) { - Activity activity = GXBaseObject.ActivitySource.StartActivity(name, (ActivityKind)kind); + Activity activity = ActivitySource.StartActivity(name, (ActivityKind)kind); + if (activity != null) + return new OtelSpan(activity); + else + return null; + } + + public OtelSpan CreateSpan(string name, GXTraceContext gxTraceContext, SpanType spanType) + { + Activity activity = ActivitySource.StartActivity(name, + kind: (ActivityKind)spanType, + parentContext: gxTraceContext.ActivityContext); + return new OtelSpan(activity); + + } + + public OtelSpan CreateSpan(string name, GXTraceContext gxTraceContext, SpanType spanType, IList gxSpanContexts) + { + //https://learn.microsoft.com/en-us/dotnet/core/diagnostics/distributed-tracing-instrumentation-walkthroughs#optional-links + List contexts = new List(); + + foreach (GXSpanContext gxSpanContext in gxSpanContexts) + { + ActivityContext context = gxSpanContext.ActivityContext; + contexts.Add(context); + } + + Activity activity = ActivitySource.StartActivity(name, + kind: (ActivityKind)spanType, + parentContext: gxTraceContext.ActivityContext, + links: contexts.Select(ctx => new ActivityLink(ctx))); return new OtelSpan(activity); } - public OtelSpan GetCurrent() + public OtelSpan CreateSpan(string name, GXTraceContext gxTraceContext, SpanType spanType, IList gxSpanContexts, DateTime dateTime) { - return new OtelSpan(Activity.Current); + //https://learn.microsoft.com/en-us/dotnet/core/diagnostics/distributed-tracing-instrumentation-walkthroughs#optional-links + List contexts = new List(); + + foreach (GXSpanContext gxSpanContext in gxSpanContexts) + { + ActivityContext context = gxSpanContext.ActivityContext; + contexts.Add(context); + } + + Activity activity = ActivitySource.StartActivity(name, + kind: (ActivityKind)spanType, + parentContext: gxTraceContext.ActivityContext, + links: contexts.Select(ctx => new ActivityLink(ctx)), + startTime:dateTime); + return new OtelSpan(activity); } - public bool HasListeners() + public static OtelSpan GetCurrent() { - return GXBaseObject.ActivitySource.HasListeners(); + return new OtelSpan(Activity.Current); } } } From 4cfa7bc5a8e02b7ed64dbe93906ccd87eb3fc26f Mon Sep 17 00:00:00 2001 From: Alejandro Panizza Carve Date: Tue, 19 Mar 2024 17:40:12 -0300 Subject: [PATCH 122/164] - Fix collection serialization for rest procedures and dataproviders (#956) * - Fix collection serialization para rest procedures and dataproviders output 106797 * - Fix case when rest procedure has an empty output parameter or no output parameter. Reverts to default wrapped status for this case * - Support for custom serialization of collection in REST proc as well as API objects. Changed Attribute GxUnWrappedJson for GxJsonSerialization(type) * - minor code improvements * - fix default case for serialization of lists in dataproviders rest with Json response * - Fix serialization wrapped for Genexus.Message Lists * - Rename of the root element in API objects that returns SDT from DPs * - Change GetWrappedStatus function as private. - Change SetWrappedStatus function as internal. * - Add Dataprovider Flag. * - Ignore wrapped status of Lists for DPs * - isDataProvider property was not inherited in NET 4.X . Created a different one. * - Saco temporalmente la restriccion de no usar el wrappedstatus en DP * - remove the property isDataProvider. Issue 106797 --- .../GxClasses/Model/GXBaseObject.cs | 2 + .../GxClasses/Model/GXSilentTrn.cs | 34 +++++++ .../GxClasses/Model/GXWebProcedure.cs | 2 +- .../GxClasses/Services/GxRestWrapper.cs | 96 +++++++++++++------ .../GxClasses/Services/ReflectionHelper.cs | 26 ++++- .../type_SdtEventMessageProperty.cs | 1 + .../type_SdtEventMessageResponse.cs | 1 + 7 files changed, 130 insertions(+), 32 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs b/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs index 8cc6f616b..d5da20307 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs @@ -37,6 +37,7 @@ public class GXBaseObject protected IGxContext _Context; bool _isMain; protected bool _isApi; + protected bool _isDP; #if NETCORE internal static ActivitySource ActivitySource { get { @@ -176,6 +177,7 @@ public bool IsApiObject set { _isApi = value; } get { return _isApi; } } + public virtual void cleanup() { } virtual public bool UploadEnabled() { return false; } diff --git a/dotnet/src/dotnetframework/GxClasses/Model/GXSilentTrn.cs b/dotnet/src/dotnetframework/GxClasses/Model/GXSilentTrn.cs index 1bff5d5cb..c64c26d10 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/GXSilentTrn.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/GXSilentTrn.cs @@ -583,6 +583,7 @@ public GXBaseCollection GetMessages() public interface IGxGenericCollectionWrapped { bool GetIsWrapped(); + string GetWrappedStatus(); void SetIsWrapped(bool value); } @@ -608,6 +609,12 @@ public GxGenericCollection(IGxCollection x, bool wrapped):this(x) isWrapped = wrapped; } + public GxGenericCollection(IGxCollection x, bool wrapped, string wrappedstatus) : this(x) + { + isWrapped = wrapped; + wrappedStatus = wrappedstatus; + } + public void LoadCollection(IGxCollection x) { foreach (IGxGenericCollectionItem x1 in this) @@ -628,6 +635,8 @@ public override string ToString() public bool GetIsWrapped() { + if (wrappedStatus.Equals("unwrapped")) + isWrapped = false; return isWrapped; } @@ -635,6 +644,18 @@ public void SetIsWrapped(bool value) { isWrapped = value; } + + private string wrappedStatus = ""; + + public string GetWrappedStatus() + { + return wrappedStatus; + } + + internal void SetWrappedStatus(string value) + { + wrappedStatus = value; + } } public interface IGxGenericCollectionItem { @@ -649,6 +670,17 @@ public GxUnWrappedJson() } } + [AttributeUsage(AttributeTargets.Class)] + public sealed class GxJsonSerialization : Attribute + { + string unwrapped = default; + public GxJsonSerialization(string jsonunwrapped) + { + unwrapped = jsonunwrapped; + } + public string JsonUnwrapped { get => unwrapped; set => unwrapped = value; } + } + [AttributeUsage(AttributeTargets.Class)] public sealed class GxOmitEmptyCollection : Attribute { @@ -836,6 +868,7 @@ public GxUpload() [XmlRoot(ElementName = "Message")] [XmlType(TypeName = "Message", Namespace = "GeneXus")] [Serializable] + [GxJsonSerialization("wrapped")] public class SdtMessages_Message : GxUserType { public SdtMessages_Message() @@ -938,6 +971,7 @@ public void initialize() [DataContract(Name = @"Messages.Message", Namespace = "GeneXus")] [GxOmitEmptyCollection] + [GxJsonSerialization("wrapped")] public class SdtMessages_Message_RESTInterface : GxGenericCollectionItem, System.Web.SessionState.IRequiresSessionState { public SdtMessages_Message_RESTInterface() diff --git a/dotnet/src/dotnetframework/GxClasses/Model/GXWebProcedure.cs b/dotnet/src/dotnetframework/GxClasses/Model/GXWebProcedure.cs index 295e553e0..7a0a689ae 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/GXWebProcedure.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/GXWebProcedure.cs @@ -57,7 +57,7 @@ protected override void SetCompression(HttpContext httpContext) } } public void setContextReportHandler() - { + { oldReportHandler = null; reportHandler = context.reportHandler; diff --git a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs index d866e3288..40e24a0c3 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs @@ -30,6 +30,8 @@ using System.Net.Http; using System.Diagnostics; using GeneXus.Diagnostics; +using System.Xml.Linq; + namespace GeneXus.Application @@ -346,31 +348,17 @@ public virtual Task MethodUrlExecute(object key) Cleanup(); } } - bool GetWrappedStatus(GXBaseObject worker, bool defaultWrapped, Dictionary outputParameters, int parCount, int originalParCount) + private bool GetWrappedStatus(GXBaseObject worker, bool defaultWrapped, Dictionary outputParameters, int parCount, int originalParCount) { bool wrapped = defaultWrapped; + if (worker.IsApiObject) { if (outputParameters.Count == 1) { if ((originalParCount == 1) || (originalParCount > 1 && !Preferences.WrapSingleApiOutput)) { - wrapped = false; - Object v = outputParameters.First().Value; - - if (v.GetType().GetInterfaces().Contains(typeof(IGxGenericCollectionWrapped))) - { - IGxGenericCollectionWrapped icollwrapped = v as IGxGenericCollectionWrapped; - if (icollwrapped != null) - wrapped = icollwrapped.GetIsWrapped(); - } - if (v is IGxGenericCollectionItem item) - { - if (item.Sdt is GxSilentTrnSdt) - { - wrapped = (parCount > 1) ? true : false; - } - } + wrapped = GetCollectionWrappedStatus(outputParameters, parCount, false, true); } if (originalParCount > 1 && Preferences.WrapSingleApiOutput) { @@ -378,6 +366,44 @@ bool GetWrappedStatus(GXBaseObject worker, bool defaultWrapped, Dictionary outputParameters , int parCount, bool defaultWrapped, bool isAPI) + { + bool wrapped = defaultWrapped; + if (outputParameters.Count > 0) + { + Object v = outputParameters.First().Value; + if (v.GetType().GetInterfaces().Contains(typeof(IGxGenericCollectionWrapped))) + { + IGxGenericCollectionWrapped icollwrapped = v as IGxGenericCollectionWrapped; + if (icollwrapped != null) + { + if (icollwrapped.GetWrappedStatus().Equals("default")) + wrapped = defaultWrapped; + else + wrapped = icollwrapped.GetIsWrapped(); + } + } + + if (isAPI) + { + if (v is IGxGenericCollectionItem item) + { + if (item.Sdt is GxSilentTrnSdt) + { + wrapped = (parCount > 1) ? true : false; + } + } + } + } return wrapped; } @@ -806,8 +832,10 @@ protected Task Serialize(object value) #else var responseStream = _httpContext.Response.OutputStream; #endif - var knownTypes = new List(); - knownTypes.Add(value.GetType()); + var knownTypes = new List + { + value.GetType() + }; JSONHelper.WCFSerialize(value, Encoding.UTF8, knownTypes, responseStream); return Task.CompletedTask; @@ -845,14 +873,17 @@ private static void RestProcess(GXBaseObject worker, Dictionary } } - protected static object MakeRestType( object v, bool isApiObject) + protected static object MakeRestType( object collectionValue, bool isApiObject) { - Type vType = v.GetType(); + Type vType = collectionValue.GetType(); Type itemType; if (vType.IsConstructedGenericType && typeof(IGxCollection).IsAssignableFrom(vType)) - { + { + bool isWrapped = (isApiObject)?false:true; + object collectionObject = null; + string wrappedStatus = ""; Type restItemType=null; - itemType = v.GetType().GetGenericArguments()[0]; + itemType = collectionValue.GetType().GetGenericArguments()[0]; if ((typeof(IGXBCCollection).IsAssignableFrom(vType)) && !isApiObject)//Collection convert to GxGenericCollection { restItemType = ClassLoader.FindType(Config.CommonAssemblyName, itemType.FullName + "_RESTLInterface", null); @@ -861,24 +892,31 @@ protected static object MakeRestType( object v, bool isApiObject) { restItemType = ClassLoader.FindType(Config.CommonAssemblyName, itemType.FullName + "_RESTInterface", null); } - bool isWrapped = !restItemType.IsDefined(typeof(GxUnWrappedJson), false); + object[] attributes = restItemType.GetCustomAttributes(typeof(GxJsonSerialization), false); + IEnumerable serializationAttributes = attributes.Where(a => a.GetType() == typeof(GxJsonSerialization)); + if (serializationAttributes != null && serializationAttributes.Any()) + { + GxJsonSerialization attFmt = (GxJsonSerialization)serializationAttributes.FirstOrDefault(); + wrappedStatus = attFmt.JsonUnwrapped; + isWrapped = (isApiObject)? ((wrappedStatus == "wrapped")? true: false): ((wrappedStatus == "unwrapped") ? false : true); + } bool isEmpty = !restItemType.IsDefined(typeof(GxOmitEmptyCollection), false); Type genericListItemType = typeof(GxGenericCollection<>).MakeGenericType(restItemType); - object c = Activator.CreateInstance(genericListItemType, new object[] { v, isWrapped}); + collectionObject = Activator.CreateInstance(genericListItemType, new object[] { collectionValue, isWrapped , wrappedStatus}); // Empty collection serialized w/ noproperty - if (c is IList restList) + if (collectionObject is IList restList) { if (restList.Count == 0 && !isEmpty) return null; } - return c; + return collectionObject; } else if (typeof(GxUserType).IsAssignableFrom(vType)) //SDTType convert to SDTType_RESTInterface { Type restItemType = ClassLoader.FindType(Config.CommonAssemblyName, vType.FullName + "_RESTInterface", null); - return Activator.CreateInstance(restItemType, new object[] { v }); + return Activator.CreateInstance(restItemType, new object[] { collectionValue }); } - return v; + return collectionValue; } #if !NETCORE diff --git a/dotnet/src/dotnetframework/GxClasses/Services/ReflectionHelper.cs b/dotnet/src/dotnetframework/GxClasses/Services/ReflectionHelper.cs index 5108ae30d..baafc35e2 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/ReflectionHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/ReflectionHelper.cs @@ -235,7 +235,7 @@ private static Dictionary ProcessParametersAfterInvoke(MethodInf int idx = 0; foreach (var methodParameter in methodParameters) { - string gxParameterName = GxParameterName(methodParameter.Name); + string gxParameterName = GxParameterName(methodParameter); if (IsByRefParameter(methodParameter)) { outputParameters.Add(gxParameterName, parametersForInvocation[idx]); @@ -320,12 +320,34 @@ internal static object[] ProcessParametersForInvoke(MethodInfo methodInfo, IList return parametersForInvocation; } private static Regex attVar = new Regex(@"^AV?\d{1,}", RegexOptions.Compiled); + + private static string GxParameterName(ParameterInfo methodParameter) + { + int idx = methodParameter.Name.IndexOf('_'); + if (idx >= 0) + { + string mparm = methodParameter.Name.Substring(idx + 1); + string PName = methodParameter.ParameterType.FullName; + // The root element name should be in the metadata of the SDT + if (mparm.StartsWith("Gx") && mparm.EndsWith("rootcol") && PName.Contains("_")) + { + int Pos = PName.IndexOf("Sdt") + 3; + mparm = PName.Substring(Pos, PName.IndexOf("_") - Pos); + } + return mparm; + } + else + { + return attVar.Replace(methodParameter.Name, string.Empty); + } + } + private static string GxParameterName(string methodParameterName) { int idx = methodParameterName.IndexOf('_'); if (idx >= 0) { - return methodParameterName.Substring(idx + 1); + return methodParameterName.Substring(idx + 1); } else { diff --git a/dotnet/src/extensions/Azure/test/GeneXus.Programs.Common/type_SdtEventMessageProperty.cs b/dotnet/src/extensions/Azure/test/GeneXus.Programs.Common/type_SdtEventMessageProperty.cs index f04498b0b..6fcdacad9 100644 --- a/dotnet/src/extensions/Azure/test/GeneXus.Programs.Common/type_SdtEventMessageProperty.cs +++ b/dotnet/src/extensions/Azure/test/GeneXus.Programs.Common/type_SdtEventMessageProperty.cs @@ -138,6 +138,7 @@ public void initialize( ) } #region Rest interface [GxUnWrappedJson()] + [GxJsonSerialization("default")] [DataContract(Name=@"EventMessageProperty", Namespace="ServerlessAPI")] public class SdtEventMessageProperty_RESTInterface : GxGenericCollectionItem, System.Web.SessionState.IRequiresSessionState { diff --git a/dotnet/src/extensions/Azure/test/GeneXus.Programs.Common/type_SdtEventMessageResponse.cs b/dotnet/src/extensions/Azure/test/GeneXus.Programs.Common/type_SdtEventMessageResponse.cs index 984b053cf..bcd519d34 100644 --- a/dotnet/src/extensions/Azure/test/GeneXus.Programs.Common/type_SdtEventMessageResponse.cs +++ b/dotnet/src/extensions/Azure/test/GeneXus.Programs.Common/type_SdtEventMessageResponse.cs @@ -131,6 +131,7 @@ public void initialize() } #region Rest interface [GxUnWrappedJson()] + [GxJsonSerialization("default")] [DataContract(Name = @"EventMessageResponse", Namespace = "GeneXus")] public class SdtEventMessageResponse_RESTInterface : GxGenericCollectionItem, System.Web.SessionState.IRequiresSessionState { From 45054aa144940377d0a96531ceb2d8bbaea91625 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Thu, 21 Mar 2024 15:08:26 -0300 Subject: [PATCH 123/164] Avoid CSRF setting adding x-frame-options header (#983) --- dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs index c6bcff2d0..c6c46ff34 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs @@ -221,7 +221,7 @@ public void ConfigureServices(IServiceCollection services) services.AddAntiforgery(options => { options.HeaderName = HttpHeader.X_CSRF_TOKEN_HEADER; - options.SuppressXFrameOptionsHeader = false; + options.SuppressXFrameOptionsHeader = true; }); } services.AddDirectoryBrowser(); From baf898d198218d35745e0ac3afb33abd0088d87f Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Thu, 21 Mar 2024 15:17:46 -0300 Subject: [PATCH 124/164] Add a mechanism to register native controllers. (#977) * Add a mechanism to register native controllers. * Add a unit test for native controller. --- dotnet/DotNetStandardClasses.sln | 9 ++++++- .../dotnetcore/GxNetCoreStartup/Startup.cs | 27 +++++++++++++++++-- .../DotNetCoreWebUnitTest.csproj | 1 + .../Middleware/MiddlewareTest.cs | 5 ++++ .../AccessTokenController_Test.cs | 24 +++++++++++++++++ .../AccessTokenController_Test.csproj | 7 +++++ .../Properties/launchSettings.json | 12 +++++++++ 7 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 dotnet/test/NativeAccessControllerTest/AccessTokenController_Test.cs create mode 100644 dotnet/test/NativeAccessControllerTest/AccessTokenController_Test.csproj create mode 100644 dotnet/test/NativeAccessControllerTest/Properties/launchSettings.json diff --git a/dotnet/DotNetStandardClasses.sln b/dotnet/DotNetStandardClasses.sln index bad8eab6d..01e391f0b 100644 --- a/dotnet/DotNetStandardClasses.sln +++ b/dotnet/DotNetStandardClasses.sln @@ -259,7 +259,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetCoreCmdTest", "test\D EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarks", "benchmarks", "{46DAAFD1-FAF5-4904-8EC5-406BE04E5538}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LogTest", "test\benchmarks\LogTest\LogTest.csproj", "{A1DBDCE0-4F09-445F-A202-9B260CDD46CF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LogTest", "test\benchmarks\LogTest\LogTest.csproj", "{A1DBDCE0-4F09-445F-A202-9B260CDD46CF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AccessTokenController_Test", "test\NativeAccessControllerTest\AccessTokenController_Test.csproj", "{A5589382-DB6F-4450-AE2B-6C6AA1643EF1}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -635,6 +637,10 @@ Global {A1DBDCE0-4F09-445F-A202-9B260CDD46CF}.Debug|Any CPU.Build.0 = Debug|Any CPU {A1DBDCE0-4F09-445F-A202-9B260CDD46CF}.Release|Any CPU.ActiveCfg = Release|Any CPU {A1DBDCE0-4F09-445F-A202-9B260CDD46CF}.Release|Any CPU.Build.0 = Release|Any CPU + {A5589382-DB6F-4450-AE2B-6C6AA1643EF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A5589382-DB6F-4450-AE2B-6C6AA1643EF1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A5589382-DB6F-4450-AE2B-6C6AA1643EF1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A5589382-DB6F-4450-AE2B-6C6AA1643EF1}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -760,6 +766,7 @@ Global {956402BD-AC8C-426E-961B-B77B3F3EDAEB} = {1D6F1776-FF4B-46C2-9B3D-BC46CCF049DC} {46DAAFD1-FAF5-4904-8EC5-406BE04E5538} = {1D6F1776-FF4B-46C2-9B3D-BC46CCF049DC} {A1DBDCE0-4F09-445F-A202-9B260CDD46CF} = {46DAAFD1-FAF5-4904-8EC5-406BE04E5538} + {A5589382-DB6F-4450-AE2B-6C6AA1643EF1} = {1D6F1776-FF4B-46C2-9B3D-BC46CCF049DC} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E18684C9-7D76-45CD-BF24-E3944B7F174C} diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs index c6c46ff34..5e8c94e0a 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Net; +using System.Reflection; using System.Threading.Tasks; using GeneXus.Configuration; using GeneXus.Http; @@ -143,6 +144,7 @@ public class Startup const string CORS_POLICY_NAME = "AllowSpecificOriginsPolicy"; const string CORS_ANY_ORIGIN = "*"; const double CORS_MAX_AGE_SECONDS = 86400; + internal const string GX_CONTROLLERS = "gxcontrollers"; public List servicesBase = new List(); @@ -161,7 +163,24 @@ public void ConfigureServices(IServiceCollection services) { OpenTelemetryService.Setup(services); - services.AddMvc(option => option.EnableEndpointRouting = false); + services.AddControllers(); + string controllers = Path.Combine(Startup.LocalPath, "bin", GX_CONTROLLERS); + IMvcBuilder mvcBuilder = services.AddMvc(option => option.EnableEndpointRouting = false); + try + { + if (Directory.Exists(controllers)) + { + foreach (string controller in Directory.GetFiles(controllers)) + { + Console.WriteLine($"Loading controller {controller}"); + mvcBuilder.AddApplicationPart(Assembly.LoadFrom(controller)).AddControllersAsServices(); + } + } + } + catch (Exception ex) + { + Console.Error.WriteLine("Error loading gxcontrollers " + ex.Message); + } services.Configure(options => { options.AllowSynchronousIO = true; @@ -248,7 +267,6 @@ public void ConfigureServices(IServiceCollection services) }); } DefineCorsPolicy(services); - services.AddMvc(); } private void DefineCorsPolicy(IServiceCollection services) @@ -333,6 +351,7 @@ public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHos { app.UseResponseCompression(); } + app.UseRouting(); app.UseCookiePolicy(); app.UseSession(); app.UseStaticFiles(); @@ -355,6 +374,10 @@ public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHos app.UseHttpsRedirection(); app.UseHsts(); } + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); if (log.IsDebugEnabled) { try diff --git a/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj b/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj index 61a57b2f2..9e1a026c4 100644 --- a/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj +++ b/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj @@ -39,6 +39,7 @@ + diff --git a/dotnet/test/DotNetCoreWebUnitTest/Middleware/MiddlewareTest.cs b/dotnet/test/DotNetCoreWebUnitTest/Middleware/MiddlewareTest.cs index 15c2c86c5..a034ebc0b 100644 --- a/dotnet/test/DotNetCoreWebUnitTest/Middleware/MiddlewareTest.cs +++ b/dotnet/test/DotNetCoreWebUnitTest/Middleware/MiddlewareTest.cs @@ -18,6 +18,7 @@ public class MiddlewareTest public MiddlewareTest() { SetEnvironmentVars(); + BeforeStartup(); server = new TestServer(WebHost.CreateDefaultBuilder().UseStartup().UseEnvironment(DOTNET_ENVIRONMENT)); GXRouting.ContentRootPath = Directory.GetCurrentDirectory(); server.PreserveExecutionContext= true; @@ -26,6 +27,10 @@ public MiddlewareTest() protected virtual void SetEnvironmentVars() { + } + protected virtual void BeforeStartup() + { + } protected string GetHeader(HttpResponseMessage response, string headerName) { diff --git a/dotnet/test/NativeAccessControllerTest/AccessTokenController_Test.cs b/dotnet/test/NativeAccessControllerTest/AccessTokenController_Test.cs new file mode 100644 index 000000000..6b8aeca31 --- /dev/null +++ b/dotnet/test/NativeAccessControllerTest/AccessTokenController_Test.cs @@ -0,0 +1,24 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; + +namespace GeneXus.Programs +{ + public class RequestParameters + { + public string message { get; set; } + } + + [ApiController] + [Route("dummy.aspx")] + + public class AccessTokenControllerDummy : ControllerBase + { + [HttpPost] + public async Task> Post([FromForm] string message) + { + return await Task.FromResult(message); + } + } + +} \ No newline at end of file diff --git a/dotnet/test/NativeAccessControllerTest/AccessTokenController_Test.csproj b/dotnet/test/NativeAccessControllerTest/AccessTokenController_Test.csproj new file mode 100644 index 000000000..68adc9bd2 --- /dev/null +++ b/dotnet/test/NativeAccessControllerTest/AccessTokenController_Test.csproj @@ -0,0 +1,7 @@ + + + + net6.0;net8.0 + Library + + diff --git a/dotnet/test/NativeAccessControllerTest/Properties/launchSettings.json b/dotnet/test/NativeAccessControllerTest/Properties/launchSettings.json new file mode 100644 index 000000000..1826f57c1 --- /dev/null +++ b/dotnet/test/NativeAccessControllerTest/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "AccessTokenController_Test": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:63881;http://localhost:63882" + } + } +} \ No newline at end of file From cf3e68eecfcf3860655db4e5f871b85c5e43dfc7 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Thu, 21 Mar 2024 15:18:19 -0300 Subject: [PATCH 125/164] Remove overhead during sql command initialization. (#981) Delay the initialization of SQL commands until the connection is opened, specifically for SQL Server. --- .../GxClasses/Data/GXDataCommon.cs | 197 +++++++++--------- 1 file changed, 99 insertions(+), 98 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs index 58a261c3e..a0556ea21 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs @@ -2619,7 +2619,6 @@ public void PrepareClose() public GxConnectionCache(IGxConnection gxconn,int maxSize) { preparedCommandsCache = new Dictionary(MAX_SIZE); - InitCommands(); preparedStmtCache=new GxPreparedStatementCache(gxconn,maxSize); conn=gxconn; dataAdapterCacheQueue = new List(); @@ -2629,7 +2628,6 @@ public GxConnectionCache(IGxConnection gxconn) { preparedCommandsCache = new Dictionary(MAX_SIZE); preparedStmtCache = new GxPreparedStatementCache(gxconn, MAX_SIZE); - InitCommands(); conn = gxconn; dataAdapterCacheQueue = new List(); } @@ -3012,118 +3010,120 @@ public void Clear() if (commandsToRemove!=null) commandsToRemove.Clear(); } - private void InitCommands() + internal void InitCommands() { - int commandTimeout = 0; + if (fetchCommand == null) + { + int commandTimeout = 0; - //----------------Fetch command - fetchCommand=new SqlCommand("sp_cursorfetch"); - fetchCommand.CommandType=CommandType.StoredProcedure; - fetchCommand.CommandTimeout = commandTimeout; - SqlParameter p1 = fetchCommand.Parameters.Add("cursor", SqlDbType.Int); - p1.Direction = ParameterDirection.Input; + //----------------Fetch command + fetchCommand = new SqlCommand("sp_cursorfetch"); + fetchCommand.CommandType = CommandType.StoredProcedure; + fetchCommand.CommandTimeout = commandTimeout; + SqlParameter p1 = fetchCommand.Parameters.Add("cursor", SqlDbType.Int); + p1.Direction = ParameterDirection.Input; - SqlParameter p2 = fetchCommand.Parameters.Add("fetchtype", SqlDbType.Int); - p2.Direction = ParameterDirection.Input; - p2.Value = 2;//0x0002 Next row. + SqlParameter p2 = fetchCommand.Parameters.Add("fetchtype", SqlDbType.Int); + p2.Direction = ParameterDirection.Input; + p2.Value = 2;//0x0002 Next row. - SqlParameter p3 = fetchCommand.Parameters.Add("rownumber", SqlDbType.Int); - p3.Direction = ParameterDirection.Input; - p3.Value = 1; - - SqlParameter p5 = fetchCommand.Parameters.Add("nrows", SqlDbType.Int); - p5.Direction = ParameterDirection.Input; + SqlParameter p3 = fetchCommand.Parameters.Add("rownumber", SqlDbType.Int); + p3.Direction = ParameterDirection.Input; + p3.Value = 1; - //-----------------PrepExec command - prepExecCommand=new SqlCommand("sp_cursorprepexec"); - prepExecCommand.CommandType=CommandType.StoredProcedure; - prepExecCommand.CommandTimeout = commandTimeout; + SqlParameter p5 = fetchCommand.Parameters.Add("nrows", SqlDbType.Int); + p5.Direction = ParameterDirection.Input; - prepExecParms=new SqlParameter[7]; - prepExecParms[0]=new SqlParameter("cursor",SqlDbType.Int); - prepExecParms[0].Direction=ParameterDirection.Output; - prepExecParms[0].Value=DBNull.Value; + //-----------------PrepExec command + prepExecCommand = new SqlCommand("sp_cursorprepexec"); + prepExecCommand.CommandType = CommandType.StoredProcedure; + prepExecCommand.CommandTimeout = commandTimeout; - prepExecParms[1]=new SqlParameter("handle",SqlDbType.Int); - prepExecParms[1].Direction=ParameterDirection.Output; - prepExecParms[1].Value=0; + prepExecParms = new SqlParameter[7]; + prepExecParms[0] = new SqlParameter("cursor", SqlDbType.Int); + prepExecParms[0].Direction = ParameterDirection.Output; + prepExecParms[0].Value = DBNull.Value; - prepExecParms[2]=new SqlParameter("parameters",SqlDbType.NVarChar); - prepExecParms[2].Direction=ParameterDirection.Input; - - prepExecParms[3]=new SqlParameter("stmt",SqlDbType.NVarChar); - prepExecParms[3].Direction=ParameterDirection.Input; - - prepExecParms[4]=new SqlParameter("scrollopt",SqlDbType.Int); - prepExecParms[4].Direction=ParameterDirection.InputOutput; - - prepExecParms[5]=new SqlParameter("ccopt",SqlDbType.Int); - prepExecParms[5].Direction=ParameterDirection.InputOutput; - prepExecParms[5].Value=1;//Readonly - - prepExecParms[6]=new SqlParameter("rowcount",SqlDbType.Int); - prepExecParms[6].Direction=ParameterDirection.InputOutput; - - //-----------------Exec command - execCommand = new SqlCommand("sp_cursorexecute"); - execCommand.CommandType=CommandType.StoredProcedure; - execCommand.CommandTimeout = commandTimeout; - - execParms=new SqlParameter[5]; - execParms[0]=new SqlParameter("cursorId",SqlDbType.Int); - execParms[0].Direction = ParameterDirection.Input; - execParms[1]=new SqlParameter("handle",SqlDbType.Int); - execParms[1].Direction = ParameterDirection.Output; - execParms[2]=new SqlParameter("scrollopt",SqlDbType.Int); - execParms[2].Direction = ParameterDirection.InputOutput; - execParms[3]=new SqlParameter("ccopt",SqlDbType.Int); - execParms[3].Direction = ParameterDirection.InputOutput; - execParms[3].Value=1;//Readonly - execParms[4]=new SqlParameter("rowcount",SqlDbType.Int); - execParms[4].Direction = ParameterDirection.InputOutput; - - //------------------prepareCursor - prepareCommand = new SqlCommand("sp_cursorprepare"); - prepareCommand.CommandType=CommandType.StoredProcedure; - prepareCommand.CommandTimeout = commandTimeout; - prepareParms=new SqlParameter[6]; - - prepareParms[0]=new SqlParameter("cursor",SqlDbType.Int); - prepareParms[0].Direction = ParameterDirection.Output; - prepareParms[0].Value=DBNull.Value; - - prepareParms[1]=new SqlParameter("parameters",SqlDbType.NVarChar); - prepareParms[1].Direction = ParameterDirection.Input; + prepExecParms[1] = new SqlParameter("handle", SqlDbType.Int); + prepExecParms[1].Direction = ParameterDirection.Output; + prepExecParms[1].Value = 0; + + prepExecParms[2] = new SqlParameter("parameters", SqlDbType.NVarChar); + prepExecParms[2].Direction = ParameterDirection.Input; + + prepExecParms[3] = new SqlParameter("stmt", SqlDbType.NVarChar); + prepExecParms[3].Direction = ParameterDirection.Input; - prepareParms[2]=new SqlParameter("stmt",SqlDbType.NVarChar); - prepareParms[2].Direction = ParameterDirection.Input; + prepExecParms[4] = new SqlParameter("scrollopt", SqlDbType.Int); + prepExecParms[4].Direction = ParameterDirection.InputOutput; - prepareParms[3]=new SqlParameter("options",SqlDbType.Int); - prepareParms[3].Direction = ParameterDirection.Input; - prepareParms[3].Value=1; + prepExecParms[5] = new SqlParameter("ccopt", SqlDbType.Int); + prepExecParms[5].Direction = ParameterDirection.InputOutput; + prepExecParms[5].Value = 1;//Readonly - prepareParms[4]=new SqlParameter("scrollopt",SqlDbType.Int); - prepareParms[4].Direction = ParameterDirection.InputOutput; + prepExecParms[6] = new SqlParameter("rowcount", SqlDbType.Int); + prepExecParms[6].Direction = ParameterDirection.InputOutput; - prepareParms[5]=new SqlParameter("ccopt",SqlDbType.Int); - prepareParms[5].Direction = ParameterDirection.InputOutput; - prepareParms[5].Value=4; + //-----------------Exec command + execCommand = new SqlCommand("sp_cursorexecute"); + execCommand.CommandType = CommandType.StoredProcedure; + execCommand.CommandTimeout = commandTimeout; - //----------------Close command - closeCommand = new SqlCommand("sp_cursorclose"); - closeCommand.CommandType=CommandType.StoredProcedure; - closeCommand.CommandTimeout = commandTimeout; - SqlParameter handle4 = closeCommand.Parameters.Add("handle", SqlDbType.Int); - handle4.Direction = ParameterDirection.Input; + execParms = new SqlParameter[5]; + execParms[0] = new SqlParameter("cursorId", SqlDbType.Int); + execParms[0].Direction = ParameterDirection.Input; + execParms[1] = new SqlParameter("handle", SqlDbType.Int); + execParms[1].Direction = ParameterDirection.Output; + execParms[2] = new SqlParameter("scrollopt", SqlDbType.Int); + execParms[2].Direction = ParameterDirection.InputOutput; + execParms[3] = new SqlParameter("ccopt", SqlDbType.Int); + execParms[3].Direction = ParameterDirection.InputOutput; + execParms[3].Value = 1;//Readonly + execParms[4] = new SqlParameter("rowcount", SqlDbType.Int); + execParms[4].Direction = ParameterDirection.InputOutput; - //------------------unprepareCursor - unprepareCommand =new SqlCommand("sp_cursorunprepare"); - unprepareCommand.CommandType = CommandType.StoredProcedure; - unprepareCommand.CommandTimeout = commandTimeout; + //------------------prepareCursor + prepareCommand = new SqlCommand("sp_cursorprepare"); + prepareCommand.CommandType = CommandType.StoredProcedure; + prepareCommand.CommandTimeout = commandTimeout; + prepareParms = new SqlParameter[6]; - SqlParameter cursor1 = unprepareCommand.Parameters.Add("cursor", SqlDbType.Int); - cursor1.Direction = ParameterDirection.Input; + prepareParms[0] = new SqlParameter("cursor", SqlDbType.Int); + prepareParms[0].Direction = ParameterDirection.Output; + prepareParms[0].Value = DBNull.Value; + prepareParms[1] = new SqlParameter("parameters", SqlDbType.NVarChar); + prepareParms[1].Direction = ParameterDirection.Input; + + prepareParms[2] = new SqlParameter("stmt", SqlDbType.NVarChar); + prepareParms[2].Direction = ParameterDirection.Input; + + prepareParms[3] = new SqlParameter("options", SqlDbType.Int); + prepareParms[3].Direction = ParameterDirection.Input; + prepareParms[3].Value = 1; + + prepareParms[4] = new SqlParameter("scrollopt", SqlDbType.Int); + prepareParms[4].Direction = ParameterDirection.InputOutput; + + prepareParms[5] = new SqlParameter("ccopt", SqlDbType.Int); + prepareParms[5].Direction = ParameterDirection.InputOutput; + prepareParms[5].Value = 4; + + //----------------Close command + closeCommand = new SqlCommand("sp_cursorclose"); + closeCommand.CommandType = CommandType.StoredProcedure; + closeCommand.CommandTimeout = commandTimeout; + SqlParameter handle4 = closeCommand.Parameters.Add("handle", SqlDbType.Int); + handle4.Direction = ParameterDirection.Input; + + //------------------unprepareCursor + unprepareCommand = new SqlCommand("sp_cursorunprepare"); + unprepareCommand.CommandType = CommandType.StoredProcedure; + unprepareCommand.CommandTimeout = commandTimeout; + + SqlParameter cursor1 = unprepareCommand.Parameters.Add("cursor", SqlDbType.Int); + cursor1.Direction = ParameterDirection.Input; + } } } @@ -4148,6 +4148,7 @@ public MssqlConnectionWrapper(String connectionString, GxConnectionCache connCac } override public void Open() { + m_connectionCache.InitCommands(); InternalConnection.Open(); if (!m_autoCommit) { From edc63e55c8ecd5e1769cb59ef6fe7862aa01c405 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 26 Mar 2024 08:52:13 -0300 Subject: [PATCH 126/164] Embedded images within HTML bodies were not being recognized by the MailKit as an attachment. (#984) --- .../src/dotnetframework/GxMail/Pop3MailKit.cs | 55 +++++++++++++------ 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/dotnet/src/dotnetframework/GxMail/Pop3MailKit.cs b/dotnet/src/dotnetframework/GxMail/Pop3MailKit.cs index e2df4bcb3..54ce23d7c 100644 --- a/dotnet/src/dotnetframework/GxMail/Pop3MailKit.cs +++ b/dotnet/src/dotnetframework/GxMail/Pop3MailKit.cs @@ -15,6 +15,7 @@ internal class Pop3MailKit : Pop3SessionBase private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); private Pop3Client client; + const string INLINE_IMAGE_PREFIX = "cid:"; public override int GetMessageCount() { @@ -161,7 +162,7 @@ public override void Receive(GXPOP3Session sessionInfo, GXMailMessage gxmessage) } gxmessage.DateReceived = Internals.Pop3.MailMessage.GetMessageDate(GetHeaderFromMimeMessage(msg,"Delivery-Date")); AddHeader(gxmessage, "DispositionNotificationTo", GetHeaderFromMimeMessage(msg, "Disposition-Notification-To")); - ProcessMailAttachments(gxmessage, msg.Attachments); + ProcessMailAttachments(gxmessage, msg); } } } @@ -192,8 +193,9 @@ private string GetHeaderFromMimeMessage(MimeMessage msg, string headerValue) return msg.Headers.Contains(headerValue) ? msg.Headers[msg.Headers.IndexOf(headerValue)].ToString() : null; } - private void ProcessMailAttachments(GXMailMessage gxmessage, IEnumerable attachs) + private void ProcessMailAttachments(GXMailMessage gxmessage, MimeMessage msg) { + IEnumerable attachs = msg.Attachments; if (attachs == null) return; @@ -202,28 +204,49 @@ private void ProcessMailAttachments(GXMailMessage gxmessage, IEnumerable -1)); + } + + private void ProcessMailAttachment(GXMailMessage gxmessage, MimeEntity attach, string attachName) + { + if (!string.IsNullOrEmpty(attach.ContentId) && attach.ContentDisposition != null && !attach.ContentDisposition.IsAttachment) + { + string cid = INLINE_IMAGE_PREFIX + attach.ContentId; + attachName = String.Format("{0}_{1}", attach.ContentId, attachName); + gxmessage.HTMLText = gxmessage.HTMLText.Replace(cid, attachName); + } + try + { + SaveAttachedFile(attach, attachName); + gxmessage.Attachments.Add(attachName); + } + catch (Exception e) + { + LogError("Could not add Attachment", "Failed to save attachment", MailConstants.MAIL_InvalidAttachment, e, log); + } + + } + private void SaveAttachedFile(MimeEntity attach, string attachName) { using (var stream = File.Create(Path.Combine(AttachDir, attachName))) From 4e10eecbb39668813b310f39885d278ceff49098 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 2 Apr 2024 09:56:50 -0300 Subject: [PATCH 127/164] Adjust error level to warning when capturing exceptions while calling methods of the DB2 driver. (#985) --- dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2400.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2400.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2400.cs index b7397cd27..38ea9a538 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2400.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2400.cs @@ -652,7 +652,7 @@ public override void DisposeCommand(IDbCommand command) } catch (Exception ex) { - GXLogging.Error(log, "DisposeCommand error", ex); + GXLogging.Warn(log, "DisposeCommand error", ex); } } From 75c9b5bd212c479a16f7124daa348374b3bd75e4 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 2 Apr 2024 18:18:45 -0300 Subject: [PATCH 128/164] Add configuration option to enable the use of the SmallDateTime datatype in SQL Server. (#986) --- .../GxClasses/Data/GXDataADO.cs | 7 +++++- .../GxClasses/Data/GXDataCommon.cs | 25 +++++++++++-------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataADO.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataADO.cs index 22938b4ad..d48cea8a9 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataADO.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataADO.cs @@ -2719,7 +2719,12 @@ GxDataRecord getDbmsDataRecord(string id, string dbms) switch (dbms) { case "sqlserver": - return new GxSqlServer(); + GxSqlServer gxSqlServer = new GxSqlServer(); + if (Config.GetValueOf("Connection-" + id + "-UseSmallDateTime", out cfgBuf) && cfgBuf == "1") + { + gxSqlServer.UseSmallDateTime(); + } + return gxSqlServer; case "mysql": #if NETCORE return new GxMySqlConnector(id); diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs index a0556ea21..756a05e18 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs @@ -1599,7 +1599,12 @@ public class GxSqlServer : GxDataRecord private const string INTEGRATED_SECURITY_NO = "no"; #endif private bool multipleDatareadersEnabled; + private DateTime SqlServer_NullDateTime= SQLSERVER_NULL_DATETIME; + internal void UseSmallDateTime() + { + SqlServer_NullDateTime = SQLSERVER_NULL_SMALLDATETIME; + } public override int GetCommandTimeout() { return base.GetCommandTimeout(); @@ -2114,14 +2119,14 @@ public override DateTime Dbms2NetDate(IGxDbCommand cmd, IDataRecord DR, int i) public override DateTime Dbms2NetDateTime( DateTime dt, Boolean precision) { //DBMS MinDate => Genexus null Date - if (dt.Equals(SQLSERVER_NULL_DATE)) + if (dt.Equals(SqlServer_NullDateTime)) { return DateTimeUtil.NullDate(); } - if (dt.Year==SQLSERVER_NULL_DATE.Year && - dt.Month==SQLSERVER_NULL_DATE.Month && - dt.Day==SQLSERVER_NULL_DATE.Day) + if (dt.Year== SqlServer_NullDateTime.Year && + dt.Month== SqlServer_NullDateTime.Month && + dt.Day== SqlServer_NullDateTime.Day) { return new DateTime( @@ -2137,16 +2142,16 @@ public override Object Net2DbmsDateTime(IDbDataParameter parm, DateTime dt) //Genexus null => save DBMS MinDate if(dt.Equals(DateTimeUtil.NullDate())) { - return SQLSERVER_NULL_DATE; + return SqlServer_NullDateTime; } //Date < DBMS MinDate => save DBMS MinDate keeping the Time component - if (dt.CompareTo(SQLSERVER_NULL_DATE)<0) + if (dt.CompareTo(SqlServer_NullDateTime) <0) { DateTime aux = new DateTime( - SQLSERVER_NULL_DATE.Year,SQLSERVER_NULL_DATE.Month, - SQLSERVER_NULL_DATE.Day,dt.Hour,dt.Minute,dt.Second,dt.Millisecond); + SqlServer_NullDateTime.Year, SqlServer_NullDateTime.Month, + SqlServer_NullDateTime.Day,dt.Hour,dt.Minute,dt.Second,dt.Millisecond); return aux; } @@ -2161,8 +2166,8 @@ public override string ConcatOp(int pos) { return ConcatOpValues[pos]; } - - static DateTime SQLSERVER_NULL_DATE = new DateTime(1753,1,1) ; + static DateTime SQLSERVER_NULL_DATETIME = new DateTime(1753,1,1) ; + static DateTime SQLSERVER_NULL_SMALLDATETIME= new DateTime(1900, 1, 1); } public class GxDataReader: IDataReader From 979f610c5922146696e9a25a055614ab35fe94c9 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Thu, 4 Apr 2024 09:20:00 -0300 Subject: [PATCH 129/164] GetApplicationPath was wrong when used from REST services hosted at the root. (#988) --- dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs | 2 +- .../DotNetCoreWebUnitTest/Middleware/RestServiceTest.cs | 2 +- dotnet/test/DotNetCoreWebUnitTest/apps/saveimage.cs | 9 ++++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs index 5e8c94e0a..819ca275f 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs @@ -465,7 +465,7 @@ public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHos app.UseWebSockets(); string basePath = string.IsNullOrEmpty(VirtualPath) ? string.Empty : $"/{VirtualPath}"; - Config.ScriptPath = basePath; + Config.ScriptPath = string.IsNullOrEmpty(basePath) ? "/" : basePath; app.MapWebSocketManager(basePath); app.MapWhen( diff --git a/dotnet/test/DotNetCoreWebUnitTest/Middleware/RestServiceTest.cs b/dotnet/test/DotNetCoreWebUnitTest/Middleware/RestServiceTest.cs index c2e3bec54..49dbbfe4f 100644 --- a/dotnet/test/DotNetCoreWebUnitTest/Middleware/RestServiceTest.cs +++ b/dotnet/test/DotNetCoreWebUnitTest/Middleware/RestServiceTest.cs @@ -49,7 +49,7 @@ public async Task TestSimpleRestPost() response.EnsureSuccessStatusCode(); Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); string responseBody = await response.Content.ReadAsStringAsync(); - Assert.Equal("{}", responseBody); + Assert.Equal("{\"ImagePath\":\"\\/imageName\"}", responseBody); } [Fact(Skip = "Non deterministic")] diff --git a/dotnet/test/DotNetCoreWebUnitTest/apps/saveimage.cs b/dotnet/test/DotNetCoreWebUnitTest/apps/saveimage.cs index e8c415716..3e7ab5e12 100644 --- a/dotnet/test/DotNetCoreWebUnitTest/apps/saveimage.cs +++ b/dotnet/test/DotNetCoreWebUnitTest/apps/saveimage.cs @@ -1,7 +1,8 @@ using GeneXus.Application; using GeneXus.Data.NTier; - +using GeneXus.Http.Server; using GeneXus.Procedure; +using Stubble.Core.Contexts; namespace GeneXus.Programs.apps { public class saveimage : GXProcedure @@ -19,9 +20,10 @@ public saveimage(IGxContext context) IsMain = false; } - public void execute(string aP0_ImageDescription, string aP1_Image) + public void execute(string aP0_ImageDescription, string aP1_Image, out string aP2_ImagePath) { System.Console.WriteLine("SaveImage executed:" + aP0_ImageDescription); + aP2_ImagePath= context.GetScriptPath() + aP1_Image; } public override bool UploadEnabled() @@ -32,8 +34,9 @@ public override bool UploadEnabled() public override void initialize() { - + httpResponse = new GxHttpResponse(context); } + GxHttpResponse httpResponse; } } From b6344a511de68ddb54bee963d6446effeb75c219 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:40:16 -0300 Subject: [PATCH 130/164] Bump version to 1.30 after creating branch for v18u9 --- dotnet/Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/Directory.Build.props b/dotnet/Directory.Build.props index 8c49dd095..1be77468d 100644 --- a/dotnet/Directory.Build.props +++ b/dotnet/Directory.Build.props @@ -3,7 +3,7 @@ 11.0.0.0 1 $([MSBuild]::Add($(MajorFileVersion), 100)) - 29 + 30 $(COMMIT_NUMBER) 0 $(MajorFileVersion).$(MinorFileVersion).$(PatchFileVersion) From 3709a3ab4ae31cc31022ffca1d6f5f4e5198aa60 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 9 Apr 2024 16:12:54 -0300 Subject: [PATCH 131/164] Support new picture formats with formatters # and ? (#950) * Support new picture formats with formatters # and ? * Add new test cases. Improve pictures that have only '?' at the right part when applied to whole numbers. --- .../GxClasses/Core/GXUtilsCommon.cs | 253 +++++++++++++++--- .../DotNetCoreUnitTest.csproj | 3 +- .../StringUtil/StringUtilTests.cs | 64 ----- .../test/DotNetUnitTest/DotNetUnitTest.csproj | 3 + .../StringUtil/StringUtilTests.cs | 180 +++++++++++++ 5 files changed, 403 insertions(+), 100 deletions(-) delete mode 100644 dotnet/test/DotNetCoreUnitTest/StringUtil/StringUtilTests.cs create mode 100644 dotnet/test/DotNetUnitTest/StringUtil/StringUtilTests.cs diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs index a567717dc..21cf5a104 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs @@ -665,18 +665,83 @@ private enum FORMAT_SECTION NEGATIVE_VALUES = -1, ZEROS = 0 } - private static string GxPictureToNetPicture(string gxpicture, bool separatorsAsLiterals, FORMAT_SECTION section) + const char ESCAPE_CHARACTER = '\\'; + const char NUMBER_SIGN = '#'; + const char QUESTION_MARK = '?'; + const char BLANK = ' '; + static bool EscapedSymbol(string picture, int idx) + { + return (idx > 0 && picture[idx - 1] == ESCAPE_CHARACTER); + } + static int LeadingBlanks(string gxpicture) + { + int leadingBlanks = 0; + bool inBlanks = false; + if (gxpicture.Contains(QUESTION_MARK)) { + for (int i = 0; i < gxpicture.Length; i++) + { + if (gxpicture[i] == QUESTION_MARK && !EscapedSymbol(gxpicture, i)) + { + inBlanks = true; + } + else if ((gxpicture[i] == '.') && !EscapedSymbol(gxpicture, i)) + { + inBlanks = false; + break; + } + + if (inBlanks) + leadingBlanks++; + } + } + return leadingBlanks; + } + static int TrailingBlanks(string gxpicture, out bool decimalsAsBlank) + { + int trailingBlanks = 0; + int sep = gxpicture.IndexOf('.'); + decimalsAsBlank = false; + if (sep >= 0) + { + string rightPic = gxpicture.Substring(sep); + if (rightPic.Contains(QUESTION_MARK)) + { + for (int i = gxpicture.Length-1; i >= 0; i--) + { + if (gxpicture[i] == QUESTION_MARK && !EscapedSymbol(gxpicture, i)) + trailingBlanks++; + else if (gxpicture[i] == '.') + { + decimalsAsBlank = true; + break; + } + else if (gxpicture[i] == NUMBER_SIGN || gxpicture[i] == 'Z' || gxpicture[i] == '9') + { + decimalsAsBlank = false; + break; + } + } + } + } + return trailingBlanks; + } + + private static string GxPictureToNetPicture(string gxpicture, bool separatorsAsLiterals, FORMAT_SECTION section, int digits, int decimals) { if (string.IsNullOrEmpty(gxpicture)) return string.Empty; bool inDecimals = false; StringBuilder strPicture = new StringBuilder("{0,"); - strPicture.Append(gxpicture.Length); + strPicture.Append(PictureLength(gxpicture)); strPicture.Append(':'); bool blankwhenzero = true; bool explicitSign = (gxpicture[0] == '+'); bool withoutMinusSign = (gxpicture[0] == '(' && gxpicture[gxpicture.Length - 1] == ')') || gxpicture.EndsWith("DB") || explicitSign; + int totalLeadingBlanks = LeadingBlanks(gxpicture); + int totalRighBlanks = TrailingBlanks(gxpicture, out bool decimalsAsBlank); + int lBlanks = 0; + int rDigits = 0; if (section == FORMAT_SECTION.NEGATIVE_VALUES && withoutMinusSign) //If it has a sign, then use the first section (which by default assigns only a negative sign). @@ -688,9 +753,34 @@ private static string GxPictureToNetPicture(string gxpicture, bool separatorsAsL strPicture.Append(';');//Section Separator. strPicture.Append(';');//Section Separator. } + if (gxpicture.IndexOf(ESCAPE_CHARACTER) >= 0) + { + StringBuilder gxEscapedPicture = new StringBuilder(); + for (int i = 0; i < gxpicture.Length; i++) + { + + if (gxpicture[i] == ESCAPE_CHARACTER && i + 1 < gxpicture.Length && gxpicture[i + 1] == ESCAPE_CHARACTER) + { + gxEscapedPicture.Append(ESCAPE_CHARACTER); + gxEscapedPicture.Append(ESCAPE_CHARACTER); + gxEscapedPicture.Append(ESCAPE_CHARACTER); + i++; + } + else + { + gxEscapedPicture.Append(gxpicture[i]); + } + } + gxpicture = gxEscapedPicture.ToString(); + } for (int i = 0; i < gxpicture.Length; i++) { - if (gxpicture[i] == 'Z') + bool inLiteral = EscapedSymbol(gxpicture, i); + if (inLiteral || gxpicture[i] == ESCAPE_CHARACTER) + { + strPicture.Append(gxpicture[i]); + } + else if (gxpicture[i] == 'Z') { if (inDecimals) { @@ -701,7 +791,39 @@ private static string GxPictureToNetPicture(string gxpicture, bool separatorsAsL strPicture.Append('0'); } else - strPicture.Append('#'); + strPicture.Append(NUMBER_SIGN); + } + else if (gxpicture[i] == NUMBER_SIGN) + { + strPicture.Append(NUMBER_SIGN); + } + else if (gxpicture[i] == QUESTION_MARK) + { + if (inDecimals) + { + if (rDigits >= decimals && rDigits < totalRighBlanks) + { + strPicture.Append(BLANK); + } + else + { + strPicture.Append(NUMBER_SIGN); + } + rDigits++; + } + else + { + if (lBlanks < (totalLeadingBlanks - digits)) + { + strPicture.Append(BLANK); + lBlanks++; + } + else + { + strPicture.Append(NUMBER_SIGN); + } + } + } else if (gxpicture[i] == '9') { @@ -711,11 +833,20 @@ private static string GxPictureToNetPicture(string gxpicture, bool separatorsAsL else if (gxpicture[i] == '.') { inDecimals = true; - if (i > 0 && strPicture[strPicture.Length - 1] == '#') strPicture[strPicture.Length - 1] = '0'; + if (i > 0 && strPicture[strPicture.Length - 1] == NUMBER_SIGN) strPicture[strPicture.Length - 1] = '0'; if (separatorsAsLiterals) strPicture.Append("\".\""); else - strPicture.Append(gxpicture[i]); + { + if (decimalsAsBlank && decimals == 0) + { + strPicture.Append(BLANK); //Replace decimal separator by blank + } + else + { + strPicture.Append(gxpicture[i]); + } + } } else if (gxpicture[i] == ',') { @@ -724,6 +855,10 @@ private static string GxPictureToNetPicture(string gxpicture, bool separatorsAsL else strPicture.Append(gxpicture[i]); } + else if (gxpicture[i] == BLANK) + { + strPicture.Append(BLANK); + } else { //0,#,.,,,%,E0, E+0, E-0,e0,e+0,e-0, are characters with special meaning in Custom Numeric Format Strings of .net @@ -740,7 +875,7 @@ private static string GxPictureToNetPicture(string gxpicture, bool separatorsAsL //Pictures (99.9) => 12.5 -12.5 if (section != FORMAT_SECTION.NEGATIVE_VALUES && withoutMinusSign && (i == 0 || i == gxpicture.Length - 1)) { - strPicture.Append(' '); + strPicture.Append(BLANK); } else { @@ -751,7 +886,7 @@ private static string GxPictureToNetPicture(string gxpicture, bool separatorsAsL //Pictures +99.9 => +12.5 -12.5 if (explicitSign && i == 0 && section == FORMAT_SECTION.ZEROS) { - strPicture.Append(' '); + strPicture.Append(BLANK); } else if (explicitSign && i == 0 && section == FORMAT_SECTION.NEGATIVE_VALUES) { @@ -769,7 +904,7 @@ private static string GxPictureToNetPicture(string gxpicture, bool separatorsAsL if (section == FORMAT_SECTION.POSITIVE_VALUES) strPicture.Append('C'); else - strPicture.Append(' '); + strPicture.Append(BLANK); } else { @@ -782,7 +917,7 @@ private static string GxPictureToNetPicture(string gxpicture, bool separatorsAsL if (section == FORMAT_SECTION.POSITIVE_VALUES) strPicture.Append('R'); else - strPicture.Append(' '); + strPicture.Append(BLANK); } else { @@ -799,14 +934,29 @@ private static string GxPictureToNetPicture(string gxpicture, bool separatorsAsL } if (blankwhenzero && section == FORMAT_SECTION.ZEROS)//Z,ZZZ,ZZZ.ZZ format 0.00 to "". sac.20145 { - return Replicate(' ', gxpicture.Length); + return Replicate(BLANK, gxpicture.Length); } else { return strPicture.Append('}').ToString(); } } - static bool useLiteralSeparators(string gxpicture) + + private static int PictureLength(string gxpicture) + { + int count = 0; + if (gxpicture.Contains(ESCAPE_CHARACTER)) + { + foreach (char ch in gxpicture) + { + if (ch == ESCAPE_CHARACTER) + count++; + } + } + return gxpicture.Length - count; + } + + static bool UseLiteralSeparators(string gxpicture) { // If it has non-numerical characters, then the separators are used as literals @@ -861,7 +1011,7 @@ public static string GetPictureFromLD(int digits, int decimals, int thousandSepL } else { - str.Append('#'); + str.Append(NUMBER_SIGN); } } } @@ -877,14 +1027,14 @@ public static string GetPictureFromLD(int digits, int decimals, int thousandSepL } public static string Concat(string init, string last) { - char[] trimChars = { ' ' }; + char[] trimChars = { BLANK }; StringBuilder fmtString = new StringBuilder(init.TrimEnd(trimChars)); fmtString.Append(last); return fmtString.ToString(); } public static string Concat(string init, string last, string separator) { - char[] trimChars = { ' ' }; + char[] trimChars = { BLANK }; StringBuilder fmtString = new StringBuilder(init.TrimEnd(trimChars)); fmtString.Append(separator); fmtString.Append(last); @@ -1011,7 +1161,7 @@ static public int Len(string s) static public string Trim(string s) { if (!string.IsNullOrEmpty(s)) - return s.Trim(' '); + return s.Trim(BLANK); else return s; } @@ -1020,8 +1170,8 @@ static public string RTrim(string s) if (!string.IsNullOrEmpty(s)) { int len = s.Length; - if (len > 0 && s[len - 1] == ' ') - return s.TrimEnd(' '); + if (len > 0 && s[len - 1] == BLANK) + return s.TrimEnd(BLANK); else return s; } @@ -1033,8 +1183,8 @@ static public string LTrim(string s) if (!string.IsNullOrEmpty(s)) { int len = s.Length; - if (len > 0 && s[0] == ' ') - return s.TrimStart(' '); + if (len > 0 && s[0] == BLANK) + return s.TrimStart(BLANK); else return s; } @@ -1166,9 +1316,14 @@ public string Format(decimal value, string gxpicture) { section = FORMAT_SECTION.ZEROS; } - bool separatorsAsLiterals = useLiteralSeparators(gxpicture); + bool separatorsAsLiterals = UseLiteralSeparators(gxpicture); + string invariantStrValue = Math.Abs(value).ToString(CultureInfo.InvariantCulture.NumberFormat); + int decSeparatorIdx = invariantStrValue.IndexOf(CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator); + + int digits = WholeDigits(value, invariantStrValue, decSeparatorIdx); + int decimals = DecimalDigits(invariantStrValue, decSeparatorIdx); - string picture = GxPictureToNetPicture(gxpicture, separatorsAsLiterals, section); + string picture = GxPictureToNetPicture(gxpicture, separatorsAsLiterals, section, digits, decimals); //It must consider format because it can have other types of characters that are not Z or 9 or. neither ,. string res; if (!string.IsNullOrEmpty(picture)) @@ -1177,7 +1332,7 @@ public string Format(decimal value, string gxpicture) } else { - res = value.ToString(CultureInfo.InvariantCulture.NumberFormat); + res = invariantStrValue; } if (separatorsAsLiterals) { @@ -1191,7 +1346,35 @@ public string Format(decimal value, string gxpicture) { return ReplaceSeparators(res, numFmtInfo.NumberDecimalSeparator, numFmtInfo.NumberGroupSeparator); } + } + int DecimalDigits(string invariantStrValue, int decSeparatorIdx) + { + int decimals; + if (decSeparatorIdx < 0) + decimals = 0; + else + decimals = invariantStrValue.Length - decSeparatorIdx - 1; + return decimals; + } + int WholeDigits(decimal value, string invariantStrValue, int decSeparatorIdx) + { + int digits; + if (value == 0) + { + digits = 1; + } + else if (value < 1 && value >= 0) + digits = 0; + else if (decSeparatorIdx < 0) + { + digits = invariantStrValue.Length; + } + else + { + digits = decSeparatorIdx; + } + return digits; } string FormatNumber(string s, string p) { @@ -1218,7 +1401,7 @@ string FormatNumber(string s, string p, string decSep, string thousandsSep) pStart = p.Length; else pDec = p.Length - pStart; // decimal count (including point) - StringBuilder result = new StringBuilder(new string(' ', Math.Max(p.Length, s.Length))); + StringBuilder result = new StringBuilder(new string(BLANK, Math.Max(p.Length, s.Length))); // Process the left of the decimal point j = sStart - 1; k = pStart - 1; @@ -1229,7 +1412,7 @@ string FormatNumber(string s, string p, string decSep, string thousandsSep) case '9': if (j < 0) result[k--] = '0'; - else if (s[j] == ' ') + else if (s[j] == BLANK) result[k--] = '0'; else result[k--] = s[j]; @@ -1237,10 +1420,10 @@ string FormatNumber(string s, string p, string decSep, string thousandsSep) break; case 'Z': if (j < 0) - result[k--] = ' '; + result[k--] = BLANK; else if (leftZ || leftZero(s, j)) { - result[k--] = ' '; + result[k--] = BLANK; leftZ = true; } else @@ -1288,7 +1471,7 @@ string FormatNumber(string s, string p, string decSep, string thousandsSep) case 'Z': if (rightZ || rightZero(s, j)) { - result[i] = ' '; + result[i] = BLANK; rightZ = true; } else if (j < s.Length) @@ -1392,7 +1575,7 @@ static public bool ToBoolean(string value) } public static string Space(int spaces) { - return new string(' ', spaces); + return new string(BLANK, spaces); } public static string Right(string text, int size) { @@ -1418,7 +1601,7 @@ public static string Left(string text, int size) static public bool Like(string str, string ptrn) { - return Like(str, ptrn, ' '); + return Like(str, ptrn, BLANK); } static public bool Like(string str, string ptrn, char escape) { @@ -1443,10 +1626,10 @@ static public bool Like(string str, string ptrn, char escape) srchPtr = 0; scapeCount = 0; - wildChr = ' '; - srchChr = ' '; + wildChr = BLANK; + srchChr = BLANK; - bool useEscape = escape != ' '; + bool useEscape = escape != BLANK; bool isEscape = false; bool applyEscape = false; @@ -1463,7 +1646,7 @@ static public bool Like(string str, string ptrn, char escape) if (srchPtr <= srchLen) srchChr = str[srchPtr - scapeCount]; else - srchChr = ' '; + srchChr = BLANK; } if (isEscape) @@ -1624,7 +1807,7 @@ public static string JSONEncode(string s) sb.Append("\\r"); else { - if (ch < ' ') + if (ch < BLANK) { sb.Append("\\u"); sb.Append(((int)ch).ToString("x4", CultureInfo.InvariantCulture)); diff --git a/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj b/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj index fd445e3c2..dafd99b31 100644 --- a/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj +++ b/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj @@ -36,7 +36,8 @@ - + + diff --git a/dotnet/test/DotNetCoreUnitTest/StringUtil/StringUtilTests.cs b/dotnet/test/DotNetCoreUnitTest/StringUtil/StringUtilTests.cs deleted file mode 100644 index 40a1f15bb..000000000 --- a/dotnet/test/DotNetCoreUnitTest/StringUtil/StringUtilTests.cs +++ /dev/null @@ -1,64 +0,0 @@ -using GeneXus.Application; -using GeneXus.Programs; -using GeneXus.Utils; -using Xunit; - -namespace xUnitTesting -{ - public class StringUtilTests - { - [Fact] - public void TestJSONEncodeDoNotEncodeGreaterCharacter() - { - string json = ""; - json += ""; - json +=" "; - json +=" "; - json +=" "; - json +=" -88.076680,43.945580 -88.077480,43.945930 -88.078530,43.946390 -88.078960"; - json +=" "; - json +=" #MyLine"; - json +=" "; - json +=""; - 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); - Assert.Equal(jsonEncoded, expectedJsonEncoded); - - } - [Fact] - public void TestFromJsonSDTWithBlankDateTime() - { - SdtSDT1_SDT1Item sdt = new SdtSDT1_SDT1Item(); - JObject json = new JObject(); - json["SDT1_DateTime"] = " 00:00:00"; - json["SDT1_Name"]=string.Empty; - json["SDT1_No"] = 0; - - sdt.FromJSONObject(json); - Assert.Equal(sdt.gxTpr_Sdt1_datetime, DateTimeUtil.NullDate()); - } - - [Fact] - public void TestFromJsonSDTWithTimeMustNotApplyTimezone() - { - SdtSDT1_SDT1Item sdt = new SdtSDT1_SDT1Item(); - JObject json = new JObject(); - json["SDT1_DateTime"] = "2014-04-29T14:29:40"; - json["SDT1_Name"] = string.Empty; - json["SDT1_No"] = 0; - - sdt.FromJSONObject(json); - Assert.Equal(14, sdt.gxTpr_Sdt1_datetime.Hour); - Assert.Equal(29, sdt.gxTpr_Sdt1_datetime.Minute); - } - - - } -} diff --git a/dotnet/test/DotNetUnitTest/DotNetUnitTest.csproj b/dotnet/test/DotNetUnitTest/DotNetUnitTest.csproj index a38f9452e..e2b6fd86e 100644 --- a/dotnet/test/DotNetUnitTest/DotNetUnitTest.csproj +++ b/dotnet/test/DotNetUnitTest/DotNetUnitTest.csproj @@ -14,6 +14,9 @@ + + + PreserveNewest diff --git a/dotnet/test/DotNetUnitTest/StringUtil/StringUtilTests.cs b/dotnet/test/DotNetUnitTest/StringUtil/StringUtilTests.cs new file mode 100644 index 000000000..58308c98a --- /dev/null +++ b/dotnet/test/DotNetUnitTest/StringUtil/StringUtilTests.cs @@ -0,0 +1,180 @@ +using GeneXus.Application; +using GeneXus.Programs; +using GeneXus.Utils; +#if !NETCORE +using Jayrock.Json; +#endif +using Xunit; + +namespace xUnitTesting +{ + public class StringUtilTests + { + [Fact] + public void TestJSONEncodeDoNotEncodeGreaterCharacter() + { + string json = ""; + json += ""; + json +=" "; + json +=" "; + json +=" "; + json +=" -88.076680,43.945580 -88.077480,43.945930 -88.078530,43.946390 -88.078960"; + json +=" "; + json +=" #MyLine"; + json +=" "; + json +=""; + 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); + Assert.Equal(jsonEncoded, expectedJsonEncoded); + + } + [Fact] + public void TestFromJsonSDTWithBlankDateTime() + { + SdtSDT1_SDT1Item sdt = new SdtSDT1_SDT1Item(); + JObject json = new JObject(); + json["SDT1_DateTime"] = " 00:00:00"; + json["SDT1_Name"]=string.Empty; + json["SDT1_No"] = 0; + + sdt.FromJSONObject(json); + Assert.Equal(sdt.gxTpr_Sdt1_datetime, DateTimeUtil.NullDate()); + } + + [Fact] + public void TestFromJsonSDTWithTimeMustNotApplyTimezone() + { + SdtSDT1_SDT1Item sdt = new SdtSDT1_SDT1Item(); + JObject json = new JObject(); + json["SDT1_DateTime"] = "2014-04-29T14:29:40"; + json["SDT1_Name"] = string.Empty; + json["SDT1_No"] = 0; + + sdt.FromJSONObject(json); + Assert.Equal(14, sdt.gxTpr_Sdt1_datetime.Hour); + Assert.Equal(29, sdt.gxTpr_Sdt1_datetime.Minute); + } + [Fact] + public void TestZPictureCompatibiliy() + { + string picture = "$ 9.99"; + GxContext context = new GxContext(); + decimal decNumber = 5; + string decStr = context.localUtil.Format(decNumber, picture); + Assert.Equal("$ 5.00", decStr); + } + [Fact] + public void TestZPictureWithEscapeChar() + { + string picture = "\\\\\" ZZ,ZZZ,ZZ9"; + GxContext context = new GxContext(); + decimal decNumber = 87654321; + string decStr = context.localUtil.Format(decNumber, picture); + Assert.Equal("\\\" 87,654,321", decStr); + } + [Fact] + public void TestZPicture() + { + GxContext context = new GxContext(); + decimal decNumber = 123456.12M; + string decStr = context.localUtil.Format(decNumber, "ZZZZZZZZZZ9.ZZZZZZ"); + Assert.Equal(" 123456.120000", decStr); + + decStr = context.localUtil.Format(decNumber, "ZZZZZZZZZZ9.999999"); + Assert.Equal(" 123456.120000", decStr); + + decStr = context.localUtil.Format(decNumber, "99999999999.999999"); + Assert.Equal("00000123456.120000", decStr); + + decStr = context.localUtil.Format(decNumber, "##########9.######"); + Assert.Equal(" 123456.12", decStr); + + decStr = context.localUtil.Format(decNumber, "??????????9.??????"); + Assert.Equal(" 123456.12 ", decStr); + + decStr = context.localUtil.Format(decNumber, "\\# ??????????9.??????"); + Assert.Equal("# 123456.12 ", decStr); + + + decStr = context.localUtil.Format(decNumber, "##,###,###,##9.######"); + Assert.Equal(" 123,456.12", decStr); + + decStr = context.localUtil.Format(decNumber, "??,???,???,??9.??????"); + Assert.Equal(" 123456.12 ", decStr); + + //=====================Zero======================================== + + decNumber = 0; + + decStr = context.localUtil.Format(decNumber, "ZZZZZZZZZZ9.ZZZZZZ"); + Assert.Equal(" 0.000000", decStr); + + decStr = context.localUtil.Format(decNumber, "###########.######"); + Assert.Equal(" ", decStr); + + decStr = context.localUtil.Format(decNumber, "???????????.??????"); + Assert.Equal(" ", decStr); + + decStr = context.localUtil.Format(decNumber, "(??????????9.??????)"); + Assert.Equal(" 0 ", decStr); + + decStr = context.localUtil.Format(decNumber, "\\# ??????????9.??????"); + Assert.Equal("# 0 ", decStr); + + decStr = context.localUtil.Format(decNumber, "(##########9.######)"); + Assert.Equal(" 0 ", decStr); + + //=====================One======================================== + + decNumber = 1; + + decStr = context.localUtil.Format(decNumber, "ZZZZZZZZZZ9.ZZZZZZ"); + Assert.Equal(" 1.000000", decStr); + + decStr = context.localUtil.Format(decNumber, "###########.######"); + Assert.Equal(" 1", decStr); + + decStr = context.localUtil.Format(decNumber, "???????????.??????"); + Assert.Equal(" 1 ", decStr); + + decStr = context.localUtil.Format(decNumber, "(??????????9.??????)"); + Assert.Equal(" 1 ", decStr); + + decStr = context.localUtil.Format(decNumber, "\\# ??????????9.??????"); + Assert.Equal("# 1 ", decStr); + + decStr = context.localUtil.Format(decNumber, "(##########9.######)"); + Assert.Equal(" 1 ", decStr); + + //=====================0.1======================================== + decNumber = 0.1M; + decStr = context.localUtil.Format(decNumber, "???????????.??????"); + Assert.Equal(" .1 ", decStr); + + + //=====================Negatives======================================== + decNumber = -123456.12M; + decStr = context.localUtil.Format(decNumber, "(??????????9.??????)"); + Assert.Equal("( 123456.12 )", decStr); + + decStr = context.localUtil.Format(decNumber, "(##########9.######)"); + Assert.Equal(" (123456.12)", decStr); + + //=====================Positives======================================== + decNumber = 123456.12M; + decStr = context.localUtil.Format(decNumber, "+ ??????????9.??????"); + Assert.Equal("+ 123456.12 ", decStr); + + decStr = context.localUtil.Format(decNumber, "+ ##########9.######"); + Assert.Equal(" + 123456.12", decStr); + + } + } +} From e94c5ecb7143b3b2019ef02dcd683ffc47a9912b Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Thu, 11 Apr 2024 11:22:53 -0300 Subject: [PATCH 132/164] Add async interfaces for http procedures (#987) * Add async interfaces for http procedures * Define protected property AsyncEnabled and internal method GetAsyncEnabledInternal. * Improve performance on GetAjaxEncryptionKey. Don not print DumpHeaders if log is off --- .../Middleware/HandlerFactory.cs | 13 +- .../GxClasses/Core/GXApplication.cs | 17 +++ .../GxClasses/Core/Web/HttpAjaxContext.cs | 39 +++--- .../GxClasses/Data/GXDataADO.cs | 83 ++++++++++++- .../GxClasses/Data/GXDataCommon.cs | 22 ++++ .../GxClasses/Data/GXDataDb2.cs | 16 ++- .../GxClasses/Data/GXDataHana.cs | 17 ++- .../GxClasses/Data/GXDataNTierService.cs | 1 - .../GxClasses/Helpers/GXLogging.cs | 9 ++ .../GxClasses/Middleware/GXHttp.cs | 117 +++++++++++++++++- .../GxClasses/Model/GXBaseObject.cs | 59 ++++++++- .../GxClasses/Model/GXWebProcedure.cs | 8 ++ .../Middleware/HttpProcTest.cs | 34 +++++ .../apps/aprochttpgetstatic.cs | 111 +++++++++++++++++ 14 files changed, 518 insertions(+), 28 deletions(-) create mode 100644 dotnet/test/DotNetCoreWebUnitTest/Middleware/HttpProcTest.cs create mode 100644 dotnet/test/DotNetCoreWebUnitTest/apps/aprochttpgetstatic.cs diff --git a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/HandlerFactory.cs b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/HandlerFactory.cs index e71b29279..d072c5d27 100644 --- a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/HandlerFactory.cs +++ b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/HandlerFactory.cs @@ -8,6 +8,7 @@ using GeneXus.Configuration; using GeneXus.Http; using GeneXus.Mime; +using GeneXus.Procedure; using GeneXus.Utils; using Microsoft.AspNetCore.Http; @@ -74,8 +75,16 @@ public async Task Invoke(HttpContext context) handler.sendAdditionalHeaders(); return Task.CompletedTask; }); - handler.ProcessRequest(context); - await Task.CompletedTask; + GXWebProcedure gxWebProc = handler as GXWebProcedure; + if (gxWebProc != null && gxWebProc.GetAsyncEnabledInternal()) + { + await gxWebProc.ProcessRequestAsync(context); + } + else + { + handler.ProcessRequest(context); + await Task.CompletedTask; + } handler.ControlOutputWriter?.Flush(); } else diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs index b1e9a1469..8ec7b8ee8 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs @@ -49,6 +49,8 @@ namespace GeneXus.Application using System.Security.Claims; using System.Security; using Microsoft.Net.Http.Headers; + using System.Threading.Tasks; + using GeneXus.Data.ADO; public interface IGxContext { @@ -1407,12 +1409,27 @@ public IGxDataStore GetDataStore(string id) return ds; return null; } +#if NETCORE + internal async Task CloseConnectionsAsync() + { + GxUserInfo.RemoveHandle(this.handle); + foreach (GxDataStore ds in _DataStores) + await ds.CloseConnectionsAsync(); + + CloseConnectionsResources(); + } +#endif public void CloseConnections() { GxUserInfo.RemoveHandle(this.handle); foreach (IGxDataStore ds in _DataStores) ds.CloseConnections(); + CloseConnectionsResources(); + } + + private void CloseConnectionsResources() + { if (_reportHandlerToClose != null) { for (int i = 0; i < _reportHandlerToClose.Count; i++) diff --git a/dotnet/src/dotnetframework/GxClasses/Core/Web/HttpAjaxContext.cs b/dotnet/src/dotnetframework/GxClasses/Core/Web/HttpAjaxContext.cs index 7092be321..b78405faa 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/Web/HttpAjaxContext.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/Web/HttpAjaxContext.cs @@ -685,29 +685,36 @@ internal static JArray GetParmsJArray(Object[] parms) public string GetAjaxEncryptionKey() { - if (context.ReadSessionKey(CryptoImpl.AJAX_ENCRYPTION_KEY) == null) + string ajaxKey = context.ReadSessionKey(CryptoImpl.AJAX_ENCRYPTION_KEY); + if (ajaxKey == null) { - if(!RecoverEncryptionKey()) - context.WriteSessionKey(CryptoImpl.AJAX_ENCRYPTION_KEY,CryptoImpl.GetRijndaelKey()); + string sessionKey; + if (!RecoverEncryptionKey(out sessionKey)) { + ajaxKey = CryptoImpl.GetRijndaelKey(); + context.WriteSessionKey(CryptoImpl.AJAX_ENCRYPTION_KEY, ajaxKey); + } + else + { + ajaxKey = sessionKey; + } } - return context.ReadSessionKey(CryptoImpl.AJAX_ENCRYPTION_KEY); + return ajaxKey; } - private bool RecoverEncryptionKey() + private bool RecoverEncryptionKey(out string sessionKey) { - if ( (context.ReadSessionKey(CryptoImpl.AJAX_ENCRYPTION_KEY) == null)) + sessionKey = null; + if (context.HttpContext != null) { - if (context.HttpContext != null) + String clientKey = context.HttpContext.Request.Headers[CryptoImpl.AJAX_SECURITY_TOKEN]; + if (!string.IsNullOrEmpty(clientKey)) { - String clientKey = context.HttpContext.Request.Headers[CryptoImpl.AJAX_SECURITY_TOKEN]; - if (!string.IsNullOrEmpty(clientKey)) + bool correctKey; + clientKey = CryptoImpl.DecryptRijndael(CryptoImpl.GX_AJAX_PRIVATE_IV + clientKey, CryptoImpl.GX_AJAX_PRIVATE_KEY, out correctKey); + if (correctKey) { - bool correctKey = false; - clientKey = CryptoImpl.DecryptRijndael(CryptoImpl.GX_AJAX_PRIVATE_IV + clientKey, CryptoImpl.GX_AJAX_PRIVATE_KEY, out correctKey); - if (correctKey) - { - context.WriteSessionKey(CryptoImpl.AJAX_ENCRYPTION_KEY, clientKey); - return true; - } + sessionKey = clientKey; + context.WriteSessionKey(CryptoImpl.AJAX_ENCRYPTION_KEY, clientKey); + return true; } } } diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataADO.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataADO.cs index d48cea8a9..7cfe94720 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataADO.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataADO.cs @@ -8,6 +8,7 @@ using System.IO; using System.Reflection; using System.Threading; +using System.Threading.Tasks; using GeneXus.Application; using GeneXus.Cache; using GeneXus.Configuration; @@ -212,7 +213,22 @@ public void RemoveAllConnections(int handle) throw e; } } +#if NETCORE + internal async Task RemoveConnectionAsync(int handle, string dataSource) + { + ServerUserInformation sui; + if (userConnections.TryGetValue(handle, out sui)) + { + GXLogging.Debug(log, "RemoveConnection handle " + handle + ",datasource:" + dataSource); + GxConnection con = sui[dataSource]; + if (sui.TryRemove(dataSource, out con)) + await con.DisposeAsync(); + ServerUserInformation suiDeleted; + if (sui.Count == 0) userConnections.TryRemove(handle, out suiDeleted); + } + } +#endif public void RemoveConnection(int handle, string dataSource) { @@ -411,7 +427,12 @@ public void Dispose() { Close(); } - +#if NETCORE + internal async Task DisposeAsync() + { + await CloseAsync(); + } +#endif public IGxDataStore DataStore { get{ return dataStore;} @@ -736,7 +757,61 @@ public void Close() wmiconnection.CleanUp(); } } +#if NETCORE + internal async Task CloseAsync() + { + if (connection != null) + { + GXLogging.Debug(log, "GxConnection.Close Id " + " connection State '" + connection.State + "'" + " handle:" + handle + " datastore:" + DataStore.Id); + } + if (connection != null && ((connection.State & ConnectionState.Closed) == 0)) + { + try + { + connectionCache.Clear(); + } + catch (Exception e) + { + GXLogging.Warn(log, "GxConnection.Close can't close all prepared cursors", e); + } + GXLogging.Debug(log, "UncommitedChanges before Close:" + UncommitedChanges); + try + { + if (UncommitedChanges) + { + rollbackTransactionOnly(); + UncommitedChanges = false; + } + } + catch (Exception e) + { + GXLogging.Warn(log, "GxConnection.Close can't rollback transaction", e); + } + try + { + await connection.CloseAsync(); + if (transaction != null) + { + transaction.Dispose(); + transaction = null; + } + + } + catch (Exception e) + { + GXLogging.Warn(log, "GxConnection.Close can't close connection", e); + } + spid = 0; + GXLogging.Debug(log, "GxConnection.Close connection is closed "); + } + m_opened = false; + if (Preferences.Instrumented && wmiconnection != null) + { + wmiconnection.CleanUp(); + } + } +#endif public int OpenHandles { get{return openHandles;} @@ -2842,6 +2917,12 @@ public void CloseConnections() { GxConnectionManager.Instance.RemoveConnection(handle, id); } +#if NETCORE + internal async Task CloseConnectionsAsync() + { + await ((GxConnectionManager)GxConnectionManager.Instance).RemoveConnectionAsync(handle, id); + } +#endif public void Release() { } diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs index 756a05e18..1eb63d2f7 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs @@ -25,6 +25,7 @@ using GeneXus.Metadata; using System.Data.Common; using System.Linq; +using System.Threading.Tasks; namespace GeneXus.Data { @@ -4343,7 +4344,28 @@ public virtual void Close() { InternalConnection.Close(); } +#if NETCORE + internal virtual async Task CloseAsync() + { + try + { + DbConnection dbConnection = InternalConnection as DbConnection; + if (dbConnection != null) + { + await dbConnection.CloseAsync(); + } + else + { + InternalConnection.Close(); + } + } + catch (Exception ex) + { + throw new DataException(ex.Message, ex); + } + } +#endif public void ChangeDatabase(String database) { throw new NotSupportedException("NoChangeMsg00" + database); diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2.cs index a52b846f0..39d6c41f1 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataDb2.cs @@ -4,6 +4,7 @@ using System.Reflection; using System.Text; using System.Threading; +using System.Threading.Tasks; using GeneXus.Application; using GeneXus.Cache; using GeneXus.Metadata; @@ -655,7 +656,20 @@ override public void Close() throw new DataException(ex.Message, ex); } } - +#if NETCORE + internal override async Task CloseAsync() + { + try + { + CheckState(false); + await base.CloseAsync(); + } + catch (Exception ex) + { + throw new DataException(ex.Message, ex); + } + } +#endif override public IDbCommand CreateCommand() { return InternalConnection.CreateCommand(); diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataHana.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataHana.cs index 967c738eb..14954b0ca 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataHana.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataHana.cs @@ -4,6 +4,7 @@ using System.IO; using System.Reflection; using System.Text; +using System.Threading.Tasks; using GeneXus.Cache; using GeneXus.Metadata; using GeneXus.Utils; @@ -415,7 +416,6 @@ override public void Close() { try { - CheckState(false); InternalConnection.Close(); } catch (Exception ex) @@ -423,7 +423,20 @@ override public void Close() throw new DataException(ex.Message, ex); } } - +#if NETCORE + internal override async Task CloseAsync() + { + try + { + CheckState(false); + await base.CloseAsync(); + } + catch (Exception ex) + { + throw new DataException(ex.Message, ex); + } + } +#endif override public IDbCommand CreateCommand() { return InternalConnection.CreateCommand(); diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierService.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierService.cs index 570c47873..57c25823c 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierService.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierService.cs @@ -363,7 +363,6 @@ override public void Close() { try { - CheckState(false); InternalConnection.Close(); } catch (Exception ex) diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXLogging.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXLogging.cs index 97a9a1685..9a66cc57a 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXLogging.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXLogging.cs @@ -429,6 +429,15 @@ public static void Warn(ILog log, string msg, Exception ex) log.Warn(msg, ex); } } + internal static void DebugSanitized(IGXLogger log, string startMsg, Func buildMsg) + { + if (log.IsDebugEnabled) + { + string msg = buildMsg(); + DebugSanitized(log, startMsg + msg); + } + } + public static void DebugSanitized(ILog log, Exception ex, params string[] list) { if (log.IsDebugEnabled) diff --git a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs index d67069d3f..cfe9ed0d5 100644 --- a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs +++ b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs @@ -48,6 +48,7 @@ namespace GeneXus.Http #endif + using System.Threading.Tasks; #if NETCORE public abstract class GXHttpHandler : GXBaseObject, IHttpHandler #else @@ -243,6 +244,15 @@ protected void setEventMetadata(string EventName, string Metadata) else EventsMetadata[EventName] = Metadata; } + internal async Task WebExecuteExAsync(HttpContext httpContext) + { + if (IsUploadRequest(httpContext)) + new GXObjectUploadServices(context).webExecute(); + else if (IsFullAjaxRequest(httpContext)) + await WebAjaxEventAsync(); + else + await WebExecuteAsync(); + } #else protected void setEventMetadata(string EventName, string Metadata) { @@ -286,6 +296,13 @@ private bool IsFullAjaxRequest(HttpContext httpContext) public virtual void InitializeDynEvents() { throw new Exception("The method or operation is not implemented."); } public virtual void initialize_properties() { throw new Exception("The method or operation is not implemented."); } public virtual void webExecute() { throw new Exception("The method or operation is not implemented."); } + protected virtual Task WebExecuteAsync() + { + GXLogging.Warn(log, this.GetType().FullName + " not generated as async service"); + webExecute(); + return Task.CompletedTask; + } + #if !NETCORE public virtual void initialize() { throw new Exception("The method or operation is not implemented."); } public virtual void cleanup() { } @@ -1048,6 +1065,40 @@ internal string Invoke(string JsonMessage, GXHttpHandler targetObj) return response; } } +#if NETCORE + internal virtual async Task WebAjaxEventAsync() + { + bool isMultipartRequest = context.IsMultipartRequest; + if (isMultipartRequest) + { + localHttpContext.Response.ContentType = MediaTypesNames.TextHtml; + } + else + { + localHttpContext.Response.ContentType = MediaTypesNames.ApplicationJson; + } + setAjaxCallMode(); + context.setFullAjaxMode(); + DynAjaxEvent dynAjaxEvent = new DynAjaxEvent(context.httpAjaxContext.DynAjaxEventContext); + string jsonRequest; + if (context.IsMultipartRequest) + jsonRequest = cgiGet(GX_AJAX_MULTIPART_ID); + else + { + using (StreamReader reader = new StreamReader(localHttpContext.Request.GetInputStream())) + { + jsonRequest = await reader.ReadToEndAsync(); ; + } + } + string jsonResponse = dynAjaxEvent.Invoke(jsonRequest, this); + + + if (!redirect(context)) + { + ((GxContext)context).SendFinalJSONResponse(jsonResponse); + } + } +#endif public virtual void webAjaxEvent() { @@ -1925,6 +1976,70 @@ public bool IsMain get { return _isMain; } } #endif +#if NETCORE + internal async Task ProcessRequestAsync(HttpContext httpContext) + { + localHttpContext = httpContext; + + if (IsSpaRequest() && !IsSpaSupported()) + { + this.SendResponseStatus(SPA_NOT_SUPPORTED_STATUS_CODE, "SPA not supported by the object"); + context.CloseConnections(); + await Task.CompletedTask; + } + ControlOutputWriter = new HtmlTextWriter(localHttpContext); + LoadParameters(localHttpContext.Request.QueryString.Value); + context.httpAjaxContext.GetAjaxEncryptionKey(); //Save encryption key in session + InitPrivates(); + try + { + SetStreaming(); + SendHeaders(); + string clientid = context.ClientID; //Send clientid cookie (before response HasStarted) if necessary, since UseResponseBuffering is not in .netcore3.0 + + bool validSession = ValidWebSession(); + if (validSession && IntegratedSecurityEnabled) + validSession = ValidSession(); + if (validSession) + { + if (UseBigStack()) + { + Thread ts = new Thread(new ParameterizedThreadStart(webExecuteWorker)); + ts.Start(httpContext); + ts.Join(); + if (workerException != null) + throw workerException; + } + else + { + await WebExecuteExAsync(httpContext); + } + } + else + { + context.CloseConnections(); + if (IsGxAjaxRequest() || context.isAjaxRequest()) + context.DispatchAjaxCommands(); + } + SetCompression(httpContext); + context.ResponseCommited = true; + } + catch (Exception e) + { + try + { + context.CloseConnections(); + } + catch { } + { + Exception exceptionToHandle = e.InnerException ?? e; + handleException(exceptionToHandle.GetType().FullName, exceptionToHandle.Message, exceptionToHandle.StackTrace); + throw new Exception("GXApplication exception", e); + } + } + } + +#endif #if !NETCORE [SecuritySafeCritical] #endif @@ -2224,7 +2339,7 @@ private string GetGAMNotAuthorizedWebObject() private void SendHeaders() { sendCacheHeaders(); - GXLogging.DebugSanitized(log, "HttpHeaders: ", DumpHeaders(localHttpContext)); + GXLogging.DebugSanitized(log, "HttpHeaders: ", () => DumpHeaders(localHttpContext)); sendAdditionalHeaders(); HttpHelper.CorsHeaders(localHttpContext); HttpHelper.AllowHeader(localHttpContext, new List() { $"{HttpMethod.Get.Method},{HttpMethod.Post.Method}" }); diff --git a/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs b/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs index d5da20307..a3d87da7d 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/GXBaseObject.cs @@ -18,6 +18,7 @@ using System.Diagnostics; using System.Reflection; using System.Threading; +using System.Threading.Tasks; namespace GeneXus.Application { @@ -63,6 +64,27 @@ protected virtual void ExecutePrivate() { } +#if NETCORE + protected virtual bool AsyncEnabled { get; } + + internal bool GetAsyncEnabledInternal() + { + return AsyncEnabled; + } + protected async Task CloseConnectionsAsync() + { + GxContext gxContext = context as GxContext; + if (gxContext != null) + { + await gxContext.CloseConnectionsAsync(); + } + } + + protected virtual Task ExecutePrivateAsync() + { + return Task.CompletedTask; + } +#endif internal static string GetObjectNameWithoutNamespace(string gxObjFullName) { string mainNamespace = Preferences.AppMainNamespace; @@ -79,18 +101,43 @@ private void ExecuteUsingSpanCode() ExecutePrivate(); } } + private async Task ExecuteUsingSpanCodeAsync() + { + string gxObjFullName = GetObjectNameWithoutNamespace(GetType().FullName); + using (Activity activity = ActivitySource.StartActivity($"{gxObjFullName}.execute")) + { + await ExecutePrivateAsync(); + } + } #endif protected virtual void ExecuteImpl() { #if NETCORE - if (GenOtelSpanEnabled()) - ExecuteUsingSpanCode(); + if (GetAsyncEnabledInternal()) + { + ExecuteImplAsync().GetAwaiter().GetResult(); + } else - ExecutePrivate(); + { + if (GenOtelSpanEnabled()) + ExecuteUsingSpanCode(); + else + ExecutePrivate(); + } #else ExecutePrivate(); #endif } + +#if NETCORE + protected virtual async Task ExecuteImplAsync() + { + if (GenOtelSpanEnabled()) + await ExecuteUsingSpanCodeAsync(); + else + await ExecutePrivateAsync(); + } +#endif protected virtual void ExecutePrivateCatch(object stateInfo) { try @@ -177,7 +224,11 @@ public bool IsApiObject set { _isApi = value; } get { return _isApi; } } - +#if NETCORE + protected virtual Task CleanupAsync() { + return Task.CompletedTask;// throw new NotImplementedException(); + } +#endif public virtual void cleanup() { } virtual public bool UploadEnabled() { return false; } diff --git a/dotnet/src/dotnetframework/GxClasses/Model/GXWebProcedure.cs b/dotnet/src/dotnetframework/GxClasses/Model/GXWebProcedure.cs index 7a0a689ae..67ff7b635 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/GXWebProcedure.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/GXWebProcedure.cs @@ -9,6 +9,7 @@ namespace GeneXus.Procedure using System.Net.Mime; #if NETCORE using Microsoft.AspNetCore.Http; + using System.Threading.Tasks; #else using System.Web; #endif @@ -37,7 +38,14 @@ public class GXWebProcedure : GXHttpHandler protected virtual void printHeaders() { } protected virtual void printFooters() { } +#if NETCORE + public override void webExecute() + { + WebExecuteAsync().GetAwaiter().GetResult(); + } +#else public override void webExecute() { } +#endif public override void initialize() { } protected override void createObjects() { } public override void skipLines(long nToSkip) { } diff --git a/dotnet/test/DotNetCoreWebUnitTest/Middleware/HttpProcTest.cs b/dotnet/test/DotNetCoreWebUnitTest/Middleware/HttpProcTest.cs new file mode 100644 index 000000000..83f9ce60f --- /dev/null +++ b/dotnet/test/DotNetCoreWebUnitTest/Middleware/HttpProcTest.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using System.Net.Http; +using System.Reflection; +using System.Threading.Tasks; +using GeneXus.Metadata; +using Xunit; +namespace xUnitTesting +{ + public class HttpProcTest : MiddlewareTest + { + Dictionary parms = new Dictionary(); + FormUrlEncodedContent formUrlEncodedContent; + public HttpProcTest():base() + { + ClassLoader.FindType("aprochttpgetstatic", "GeneXus.Programs", "aprochttpgetstatic", Assembly.GetExecutingAssembly(), true);//Force loading assembly for webhook procedure + server.AllowSynchronousIO=true; + parms.Add("client_id", "SM40d2cbda93b2de0a15df7a1598c7db83"); + parms.Add("refresh_token", "99"); + formUrlEncodedContent = new FormUrlEncodedContent(parms); + } + [Fact] + public async Task HtttpPostTest() + { + HttpClient client = server.CreateClient(); + + HttpResponseMessage response = await client.PostAsync("aprochttpgetstatic.aspx", formUrlEncodedContent);//"application/x-www-form-urlencoded" + response.EnsureSuccessStatusCode(); + string resp = await response.Content.ReadAsStringAsync(); + Assert.NotEmpty(resp); + Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); + } + } + +} diff --git a/dotnet/test/DotNetCoreWebUnitTest/apps/aprochttpgetstatic.cs b/dotnet/test/DotNetCoreWebUnitTest/apps/aprochttpgetstatic.cs new file mode 100644 index 000000000..8fef42f0f --- /dev/null +++ b/dotnet/test/DotNetCoreWebUnitTest/apps/aprochttpgetstatic.cs @@ -0,0 +1,111 @@ +using System.Threading.Tasks; +using GeneXus.Application; +using GeneXus.Data.NTier; +using GeneXus.Http.Client; +using GeneXus.Http.Server; +using GeneXus.Procedure; +using GeneXus.Utils; +namespace GeneXus.Programs +{ + public class aprochttpgetstatic : GXWebProcedure + { + protected override async Task WebExecuteAsync( ) + { + context.SetDefaultTheme("HttpClientTest", true); + initialize(); + { + await ExecutePrivateAsync(); + } + await CleanupAsync(); + } + + public aprochttpgetstatic( ) + { + context = new GxContext( ); + DataStoreUtil.LoadDataStores( context); + IsMain = true; + context.SetDefaultTheme("HttpClientTest", true); + } + + public aprochttpgetstatic( IGxContext context ) + { + this.context = context; + IsMain = false; + } + + public void execute( ) + { + initialize(); + ExecuteImpl(); + } + + public void executeSubmit( ) + { + SubmitImpl(); + } + + protected override async Task ExecutePrivateAsync( ) + { + /* GeneXus formulas */ + /* Output device settings */ + AV14grant_type = "refresh_token"; + AV12ClientId = AV10HttpRequest.GetValue("client_id"); + AV16Refresh_Token = AV10HttpRequest.GetValue("refresh_token"); + AV8baseUrl = "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"; + AV17baseUrlWithParms = StringUtil.Format( "%1?grant_type=%2&client_id=%3&refresh_token=%4", AV8baseUrl, StringUtil.Trim( AV14grant_type), StringUtil.Trim( AV12ClientId), StringUtil.Trim( AV16Refresh_Token), "", "", "", "", ""); + AV9Httpclient.AddHeader("Content-Type", "application/x-www-form-urlencoded"); + AV9Httpclient.Execute("GET", StringUtil.Trim( AV17baseUrlWithParms)); + AV18Httpclientstr = AV9Httpclient.ToString(); + AV11HttpResponse.AddString(AV18Httpclientstr); + if ( context.WillRedirect( ) ) + { + context.Redirect( context.wjLoc ); + context.wjLoc = ""; + } + await CleanupAsync(); + } + + protected override async Task CleanupAsync( ) + { + CloseCursors(); + base.cleanup(); + if ( IsMain ) + { + await CloseConnectionsAsync(); + } + ExitApp(); + } + + + public override void initialize( ) + { + // GXKey = ""; + //gxfirstwebparm = ""; + AV14grant_type = ""; + AV12ClientId = ""; + AV10HttpRequest = new GxHttpRequest( context); + AV16Refresh_Token = ""; + AV8baseUrl = ""; + AV17baseUrlWithParms = ""; + AV9Httpclient = new GxHttpClient( context); + AV18Httpclientstr = ""; + AV11HttpResponse = new GxHttpResponse( context); + /* GeneXus formulas. */ + } + + //private short gxcookieaux ; + //private string GXKey ; + //private string gxfirstwebparm ; + private string AV14grant_type ; + private string AV12ClientId ; + private string AV16Refresh_Token ; + private string AV17baseUrlWithParms ; + private string AV18Httpclientstr ; + //private bool entryPointCalled ; + private string AV8baseUrl ; + private GxHttpRequest AV10HttpRequest ; + private GxHttpClient AV9Httpclient ; + private GxHttpResponse AV11HttpResponse ; + } + +} From 39ae59f6581533597cf7f9b3cd27dbb89e029411 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Thu, 11 Apr 2024 11:23:28 -0300 Subject: [PATCH 133/164] Improve scalability when using gxhttpclient (#972) * Refactored gxhttpclient implementation to utilize a singleton instance for reusing the connection pool of httpclient instances. Avoided using CookieContainer of handlers, as they are shared across the pooled connections. Instead, managed sending and receiving cookies as headers. * Change public method by internal. * Honor property Maximum pool size per route. * Define const for DEFAULT_HTTPCLIENT_MAX_PER_ROUTE. * Rename SINGLETON_HTTPCLIENT to HTTPCLIENT_SINGLETON to maintain consistency with other keys, such as HTTPCLIENT_MAX_PER_ROUTE * Add trace for HttpClient. Ignore cookies in container that are invalid for the current url. * Avoid InvalidOperationException in HttpRequest.GetValue when there is no HasFormContentType. Use async operations when possible for httpclient connectionProperties was not caching empty values * Prepare for async calls to httpclient. Enable Microsoft.VisualStudio.Threading.Analyzers * Fix build error. * Revert changes related to async and keep only the httpclient singleton changes in this branch. This reverts commit c855419b670329543a4af663abf780ca946f2756. Revert "Prepare for async calls to httpclient." This reverts commit cd6c42ebb9311e2291d28862eab9e0cae84d1715. Revert "Avoid InvalidOperationException in HttpRequest.GetValue when there is no HasFormContentType." This reverts commit 4f77cb350040dd5caeff5147368db2c2f93381de. * Consider SslOptions when creating the key for SocketsHttpHandler, as the ServicePointManager.ServerCertificateValidationCallback may change after the first handler has been created. Therefore, subsequent calls cannot reuse the same handler. * Add ToStringAsync and ExecuteAsync methods to HttpClient. * ExecuteAsync must be public as it is used from generated code. * Remove unnecessary call to ReceiveData (sync method) in ToStringAsync --- .../GxClasses/Core/gxconfig.cs | 23 +- .../GxClasses/Domain/GxHttpClient.cs | 756 ++++++++++++++---- .../GxClasses/Helpers/HttpHelper.cs | 42 + .../DotNetUnitTest/Domain/GxHttpClientTest.cs | 118 +++ 4 files changed, 796 insertions(+), 143 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs b/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs index 00443b224..5dadc513c 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs @@ -848,6 +848,7 @@ public class Preferences const string DEFAULT_DS = "Default"; static int httpclient_max_per_route = -1; static int sessionTimeout = -1; + static int singletonHttpClient = -1; internal static string AppMainNamespace { get @@ -1443,6 +1444,18 @@ internal static bool WrapSingleApiOutput return DefaultWrapSingleApiOutput; } } + + internal static bool SingletonHttpClient() + { + if (singletonHttpClient == -1) + { + if (Config.GetValueOrEnvironmentVarOf("HTTPCLIENT_SINGLETON", out string sValue) && int.TryParse(sValue, out int value)) + singletonHttpClient = value; + else + singletonHttpClient = 1; + } + return singletonHttpClient==1; + } internal static string CorsAllowedOrigins() { if (Config.GetValueOf("CORS_ALLOW_ORIGIN", out string corsOrigin)) @@ -1484,27 +1497,27 @@ public static string GetDefaultTheme() else return ""; } - - public static int GetHttpClientMaxConnectionPerRoute() + internal const int DEFAULT_HTTPCLIENT_MAX_PER_ROUTE= 1000; + internal static int GetHttpClientMaxConnectionPerRoute() { if (httpclient_max_per_route == -1) { try { string strmax; - if (Config.GetValueOf("HTTPCLIENT_MAX_PER_ROUTE", out strmax)) + if (Config.GetValueOrEnvironmentVarOf("HTTPCLIENT_MAX_PER_ROUTE", out strmax)) { httpclient_max_per_route = Convert.ToInt32(strmax); } else { - httpclient_max_per_route = 1000; + httpclient_max_per_route = DEFAULT_HTTPCLIENT_MAX_PER_ROUTE; } } catch (Exception ex) { GXLogging.Error(log, "HttpClientMaxPerRoute error", ex); - httpclient_max_per_route = 1000; + httpclient_max_per_route = DEFAULT_HTTPCLIENT_MAX_PER_ROUTE; } } return httpclient_max_per_route; diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs index 712dcee1d..8cda5d449 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs @@ -2,6 +2,7 @@ namespace GeneXus.Http.Client { using System; using System.Collections; + using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Specialized; using System.Globalization; @@ -9,6 +10,7 @@ namespace GeneXus.Http.Client using System.Net; using System.Net.Http; using System.Net.Http.Headers; + using System.Net.Security; using System.Security; using System.Security.Cryptography.X509Certificates; using System.Text; @@ -60,6 +62,7 @@ internal MultiPartTemplate() public class GxHttpClient : IGxHttpClient, IDisposable { private static readonly IGXLogger log = GXLoggerFactory.GetLogger(); + private const int DEFAULT_TIMEOUT = 30000; public const int _Basic = 0; public const int _Digest = 1; public const int _NTLM = 2; @@ -67,7 +70,7 @@ public class GxHttpClient : IGxHttpClient, IDisposable const int StreamWriterDefaultBufferSize = 1024; Stream _sendStream; byte[] _receiveData; - int _timeout = 30000; + int _timeout = DEFAULT_TIMEOUT; short _statusCode = 0; string _proxyHost; int _proxyPort; @@ -93,18 +96,19 @@ public class GxHttpClient : IGxHttpClient, IDisposable IGxContext _context; #if NETCORE - IWebProxy _proxyObject; + static IWebProxy _proxyObject; + static object syncRootHttpInstance = new Object(); #else - WebProxy _proxyObject; + static WebProxy _proxyObject; #endif ArrayList _authCollection; ArrayList _authProxyCollection; X509Certificate2Collection _certificateCollection; + List _fileCertificateCollection; Encoding _encoding; Encoding _contentEncoding; - - + static object syncRoot = new Object(); public MultiPartTemplate MultiPart { get @@ -144,17 +148,161 @@ internal byte[] ReceiveData } } + #if NETCORE - [SecuritySafeCritical] - private HttpClientHandler GetHandler() + private async Task ReceiveDataAsync() + { + await ReadResponseDataAsync(); + return _receiveData; + } + + private const int POOLED_CONNECTION_LIFETIME_MINUTES = 2; + internal static ConcurrentDictionary _httpClientInstances = new ConcurrentDictionary(); + private static HttpClient GetHttpClientInstance(Uri URI, int timeout, ArrayList authCollection, ArrayList authProxyCollection, X509Certificate2Collection certificateCollection, List fileCertificateCollection, string proxyHost, int proxyPort, out bool disposableInstance) + { + if (CacheableInstance(authCollection, authProxyCollection)) + { + HttpClient value; + disposableInstance = false; + string key = HttpClientInstanceIdentifier(proxyHost, proxyPort, fileCertificateCollection, timeout); + if (_httpClientInstances.TryGetValue(key, out value)) + { + GXLogging.Debug(log, $"Getting httpClient cached instance"); + return value; + } + else + { + lock (syncRootHttpInstance) + { + if (_httpClientInstances.TryGetValue(key, out value)) + { + GXLogging.Debug(log, $"Getting httpClient cached instance"); + return value; + } + value = new HttpClient(GetHandler(URI, authCollection, authProxyCollection, certificateCollection, proxyHost, proxyPort)); + value.Timeout = TimeSpan.FromMilliseconds(timeout); + _httpClientInstances.TryAdd(key, value); + return value; + } + } + } + else + { + disposableInstance = true; + return new HttpClient(GetHandler(URI, authCollection, authProxyCollection, certificateCollection, proxyHost, proxyPort)); + } + } + + private static string HttpClientInstanceIdentifier(string proxyHost, int proxyPort, List fileCertificateCollection, int timeout) + { + bool defaultSslOptions = ServicePointManager.ServerCertificateValidationCallback == null; + if (string.IsNullOrEmpty(proxyHost) && fileCertificateCollection.Count==0 && timeout== DEFAULT_TIMEOUT && defaultSslOptions) + { + return string.Empty; + } + else if (fileCertificateCollection.Count==0) + { + return $"{proxyHost}:{proxyPort}::{timeout}:{defaultSslOptions}"; + } + else + { + return $"{proxyHost}:{proxyPort}:{string.Join(';', fileCertificateCollection)}:{timeout}:{defaultSslOptions}"; + } + } + + private static bool CacheableInstance(ArrayList authCollection, ArrayList authProxyCollection) + { + return authCollection.Count == 0 && authProxyCollection.Count == 0 && Preferences.SingletonHttpClient(); + } + private static SocketsHttpHandler GetHandler(Uri URI, ArrayList authCollection, ArrayList authProxyCollection, X509Certificate2Collection certificateCollection, string proxyHost, int proxyPort) { - return new HttpClientHandler(); + SocketsHttpHandler handler = new SocketsHttpHandler() + { + PooledConnectionLifetime = TimeSpan.FromMinutes(POOLED_CONNECTION_LIFETIME_MINUTES), + }; + int maxConnections = Preferences.GetHttpClientMaxConnectionPerRoute(); + if (maxConnections != Preferences.DEFAULT_HTTPCLIENT_MAX_PER_ROUTE) + { + handler.MaxConnectionsPerServer = maxConnections; + } + GXLogging.Debug(log, $"Creating SocketsHttpHandler MaxConnectionsPerServer:{handler.MaxConnectionsPerServer}"); + ICredentials cc = getCredentialCache(URI, authCollection); + if (cc != null) + { + handler.Credentials = getCredentialCache(URI, authCollection); + } + + SetSslOptions(handler); + + if (GXUtil.CompressResponse()) + { + handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; + } + foreach (X509Certificate2 cert in certificateCollection) + handler.SslOptions.ClientCertificates.Add(cert); + + WebProxy proxy = getProxy(proxyHost, proxyPort, authProxyCollection); + if (proxy != null) + { + handler.Proxy = proxy; + } + handler.UseCookies = false; + return handler; + + } + + private static void SetSslOptions(SocketsHttpHandler handler) + { + if (ServicePointManager.ServerCertificateValidationCallback != null) + { + handler.SslOptions = new SslClientAuthenticationOptions + { + RemoteCertificateValidationCallback = ServicePointManager.ServerCertificateValidationCallback + }; + } } #else [SecuritySafeCritical] - private WinHttpHandler GetHandler() + + private static HttpClient GetHttpClientInstance(Uri URI, int timeout, ArrayList authCollection, ArrayList authProxyCollection, X509Certificate2Collection certificateCollection, string proxyHost, int proxyPort, CookieContainer cookies) + { + TimeSpan milliseconds = TimeSpan.FromMilliseconds(timeout); + HttpClient value = new HttpClient(GetHandler(URI, milliseconds, authCollection, authProxyCollection, certificateCollection, proxyHost, proxyPort, cookies)); + value.Timeout = milliseconds; + return value; + } + [SecuritySafeCritical] + private static WinHttpHandler GetHandler(Uri URI, TimeSpan milliseconds, ArrayList authCollection, ArrayList authProxyCollection, X509Certificate2Collection certificateCollection, string proxyHost, int proxyPort, CookieContainer cookies) { - return new WinHttpHandler(); + WinHttpHandler handler = new WinHttpHandler(); + ICredentials cc = getCredentialCache(URI, authCollection); + if (cc != null) + { + handler.ServerCredentials = cc; + } + if (ServicePointManager.ServerCertificateValidationCallback != null) + { + handler.ServerCertificateValidationCallback = ((sender, certificate, chain, sslPolicyErrors) => ServicePointManager.ServerCertificateValidationCallback(sender, certificate, chain, sslPolicyErrors)); + } + handler.CookieUsePolicy = CookieUsePolicy.UseSpecifiedCookieContainer; + handler.CookieContainer = cookies; + if (GXUtil.CompressResponse()) + { + handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; + } + foreach (X509Certificate2 cert in certificateCollection) + handler.ClientCertificates.Add(cert); + WebProxy proxy = getProxy(proxyHost, proxyPort, authProxyCollection); + if (proxy != null) + { + handler.Proxy = proxy; + handler.WindowsProxyUsePolicy = WindowsProxyUsePolicy.UseCustomProxy; + } + + handler.ReceiveDataTimeout = milliseconds; + handler.ReceiveHeadersTimeout = milliseconds; + + return handler; } #endif public GxHttpClient(IGxContext context) : this() @@ -172,21 +320,18 @@ public GxHttpClient() : base() _authCollection = new ArrayList(); _authProxyCollection = new ArrayList(); _certificateCollection = new X509Certificate2Collection(); + _fileCertificateCollection = new List(); IncludeCookies = true; _proxyHost = string.Empty; try { -#if NETCORE - _proxyObject = WebRequest.GetSystemWebProxy(); - -#else - _proxyObject = WebProxy.GetDefaultProxy(); - if (_proxyObject != null && _proxyObject.Address != null) +#if !NETCORE + if (ProxyObject != null && ProxyObject.Address != null) { - _proxyHost = _proxyObject.Address.Host; - _proxyPort = _proxyObject.Address.Port; + _proxyHost = ProxyObject.Address.Host; + _proxyPort = ProxyObject.Address.Port; } #endif } @@ -196,7 +341,36 @@ public GxHttpClient() : base() } } +#if NETCORE + + private IWebProxy ProxyObject +#else + private static WebProxy ProxyObject +#endif + { + get { + if (_proxyObject == null) + { + lock (syncRoot) + { + try + { +#if NETCORE + _proxyObject = WebRequest.GetSystemWebProxy(); +#else + _proxyObject = WebProxy.GetDefaultProxy(); +#endif + } + catch (Exception e) + { + GXLogging.Warn(log, "Error getting ProxyObject", e); + } + } + } + return _proxyObject; + } + } public short Digest { get { return _Digest; } @@ -532,12 +706,19 @@ private void EndMultipartBoundary(Stream reqStream) if (IsMultipart) reqStream.Write(MultiPart.EndBoundaryBytes, 0, MultiPart.EndBoundaryBytes.Length); } - - void setHeaders(HttpRequestMessage request, CookieContainer cookies) + void setContentHeaders(HttpRequestMessage request, string contentType) + { + if (contentType != null) + { + HttpContentHeaders contentHeaders = request.Content.Headers; + contentHeaders.ContentType = MediaTypeHeaderValue.Parse(contentType); + } + InferContentType(contentType, request); + } + void setHeaders(HttpRequestMessage request, CookieContainer cookies, out string contentType) { - HttpContentHeaders contentHeaders = request.Content.Headers; HttpRequestHeaders headers = request.Headers; - string contentType = null; + contentType = null; for (int i = 0; i < _headers.Count; i++) { string currHeader = _headers.Keys[i]; @@ -550,7 +731,6 @@ void setHeaders(HttpRequestMessage request, CookieContainer cookies) break; case "CONTENT-TYPE": contentType = _headers[i].ToString(); - contentHeaders.ContentType = MediaTypeHeaderValue.Parse(_headers[i].ToString()); break; case "ACCEPT": AddHeader(headers, "Accept", _headers[i]); @@ -611,7 +791,6 @@ void setHeaders(HttpRequestMessage request, CookieContainer cookies) else headers.ConnectionClose = false; } - InferContentType(contentType, request); } Cookie ParseCookie(string cookie, string domain) { @@ -649,85 +828,123 @@ void setHttpVersion(HttpRequestMessage req) req.Version = HttpVersion.Version11; } [SecuritySafeCritical] - HttpResponseMessage ExecuteRequest(string method, string requestUrl, CookieContainer cookies) + HttpResponseMessage ExecuteRequest(string method, string requestUrl, bool contextCookies) { - GXLogging.Debug(log, String.Format("Start HTTPClient buildRequest: requestUrl:{0} method:{1}", requestUrl, method)); + CookieContainer cookies = contextCookies ? _context.GetCookieContainer(requestUrl, IncludeCookies) : new CookieContainer(); + + GXLogging.Debug(log, string.Format("Start HTTPClient buildRequest: requestUrl:{0} method:{1}", requestUrl, method)); HttpRequestMessage request; - HttpClient client; + HttpClient client = null; int BytesRead; - Byte[] Buffer = new Byte[1024]; + byte[] Buffer = new byte[1024]; + HttpResponseMessage response; - request = new HttpRequestMessage(); - request.RequestUri = new Uri(requestUrl); -#if NETCORE - HttpClientHandler handler = GetHandler(); - handler.Credentials = getCredentialCache(request.RequestUri, _authCollection); - if (ServicePointManager.ServerCertificateValidationCallback != null) + request = new HttpRequestMessage() { - handler.ServerCertificateCustomValidationCallback = ((sender, certificate, chain, sslPolicyErrors) => ServicePointManager.ServerCertificateValidationCallback(sender, certificate, chain, sslPolicyErrors)); - } -#else - WinHttpHandler handler = GetHandler(); - handler.ServerCredentials = getCredentialCache(request.RequestUri, _authCollection); - if (ServicePointManager.ServerCertificateValidationCallback != null) + RequestUri = new Uri(requestUrl), + Method = new HttpMethod(method), + }; + setHeaders(request, cookies, out string contentType); + setHttpVersion(request); + bool disposableInstance = true; + try { - handler.ServerCertificateValidationCallback = ((sender, certificate, chain, sslPolicyErrors) => ServicePointManager.ServerCertificateValidationCallback(sender, certificate, chain, sslPolicyErrors)); - } - handler.CookieUsePolicy = CookieUsePolicy.UseSpecifiedCookieContainer; +#if NETCORE + request.PopulateCookies(cookies); + client = GetHttpClientInstance(request.RequestUri, _timeout, _authCollection, _authProxyCollection, _certificateCollection, _fileCertificateCollection, _proxyHost, _proxyPort, out disposableInstance); +#else + client = GetHttpClientInstance(request.RequestUri, _timeout, _authCollection, _authProxyCollection, _certificateCollection, _proxyHost, _proxyPort, cookies); #endif - if (GXUtil.CompressResponse()) + using (MemoryStream reqStream = new MemoryStream()) + { + SendVariables(reqStream); + SendStream.Seek(0, SeekOrigin.Begin); + BytesRead = SendStream.Read(Buffer, 0, 1024); + GXLogging.Debug(log, "Start SendStream.Read: BytesRead " + BytesRead); + while (BytesRead > 0) + { + GXLogging.Debug(log, "reqStream.Write: Buffer.length " + Buffer.Length + ",'" + Encoding.UTF8.GetString(Buffer, 0, Buffer.Length) + "'"); + reqStream.Write(Buffer, 0, BytesRead); + BytesRead = SendStream.Read(Buffer, 0, 1024); + } + EndMultipartBoundary(reqStream); + GXLogging.Debug(log, "End SendStream.Read: stream " + reqStream.ToString()); + reqStream.Seek(0, SeekOrigin.Begin); + request.Content = new ByteArrayContent(reqStream.ToArray()); + setContentHeaders(request, contentType); +#if NETCORE + response = client.Send(request, HttpCompletionOption.ResponseHeadersRead); + response.ExtractCookies(cookies); +#else + response = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).GetAwaiter().GetResult(); +#endif + } + } + finally { - handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; + if (disposableInstance && client != null) + { + client.Dispose(); + } } + return response; + } +#if NETCORE + async Task ExecuteRequestAsync(string method, string requestUrl, bool contextCookies) + { + CookieContainer cookies = contextCookies ? _context.GetCookieContainer(requestUrl, IncludeCookies) : new CookieContainer(); - handler.CookieContainer = cookies; - - foreach (X509Certificate2 cert in _certificateCollection) - handler.ClientCertificates.Add(cert); + GXLogging.Debug(log, string.Format("Start HTTPClient buildRequest: requestUrl:{0} method:{1}", requestUrl, method)); + HttpRequestMessage request; + HttpClient client = null; + int BytesRead; + byte[] Buffer = new byte[1024]; + HttpResponseMessage response; - request.Method = new HttpMethod(method); - setHttpVersion(request); - WebProxy proxy = getProxy(_proxyHost, _proxyPort, _authProxyCollection); - if (proxy != null) + request = new HttpRequestMessage() { - handler.Proxy = proxy; -#if !NETCORE - handler.WindowsProxyUsePolicy = WindowsProxyUsePolicy.UseCustomProxy; -#endif - } - HttpResponseMessage response; - TimeSpan milliseconds = TimeSpan.FromMilliseconds(_timeout); -#if !NETCORE - handler.ReceiveDataTimeout = milliseconds; - handler.ReceiveHeadersTimeout = milliseconds; -#endif - using (client = new HttpClient(handler)) + RequestUri = new Uri(requestUrl), + Method = new HttpMethod(method), + }; + setHeaders(request, cookies, out string contentType); + setHttpVersion(request); + bool disposableInstance = true; + try { - client.Timeout = milliseconds; - client.BaseAddress = request.RequestUri; - + request.PopulateCookies(cookies); + client = GetHttpClientInstance(request.RequestUri, _timeout, _authCollection, _authProxyCollection, _certificateCollection, _fileCertificateCollection, _proxyHost, _proxyPort, out disposableInstance); using (MemoryStream reqStream = new MemoryStream()) { SendVariables(reqStream); SendStream.Seek(0, SeekOrigin.Begin); - BytesRead = SendStream.Read(Buffer, 0, 1024); + BytesRead = await SendStream.ReadAsync(Buffer, 0, 1024); GXLogging.Debug(log, "Start SendStream.Read: BytesRead " + BytesRead); while (BytesRead > 0) { GXLogging.Debug(log, "reqStream.Write: Buffer.length " + Buffer.Length + ",'" + Encoding.UTF8.GetString(Buffer, 0, Buffer.Length) + "'"); - reqStream.Write(Buffer, 0, BytesRead); - BytesRead = SendStream.Read(Buffer, 0, 1024); + await reqStream.WriteAsync(Buffer, 0, BytesRead); + BytesRead = await SendStream.ReadAsync(Buffer, 0, 1024); } EndMultipartBoundary(reqStream); GXLogging.Debug(log, "End SendStream.Read: stream " + reqStream.ToString()); reqStream.Seek(0, SeekOrigin.Begin); request.Content = new ByteArrayContent(reqStream.ToArray()); - setHeaders(request, handler.CookieContainer); - response = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).GetAwaiter().GetResult(); + setContentHeaders(request, contentType); + response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); + response.ExtractCookies(cookies); + } + } + finally + { + if (disposableInstance && client != null) + { + client.Dispose(); } } return response; - } + } +#endif + void ReadResponseData() { if (_receiveData == null && _response!=null) @@ -735,7 +952,11 @@ void ReadResponseData() _receiveData = Array.Empty(); try { +#if NETCORE + Stream stream = _response.Content.ReadAsStream(); +#else Stream stream = _response.Content.ReadAsStreamAsync().GetAwaiter().GetResult(); +#endif using (MemoryStream ms = new MemoryStream()) { @@ -759,6 +980,39 @@ void ReadResponseData() } } } +#if NETCORE + async Task ReadResponseDataAsync() + { + if (_receiveData == null && _response != null) + { + _receiveData = Array.Empty(); + try + { + Stream stream = await _response.Content.ReadAsStreamAsync(); + + using (MemoryStream ms = new MemoryStream()) + { + await stream.CopyToAsync(ms); + _receiveData = ms.ToArray(); + } + _eof = true; + int bytesRead = _receiveData.Length; + GXLogging.Debug(log, "BytesRead " + _receiveData.Length); + if (bytesRead > 0 && !_encodingFound) + { + _encoding = DetectEncoding(_charset, out _encodingFound, _receiveData, bytesRead); + } + } + catch (IOException ioEx) + { + if (_errCode == 1) + GXLogging.Warn(log, "Could not read response", ioEx); + else + throw ioEx; + } + } + } + #endif bool UseOldHttpClient(string name) { if (Config.GetValueOf("useoldhttpclient", out string useOld) && useOld.StartsWith("y", StringComparison.OrdinalIgnoreCase)) @@ -792,6 +1046,20 @@ public void Execute(string method, string name) HttpClientExecute(method, name); } } +#if NETCORE + public async Task ExecuteAsync(string method, string name) + { + if (UseOldHttpClient(name)) + { + GXLogging.Debug(log, "Using legacy GxHttpClient"); + await WebExecuteAsync(method, name); + } + else + { + await HttpClientExecuteAsync(method, name); + } + } +#endif internal void ProcessResponse(HttpResponseMessage httpResponse) { _response = httpResponse; @@ -804,28 +1072,13 @@ internal void ProcessResponse(HttpResponseMessage httpResponse) _errDescription = "The remote server returned an error: (" + _statusCode + ") " + _statusDescription + "."; } } - public void HttpClientExecute(string method, string name) + private void ProcessHttpClientException(Exception ex) { - _receiveData = null; - _response = null; - Byte[] Buffer = new Byte[1024]; - _errCode = 0; - _errDescription = string.Empty; - GXLogging.Debug(log, "Start Execute: method '" + method + "', name '" + name + "'"); - try - { - string requestUrl = GetRequestURL(name); - bool contextCookies = _context != null && !String.IsNullOrEmpty(requestUrl); - CookieContainer cookies = contextCookies ? _context.GetCookieContainer(requestUrl, IncludeCookies) : new CookieContainer(); - _response = ExecuteRequest(method, requestUrl, cookies); - - if (contextCookies) - _context.UpdateSessionCookieContainer(); - - - } + HttpRequestException httpex; + TaskCanceledException tcex; #if NETCORE - catch (AggregateException aex) + AggregateException aex; + if ((aex = ex as AggregateException) != null) { GXLogging.Warn(log, "Error Execute", aex); _errCode = 1; @@ -837,44 +1090,97 @@ public void HttpClientExecute(string method, string name) _response.Content = new StringContent(HttpHelper.StatusCodeToTitle(HttpStatusCode.InternalServerError)); _response.StatusCode = HttpStatusCode.InternalServerError; } + else #endif - catch (HttpRequestException e) + if ((httpex = ex as HttpRequestException) != null) { - GXLogging.Warn(log, "Error Execute", e); + GXLogging.Warn(log, "Error Execute", httpex); _errCode = 1; - if (e.InnerException != null) - _errDescription = e.Message + " " + e.InnerException.Message; + if (httpex.InnerException != null) + _errDescription = httpex.Message + " " + httpex.InnerException.Message; else - _errDescription = e.Message; + _errDescription = httpex.Message; _response = new HttpResponseMessage(); _response.Content = new StringContent(HttpHelper.StatusCodeToTitle(HttpStatusCode.InternalServerError)); #if NETCORE - _response.StatusCode = (HttpStatusCode)(e.StatusCode != null ? e.StatusCode : HttpStatusCode.InternalServerError); + _response.StatusCode = (HttpStatusCode)(httpex.StatusCode != null ? httpex.StatusCode : HttpStatusCode.InternalServerError); #else _response.StatusCode = HttpStatusCode.InternalServerError; #endif + } - catch (TaskCanceledException e) + else if ((tcex = ex as TaskCanceledException) != null) { - GXLogging.Warn(log, "Error Execute", e); + GXLogging.Warn(log, "Error Execute", tcex); _errCode = 1; - _errDescription = "The request has timed out. " + e.Message; + _errDescription = "The request has timed out. " + tcex.Message; _response = new HttpResponseMessage(); _response.StatusCode = 0; _response.Content = new StringContent(String.Empty); } - catch (Exception e) + else { - GXLogging.Warn(log, "Error Execute", e); + GXLogging.Warn(log, "Error Execute", ex); _errCode = 1; - if (e.InnerException != null) - _errDescription = e.Message + " " + e.InnerException.Message; + if (ex.InnerException != null) + _errDescription = ex.Message + " " + ex.InnerException.Message; else - _errDescription = e.Message; + _errDescription = ex.Message; _response = new HttpResponseMessage(); _response.Content = new StringContent(HttpHelper.StatusCodeToTitle(HttpStatusCode.InternalServerError)); _response.StatusCode = HttpStatusCode.InternalServerError; } + } +#if NETCORE + internal async Task HttpClientExecuteAsync(string method, string name) + { + _receiveData = null; + _response = null; + _errCode = 0; + _errDescription = string.Empty; + GXLogging.Debug(log, "Start Execute: method '" + method + "', name '" + name + "'"); + try + { + string requestUrl = GetRequestURL(name); + bool contextCookies = _context != null && !String.IsNullOrEmpty(requestUrl); + _response = await ExecuteRequestAsync(method, requestUrl, contextCookies); + + if (contextCookies) + _context.UpdateSessionCookieContainer(); + + } + catch (Exception ex) { + ProcessHttpClientException(ex); + } + + GXLogging.Debug(log, "Reading response..."); + if (_response == null) + return; + ProcessResponse(_response); + ClearSendStream(); + } +#endif + public void HttpClientExecute(string method, string name) + { + _receiveData = null; + _response = null; + _errCode = 0; + _errDescription = string.Empty; + GXLogging.Debug(log, "Start Execute: method '" + method + "', name '" + name + "'"); + try + { + string requestUrl = GetRequestURL(name); + bool contextCookies = _context != null && !String.IsNullOrEmpty(requestUrl); + _response = ExecuteRequest(method, requestUrl, contextCookies); + + if (contextCookies) + _context.UpdateSessionCookieContainer(); + + } + catch (Exception ex) + { + ProcessHttpClientException(ex); + } GXLogging.Debug(log, "Reading response..."); if (_response == null) return; @@ -887,11 +1193,13 @@ public void HttpClientExecute(string method, string name) internal void LoadResponseHeaders(HttpResponseMessage resp) { _respHeaders = new NameValueCollection(); - foreach (KeyValuePair> header in resp.Headers) + HttpResponseHeaders headers = resp.Headers; + foreach (KeyValuePair> header in headers) { _respHeaders.Add(header.Key, String.Join(",", header.Value)); } - foreach (KeyValuePair> header in resp.Content.Headers) + HttpContentHeaders contentHeaders = resp.Content.Headers; + foreach (KeyValuePair> header in contentHeaders) { _respHeaders.Add(header.Key, String.Join(",", header.Value)); } @@ -1035,7 +1343,7 @@ private void InferContentType(string contentType, HttpWebRequest req) } } - WebProxy getProxy(string proxyHost, int proxyPort, ArrayList authenticationCollection) + static WebProxy getProxy(string proxyHost, int proxyPort, ArrayList authenticationCollection) { if (proxyHost.Length > 0) { @@ -1101,7 +1409,8 @@ public void ConfigureHttpClientProtocol(string name, SoapHttpClientProtocol http httpC.Timeout = _timeout; } #endif - HttpWebRequest buildRequest(string method, string requestUrl, CookieContainer cookies) +#if NETCORE + async Task buildRequestAsync(string method, string requestUrl, CookieContainer cookies) { GXLogging.Debug(log, String.Format("Start HTTPClient buildRequest: requestUrl:{0} method:{1}", requestUrl, method)); int BytesRead; @@ -1133,8 +1442,56 @@ HttpWebRequest buildRequest(string method, string requestUrl, CookieContainer co #if !NETCORE using (Stream reqStream = req.GetRequestStream()) #else - using (Stream reqStream = req.GetRequestStreamAsync().GetAwaiter().GetResult()) + using (Stream reqStream = await req.GetRequestStreamAsync()) #endif + { + SendVariables(reqStream); + SendStream.Seek(0, SeekOrigin.Begin); + BytesRead = await SendStream.ReadAsync(Buffer, 0, 1024); + GXLogging.Debug(log, "Start SendStream.Read: BytesRead " + BytesRead); + while (BytesRead > 0) + { + GXLogging.Debug(log, "reqStream.Write: Buffer.length " + Buffer.Length + ",'" + Encoding.UTF8.GetString(Buffer, 0, Buffer.Length) + "'"); + await reqStream.WriteAsync(Buffer, 0, BytesRead); + BytesRead = await SendStream.ReadAsync(Buffer, 0, 1024); + } + EndMultipartBoundary(reqStream); + } + } + return req; + } +#endif + + HttpWebRequest buildRequest(string method, string requestUrl, CookieContainer cookies) + { + GXLogging.Debug(log, String.Format("Start HTTPClient buildRequest: requestUrl:{0} method:{1}", requestUrl, method)); + int BytesRead; + Byte[] Buffer = new Byte[1024]; +#pragma warning disable SYSLIB0014 // WebRequest + HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requestUrl); +#pragma warning disable SYSLIB0014 // WebRequest + + if (GXUtil.CompressResponse()) + { + req.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; + } + + req.Credentials = getCredentialCache(req.RequestUri, _authCollection); + req.CookieContainer = cookies; + foreach (X509Certificate2 cert in _certificateCollection) + req.ClientCertificates.Add(cert); + req.Method = method.Trim(); + req.Timeout = _timeout; + setHttpVersion(req); + WebProxy proxy = getProxy(_proxyHost, _proxyPort, _authProxyCollection); + if (proxy != null) + req.Proxy = proxy; + + setHeaders(req); + + if (!method.Equals(HttpMethod.Get.Method, StringComparison.OrdinalIgnoreCase) && !method.Equals(HttpMethod.Head.Method, StringComparison.OrdinalIgnoreCase)) + { + using (Stream reqStream = req.GetRequestStream()) { SendVariables(reqStream); SendStream.Seek(0, SeekOrigin.Begin); @@ -1156,11 +1513,11 @@ public ICredentials GetCredentials(string url) { return getCredentialCache(new Uri(url), _authCollection); } - ICredentials getCredentialCache(Uri URI, ArrayList authenticationCollection) + static ICredentials getCredentialCache(Uri URI, ArrayList authenticationCollection) { string sScheme; GxAuthScheme auth; - CredentialCache cc = new CredentialCache(); + CredentialCache cc = null; for (int i = 0; i < authenticationCollection.Count; i++) { @@ -1190,10 +1547,18 @@ ICredentials getCredentialCache(Uri URI, ArrayList authenticationCollection) } else if (sScheme != "Basic") { + if (cc == null) + { + cc = new CredentialCache(); + } cc.Add(URI, sScheme, new NetworkCredential(auth.User, auth.Password, auth.Realm)); } else { + if (cc == null) + { + cc = new CredentialCache(); + } cc.Add(URI, sScheme, new NetworkCredential(auth.User, auth.Password)); } } @@ -1203,11 +1568,11 @@ ICredentials getCredentialCache(Uri URI, ArrayList authenticationCollection) } return cc; } - - private void WebExecute(string method, string name) +#if NETCORE + private async Task WebExecuteAsync(string method, string name) { HttpWebRequest req; - HttpWebResponse resp = null; + HttpWebResponse resp; _errCode = 0; _errDescription = string.Empty; @@ -1218,43 +1583,140 @@ private void WebExecute(string method, string name) string requestUrl = GetRequestURL(name); bool contextCookies = _context != null && !String.IsNullOrEmpty(requestUrl); CookieContainer cookies = contextCookies ? _context.GetCookieContainer(requestUrl, IncludeCookies) : new CookieContainer(); - req = buildRequest(method, requestUrl, cookies); + req = await buildRequestAsync(method, requestUrl, cookies); -#if NETCORE - resp = req.GetResponse() as HttpWebResponse; + resp = await req.GetResponseAsync() as HttpWebResponse; if (contextCookies) _context.UpdateSessionCookieContainer(); -#else - resp = (HttpWebResponse)req.GetResponse(); -#endif } - catch (WebException e) + catch (Exception e) { - GXLogging.Warn(log, "Error Execute", e); - _errCode = 1; - _errDescription = e.Message; - resp = (HttpWebResponse)(e.Response); + resp = ProcessWebExecuteException(e); } + + + _receiveData = Array.Empty(); + if (resp != null) + { + GXLogging.Debug(log, "Reading response..."); + loadResponseHeaders(resp); + + String charset = resp.ContentType; + using (Stream rStream = resp.GetResponseStream()) + { + try + { + bool encodingFound = false; + if (!string.IsNullOrEmpty(charset)) + { + int idx = charset.IndexOf("charset="); + if (idx > 0) + { + idx += 8; + charset = charset.Substring(idx, charset.Length - idx); + _encoding = GetEncoding(charset); + if (_encoding != null) + encodingFound = true; + } + else + { + charset = String.Empty; + } + } + using (MemoryStream ms = new MemoryStream()) + { + await rStream.CopyToAsync(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) + { + if (_errCode == 1) + GXLogging.Warn(log, "Could not read response", ioEx); + else + throw ioEx; + } + } + _statusCode = (short)resp.StatusCode; + _statusDescription = resp.StatusDescription; + resp.Close(); + + GXLogging.DebugSanitized(log, "_responseString " + ToString()); + } + ClearSendStream(); + } +#endif + private HttpWebResponse ProcessWebExecuteException(Exception ex) + { + WebException we; + HttpWebResponse resp=null; #if NETCORE - catch (AggregateException aex) + AggregateException agge; + if ((agge = ex as AggregateException) != null) { - GXLogging.Warn(log, "Error Execute", aex); + GXLogging.Warn(log, "Error Execute", agge); _errCode = 1; - _errDescription = aex.Message; + _errDescription = agge.Message; - var baseEx = aex.GetBaseException() as WebException; + var baseEx = agge.GetBaseException() as WebException; if (baseEx != null) { resp = baseEx.Response as HttpWebResponse; _errDescription = baseEx.Message; } } + else #endif - catch (Exception e) + if ((we = ex as WebException)!=null) + { + GXLogging.Warn(log, "Error Execute", we); + _errCode = 1; + _errDescription = we.Message; + resp = (HttpWebResponse)(we.Response); + } + else { - GXLogging.Warn(log, "Error Execute", e); + GXLogging.Warn(log, "Error Execute", ex); _errCode = 1; - _errDescription = e.Message; + _errDescription = ex.Message; + } + return resp; + + } + private void WebExecute(string method, string name) + { + HttpWebRequest req; + HttpWebResponse resp = null; + + _errCode = 0; + _errDescription = string.Empty; + + GXLogging.Debug(log, "Start Execute: method '" + method + "', name '" + name + "'"); + try + { + string requestUrl = GetRequestURL(name); + bool contextCookies = _context != null && !String.IsNullOrEmpty(requestUrl); + CookieContainer cookies = contextCookies ? _context.GetCookieContainer(requestUrl, IncludeCookies) : new CookieContainer(); + req = buildRequest(method, requestUrl, cookies); + +#if NETCORE + resp = req.GetResponse() as HttpWebResponse; + if (contextCookies) + _context.UpdateSessionCookieContainer(); +#else + resp = (HttpWebResponse)req.GetResponse(); +#endif + } + catch (Exception e) + { + resp = ProcessWebExecuteException(e); } @@ -1385,10 +1847,9 @@ private Encoding ExtractEncodingFromCharset(string responseText, string regExpP, Encoding enc = null; Match m = Regex.Match(responseText, regExpP); - string parsedEncoding = string.Empty; if (m != null && m.Success) { - parsedEncoding = m.Value; + string parsedEncoding = m.Value; parsedEncoding = parsedEncoding.Substring(startAt, parsedEncoding.Length - (startAt + 1)); enc = GetEncoding(parsedEncoding); } @@ -1414,7 +1875,11 @@ public string ReadChunk() { if (_receivedChunkedStream == null) { +#if NETCORE + _receivedChunkedStream = new StreamReader(_response.Content.ReadAsStream()); +#else _receivedChunkedStream = new StreamReader(_response.Content.ReadAsStreamAsync().GetAwaiter().GetResult()); +#endif } _eof = _receivedChunkedStream.EndOfStream; if (!_eof) @@ -1443,6 +1908,20 @@ public override string ToString() GXLogging.DebugSanitized(log, "_responseString " + responseString); return responseString; } +#if NETCORE + public async Task ToStringAsync() + { + byte[] bytes = await ReceiveDataAsync(); + if (bytes == null) + return string.Empty; + if (_encoding == null) + _encoding = Encoding.UTF8; + string responseString = _encoding.GetString(bytes); + GXLogging.DebugSanitized(log, "_responseString " + responseString); + return responseString; + } +#endif + public void ToFile(string fileName) { string pathName = fileName; @@ -1520,6 +1999,7 @@ public void AddCertificate(string file, string pass) { c = new X509Certificate2(file, pass); } + _fileCertificateCollection.Add(file); _certificateCollection.Add(c); } diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs index dc282f196..65d9c4789 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs @@ -73,6 +73,48 @@ public class WrappedJsonError [DataMember(Name = "error")] public HttpJsonError Error; } +#if NETCORE + internal static class CookiesHelper + { + static readonly IGXLogger log = GXLoggerFactory.GetLogger(typeof(CookiesHelper).FullName); + + internal static void PopulateCookies(this HttpRequestMessage request, CookieContainer cookieContainer) + { + if (cookieContainer != null) + { + IEnumerable cookies = cookieContainer.GetCookies(); + if (cookies.Any()) + { + request.Headers.Add("Cookie", cookies.ToHeaderFormat()); + } + } + } + + private static string ToHeaderFormat(this IEnumerable cookies) + { + return string.Join(";", cookies); + } + internal static void ExtractCookies(this HttpResponseMessage response, CookieContainer cookieContainer) + { + if (response.Headers.TryGetValues("Set-Cookie", out var cookieValues)) + { + Uri uri = response.RequestMessage.RequestUri; + foreach (string cookieValue in cookieValues) + { + try + { + cookieContainer.SetCookies(uri, cookieValue); + } + catch (CookieException ex) + { + GXLogging.Warn(log, $"Ignored cookie for container: {cookieValue} url:{uri}", ex); + } + } + + } + } + } +#endif public class HttpHelper { static readonly IGXLogger log = GXLoggerFactory.GetLogger(); diff --git a/dotnet/test/DotNetUnitTest/Domain/GxHttpClientTest.cs b/dotnet/test/DotNetUnitTest/Domain/GxHttpClientTest.cs index cb9547c4a..68f3fa9ab 100644 --- a/dotnet/test/DotNetUnitTest/Domain/GxHttpClientTest.cs +++ b/dotnet/test/DotNetUnitTest/Domain/GxHttpClientTest.cs @@ -1,5 +1,10 @@ +using System; +using System.Collections.Generic; using System.IO; +using System.Linq; using System.Net; +using System.Net.Http; +using System.Threading.Tasks; using GeneXus.Application; using GeneXus.Http.Client; using Xunit; @@ -13,6 +18,10 @@ namespace xUnitTesting public class GxHttpClientTest { + const int MAX_CONNECTIONS= 5; + public GxHttpClientTest() { + Environment.SetEnvironmentVariable("GX_HTTPCLIENT_MAX_PER_ROUTE", MAX_CONNECTIONS.ToString(), EnvironmentVariableTarget.Process); + } [Fact] public void AddHeaderWithSpecialCharactersDoesNotThrowException() { @@ -68,8 +77,117 @@ public void HttpClientCookieHeader() oldHttpclient.Execute("GET", string.Empty); Assert.NotEqual(((int)HttpStatusCode.InternalServerError), oldHttpclient.StatusCode); } + } +#if NETCORE + [Fact(Skip = "For local testing only")] + public void TestHttpClientMaxPoolSize() + { + HttpClientMaxPoolSize().Wait(); + } + async Task HttpClientMaxPoolSize() { + GxContext context = new GxContext(); + string baseUrl = "http://localhost:8082/HttpClientTestNETSQLServer/testcookies.aspx"; + + var tasks = new List(); + + for (int i = 0; i < MAX_CONNECTIONS * 10; i++) + { + string url = $"{baseUrl}?id=" + i; + tasks.Add(Task.Run(() => ExecuteGet(url))); + } + await Task.WhenAll(tasks); + + Assert.Single(GxHttpClient._httpClientInstances); + + HttpClient c = GxHttpClient._httpClientInstances.First().Value; + Assert.NotNull(c); + + Assert.True(pendingRequestsCount <= MAX_CONNECTIONS, $"Active connections ({pendingRequestsCount}) exceed MaxConnectionsPerServer ({MAX_CONNECTIONS})"); + } + static private int pendingRequestsCount = 0; + static private readonly object syncObject = new object(); + static private void IncrementPendingRequestsCount() + { + lock (syncObject) + { + pendingRequestsCount++; + } + } + static private void DecrementPendingRequestsCount() + { + lock (syncObject) + { + pendingRequestsCount--; + } } + private string ExecuteGet(string url) + { + GxContext context = new GxContext(); + using (GxHttpClient httpclient = new GxHttpClient(context)) + { + IncrementPendingRequestsCount(); + httpclient.HttpClientExecute("GET", url); + Assert.Equal((int)HttpStatusCode.OK, httpclient.StatusCode); //When failed, turn on log.config to see server side error. + DecrementPendingRequestsCount(); + return httpclient.ToString(); + } + } + +#endif + [Fact(Skip = "For local testing only")] + public void HttpClientCookiesTest() + { + GxContext context = new GxContext(); + string baseUrl = "http://localhost:8082/HttpClientTestNETSQLServer/testcookies.aspx"; + + using (GxHttpClient httpclient = new GxHttpClient(context)) + { + string url = $"{baseUrl}?id=1"; + httpclient.HttpClientExecute("GET", url); + Assert.Equal((int)HttpStatusCode.OK, httpclient.StatusCode); + CookieContainer cookies = context.GetCookieContainer(url, true); + Assert.NotNull(cookies); + CookieCollection responseCookies = cookies.GetCookies(new Uri(url)); + Assert.NotEmpty(responseCookies); + string result = httpclient.ToString(); + Assert.Contains("1", result, StringComparison.OrdinalIgnoreCase); + + } + using (GxHttpClient httpclient = new GxHttpClient(context)) + { + string url = $"{baseUrl}?id=2"; + httpclient.IncludeCookies = true; + httpclient.HttpClientExecute("GET", url); + Assert.Equal((int)HttpStatusCode.OK, httpclient.StatusCode); + string result = httpclient.ToString(); + Assert.StartsWith("Cookie found ", result, StringComparison.OrdinalIgnoreCase); + Assert.Contains("2", result, StringComparison.OrdinalIgnoreCase); + } + using (GxHttpClient httpclient = new GxHttpClient(context)) + { + string url = $"{baseUrl}?id=3"; + httpclient.IncludeCookies = false; + httpclient.HttpClientExecute("GET", url); + Assert.Equal((int)HttpStatusCode.OK, httpclient.StatusCode); + string result = httpclient.ToString(); + Assert.StartsWith("Cookie not found", result, StringComparison.OrdinalIgnoreCase); + Assert.Contains("3", result, StringComparison.OrdinalIgnoreCase); + } + using (GxHttpClient httpclient = new GxHttpClient(context)) + { + string url = "https://www.google.com/"; + httpclient.HttpClientExecute("GET", url); + Assert.Equal((int)HttpStatusCode.OK, httpclient.StatusCode); + CookieContainer cookies = context.GetCookieContainer(url, true); + Assert.NotNull(cookies); + CookieCollection responseCookies = cookies.GetCookies(new Uri(url)); + Assert.NotEmpty(responseCookies); + string result = httpclient.ToString(); + } + + } + #if !NETCORE [Fact] public void NoStoreHeader() From a64b1a9b3b429a42262f6e8cfb110bef01271475 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Thu, 11 Apr 2024 11:24:09 -0300 Subject: [PATCH 134/164] Update package references (#979) * Update System.Security.Cryptography.Pkcs from 6.0.3 to 8.0.0 Microsoft.AspNetCore.DataProtection.StackExchangeRedis 3.1.7 to 8.0.3 Microsoft.Extensions.Caching.StackExchangeRedis 3.1.7 to 8.0.3 System.Security.Cryptography.Xml from 4.7.1 to 8.0.0 * Remove unused NetTopologySuite.Core package reference. --- dotnet/src/dotnetcore/GxClasses/GxClasses.csproj | 1 - dotnet/src/dotnetcore/GxExcel/GxExcel.csproj | 2 +- .../src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj | 5 ++--- dotnet/src/dotnetcore/Providers/Cache/GxRedis/GxRedis.csproj | 2 +- .../Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj | 2 +- .../GeneXusXmlSignatureNetCore.csproj | 2 +- 6 files changed, 6 insertions(+), 8 deletions(-) diff --git a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj index 37eb56d95..be360c140 100644 --- a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj +++ b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj @@ -167,7 +167,6 @@ - diff --git a/dotnet/src/dotnetcore/GxExcel/GxExcel.csproj b/dotnet/src/dotnetcore/GxExcel/GxExcel.csproj index 2c747897b..916d3c26d 100644 --- a/dotnet/src/dotnetcore/GxExcel/GxExcel.csproj +++ b/dotnet/src/dotnetcore/GxExcel/GxExcel.csproj @@ -18,7 +18,7 @@ - + diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj b/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj index 4a770c6bc..172d64c86 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj @@ -10,11 +10,10 @@ - - + - + diff --git a/dotnet/src/dotnetcore/Providers/Cache/GxRedis/GxRedis.csproj b/dotnet/src/dotnetcore/Providers/Cache/GxRedis/GxRedis.csproj index f6c96079c..f616027d3 100644 --- a/dotnet/src/dotnetcore/Providers/Cache/GxRedis/GxRedis.csproj +++ b/dotnet/src/dotnetcore/Providers/Cache/GxRedis/GxRedis.csproj @@ -18,7 +18,7 @@ - + diff --git a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj b/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj index 1903997a9..436ee7ca2 100644 --- a/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj +++ b/dotnet/src/extensions/Azure/Handlers/GeneXus.Deploy.AzureFunctions.Handlers.csproj @@ -72,7 +72,7 @@ - + diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusXmlSignatureNetCore/GeneXusXmlSignatureNetCore.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusXmlSignatureNetCore/GeneXusXmlSignatureNetCore.csproj index b6e1601c5..7d3b069e0 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusXmlSignatureNetCore/GeneXusXmlSignatureNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusXmlSignatureNetCore/GeneXusXmlSignatureNetCore.csproj @@ -27,7 +27,7 @@ - + From 7343dded974794d841a9d4485a4dda8d2066ce00 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 17 Apr 2024 12:54:49 -0300 Subject: [PATCH 135/164] Add support for the external object Dictionary. (#918) * Add support for the external object Dictionary. * Simplify the RemoveKey method by removing the redundant ContainsKey condition. --- .../GxClasses/Domain/GxCollections.cs | 189 +++++++++++++++++- .../GxClasses/Helpers/JSONHelper.cs | 29 ++- .../DotNetCoreUnitTest.csproj | 3 +- .../Domain/GxGenericDictionaryTest.cs | 22 ++ 4 files changed, 236 insertions(+), 7 deletions(-) create mode 100644 dotnet/test/DotNetUnitTest/Domain/GxGenericDictionaryTest.cs diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs index 8e372a3c8..6a6a11ab7 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs @@ -14,6 +14,7 @@ namespace GeneXus.Utils using System.Linq; using System.Reflection; using System.Runtime.Serialization; + using System.Runtime.Serialization.Json; using System.Text; using System.Xml; using System.Xml.Serialization; @@ -1563,13 +1564,25 @@ public void AddObjectProperty(string name, object prop, bool includeState) public void AddObjectProperty(string name, object prop, bool includeState, bool includeNonInitialized) { IGxJSONAble ijsonProp = prop as IGxJSONAble; + IGxExternalObject extObj = prop as IGxExternalObject; if (ijsonProp != null) { GxSilentTrnSdt silentTrn = prop as GxSilentTrnSdt; if (silentTrn != null) silentTrn.GetJSONObject(includeState, includeNonInitialized); - else + else if (extObj != null) + { + object extInstance = extObj.ExternalInstance; + IGxJSONAble gxJSONAble = extInstance as IGxJSONAble; + if (gxJSONAble != null) + { + JsonObj.Put(name, gxJSONAble.GetJSONObject(includeState)); + } + } + else + { JsonObj.Put(name, ijsonProp.GetJSONObject(includeState)); + } } else { @@ -1703,7 +1716,14 @@ public void FromJSONObject(dynamic obj) IGXBCCollection bcColl; GxSimpleCollection currSimpleColl; IGxJSONAble currJsonProp; + IGxExternalObject currExtProp; CollectionBase currObjColl = currObj as CollectionBase; + + if ((currExtProp = currProp as IGxExternalObject) != null) + { + currProp = currExtProp.ExternalInstance; + } + #if !NETCORE GxObjectCollectionBase currColl; if ((currColl = currProp as GxObjectCollectionBase) != null) @@ -2460,7 +2480,6 @@ public interface IGxCollection : IGxCollection { T GetNumeric(int idx); } - public interface IGxExternalObject { object ExternalInstance { get; set; } @@ -2859,7 +2878,173 @@ public override string ToString() } } + public class GxGenericDictionary : Dictionary, IGxJSONSerializable, IGxJSONAble + { + private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(GxGenericDictionary)); + private readonly DataContractJsonSerializerSettings settings = new DataContractJsonSerializerSettings() { UseSimpleDictionaryFormat = true }; + public void SetDictionary(GxGenericDictionary dictionary) + { + foreach (var entry in dictionary) + { + this[entry.Key] = entry.Value; + } + } + + public bool Get(TKey key, out TValue value) + { + if (TryGetValue(key, out value)) + { + return true; + } + else + { + return false; + } + } + public TValue Get(TKey key) + { + if (TryGetValue(key, out TValue value)) + { + return value; + + } + else + { + return default; + } + } + public List ValueList + { + get{ + return base.Values.ToList(); + } + } + public List KeyList + { + get + { + return base.Keys.ToList(); + } + } + public void Set(TKey key, TValue value) + { + base[key] = value; + } + + public bool RemoveKey(TKey key) + { + return Remove(key); + } + + public void RemoveKeys(List keys) + { + foreach (var key in keys.ToList()) + { + RemoveKey(key); + } + } + public void RemoveAll(GxGenericDictionary dictionary) + { + foreach (var key in dictionary.Keys.ToList()) + { + RemoveKey(key); + } + } + public string ToJson() + { + try + { + return JSONHelper.Serialize(this, settings); + } + catch (Exception e) + { + log.Error("Could not obtain JSON from Dictionary", e); + return ""; + } + } + + public void FromJson(string json) + { + try + { + Clear(); + Dictionary deserializedDictionary = JSONHelper.Deserialize>(json, Encoding.Unicode, null, null, settings); + foreach (var entry in deserializedDictionary) + { + this[entry.Key] = entry.Value; + } + } + catch (Exception e) + { + log.Error("Could not set Dictionary from JSON", e); + } + } + + public string ToJSonString() + { + return ToJson(); + } + + public bool FromJSonString(string s) + { + throw new NotImplementedException(); + } + + public bool FromJSonString(string s, GXBaseCollection Messages) + { + throw new NotImplementedException(); + } + + public bool FromJSonFile(GxFile file) + { + throw new NotImplementedException(); + } + + public bool FromJSonFile(GxFile file, GXBaseCollection Messages) + { + throw new NotImplementedException(); + } + + public void AddObjectProperty(string name, object prop) + { + throw new NotImplementedException(); + } + + public object GetJSONObject() + { + JObject jObj = new JObject(); + foreach (TKey item in Keys) + { + jObj.Accumulate(item.ToString(), this[item]); + } + return jObj; + + } + + public object GetJSONObject(bool includeState) + { + return GetJSONObject(); + } + + public void FromJSONObject(dynamic obj) + { + this.Clear(); + JObject jObj = obj as JObject; + if (jObj != null) + { + foreach (DictionaryEntry item in jObj) + { + base[(TKey)item.Key]= (TValue)item.Value; + } + } + } + + public string ToJavascriptSource() + { + throw new NotImplementedException(); + } + } public class GxDictionary : Dictionary { public bool HasKey(string key) diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/JSONHelper.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/JSONHelper.cs index aa22bc428..5cce38a9a 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/JSONHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/JSONHelper.cs @@ -257,7 +257,7 @@ public static string Serialize(T kbObject, Encoding encoding, IEnumerable(T kbObject, Encoding encoding, IEnumerable(T kbObject, DataContractJsonSerializerSettings settings) where T : class + { + try + { + Encoding encoding = Encoding.UTF8; + DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T), settings); + using (MemoryStream stream = new MemoryStream()) + { + serializer.WriteObject(stream, kbObject); + return encoding.GetString(stream.ToArray()); + } + } + catch (Exception ex) + { + GXLogging.Error(log, "Serialize error ", ex); + } + return null; + } internal static string WCFSerialize(T kbObject, Encoding encoding, IEnumerable knownTypes, bool useSimpleDictionaryFormat) where T : class { try @@ -319,12 +337,16 @@ static DataContractJsonSerializerSettings WCFSerializationSettings(IEnumerable(kbObject, encoding, knownTypes, new T()); } public static T Deserialize(string kbObject, Encoding encoding, IEnumerable knownTypes, T defaultValue) where T : class + { + var settings = SerializationSettings(knownTypes); + return Deserialize(kbObject, encoding, knownTypes, defaultValue, settings); + } + internal static T Deserialize(string kbObject, Encoding encoding, IEnumerable knownTypes, T defaultValue, DataContractJsonSerializerSettings settings) where T : class { if (!string.IsNullOrEmpty(kbObject)) { try { - var settings = SerializationSettings(knownTypes); using (MemoryStream stream = new MemoryStream(encoding.GetBytes(kbObject))) { DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T), settings); @@ -342,14 +364,13 @@ public static T Deserialize(string kbObject, Encoding encoding, IEnumerable(string kbObject, Encoding encoding) where T : class, new() { - return Deserialize(kbObject, Encoding.Unicode, null, new T()); + return Deserialize(kbObject, encoding, null, new T()); } public static T Deserialize(string kbObject) where T : class, new() { return Deserialize(kbObject, Encoding.Unicode); } - public static T DeserializeNullDefaultValue(string kbObject) where T : class { return Deserialize(kbObject, Encoding.Unicode, null, null); diff --git a/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj b/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj index dafd99b31..1bf70900a 100644 --- a/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj +++ b/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj @@ -15,6 +15,7 @@ + @@ -73,7 +74,7 @@ all - + diff --git a/dotnet/test/DotNetUnitTest/Domain/GxGenericDictionaryTest.cs b/dotnet/test/DotNetUnitTest/Domain/GxGenericDictionaryTest.cs new file mode 100644 index 000000000..b76067c32 --- /dev/null +++ b/dotnet/test/DotNetUnitTest/Domain/GxGenericDictionaryTest.cs @@ -0,0 +1,22 @@ +using GeneXus.Utils; +using Xunit; + +namespace xUnitTesting +{ + public class GxGenericDictionaryTest + { + [Fact] + public void ToJsonTest() + { + GxGenericDictionary dic = new GxGenericDictionary + { + { "key1", 1 }, + { "key2", 2 } + }; + string json = dic.ToJson(); + string expectedJson = "{\"key1\":1,\"key2\":2}"; + Assert.Equal(expectedJson, json); + } + + } +} From e34f86303d8ed46c61fd1f6130d0bca28645983e Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 23 Apr 2024 09:25:28 -0300 Subject: [PATCH 136/164] Basic Authentication user ID was not properly parsed when the password contained the special separator character ':'. (#989) --- .../GxClasses/Helpers/BasicAuthentication.cs | 28 +++++++++------ .../Middleware/HeadersTest.cs | 7 +++- .../DotNetCoreWebUnitTest/apps/httpheaders.cs | 35 ++++++++++++++++++- 3 files changed, 57 insertions(+), 13 deletions(-) diff --git a/dotnet/src/dotnetcore/GxClasses/Helpers/BasicAuthentication.cs b/dotnet/src/dotnetcore/GxClasses/Helpers/BasicAuthentication.cs index f6d093183..d7cdc1ca2 100644 --- a/dotnet/src/dotnetcore/GxClasses/Helpers/BasicAuthentication.cs +++ b/dotnet/src/dotnetcore/GxClasses/Helpers/BasicAuthentication.cs @@ -1,11 +1,11 @@ -using System; -using System.Collections.Generic; +using System; using System.Text; namespace GxClasses.Helpers { public class BasicAuthenticationHeaderValue { + const char UserNamePasswordSeparator= ':'; public BasicAuthenticationHeaderValue(string authenticationHeaderValue) { if (!string.IsNullOrWhiteSpace(authenticationHeaderValue)) @@ -19,7 +19,7 @@ public BasicAuthenticationHeaderValue(string authenticationHeaderValue) } private readonly string _authenticationHeaderValue; - private string[] _splitDecodedCredentials; + private string _usernamePassword; public bool IsValidBasicAuthenticationHeaderValue { get; private set; } public string UserIdentifier { get; private set; } @@ -32,11 +32,11 @@ private bool TryDecodeHeaderValue() { return false; } - var encodedCredentials = _authenticationHeaderValue.Substring(headerSchemeLength); + string encodedCredentials = _authenticationHeaderValue.Substring(headerSchemeLength); try { - var decodedCredentials = Convert.FromBase64String(encodedCredentials); - _splitDecodedCredentials = System.Text.Encoding.ASCII.GetString(decodedCredentials).Split(':'); + byte[] decodedCredentials = Convert.FromBase64String(encodedCredentials); + _usernamePassword = Encoding.ASCII.GetString(decodedCredentials); return true; } catch (FormatException) @@ -47,13 +47,19 @@ private bool TryDecodeHeaderValue() private void ReadAuthenticationHeaderValue() { - IsValidBasicAuthenticationHeaderValue = _splitDecodedCredentials!= null && _splitDecodedCredentials.Length == 2 - && !string.IsNullOrWhiteSpace(_splitDecodedCredentials[0]) - && !string.IsNullOrWhiteSpace(_splitDecodedCredentials[1]); + IsValidBasicAuthenticationHeaderValue = !string.IsNullOrEmpty(_usernamePassword) && _usernamePassword.Contains(UserNamePasswordSeparator); if (IsValidBasicAuthenticationHeaderValue) { - UserIdentifier = _splitDecodedCredentials[0]; - UserPassword = _splitDecodedCredentials[1]; + int separatorIndex = _usernamePassword.IndexOf(UserNamePasswordSeparator); + UserIdentifier = _usernamePassword.Substring(0, separatorIndex); + if (separatorIndex + 1 < _usernamePassword.Length) + { + UserPassword = _usernamePassword.Substring(separatorIndex + 1); + } + else + { + UserPassword = string.Empty; + } } } } diff --git a/dotnet/test/DotNetCoreWebUnitTest/Middleware/HeadersTest.cs b/dotnet/test/DotNetCoreWebUnitTest/Middleware/HeadersTest.cs index cc26e10e5..da4184ca4 100644 --- a/dotnet/test/DotNetCoreWebUnitTest/Middleware/HeadersTest.cs +++ b/dotnet/test/DotNetCoreWebUnitTest/Middleware/HeadersTest.cs @@ -3,6 +3,7 @@ using System.Reflection; using System.Threading.Tasks; using GeneXus.Metadata; +using GeneXus.Utils; using Xunit; namespace xUnitTesting { @@ -25,14 +26,18 @@ public async Task TestForwardedHeaders() const string host = "192.168.1.100"; const string scheme = "https"; const string remoteUrl = $"{scheme}:\\/\\/{host}"; + const string passwordWithSpecialCharacters = "mypasswordwithspecialcharacters:!*"; + const string userId = "myuser"; HttpClient client = server.CreateClient(); client.DefaultRequestHeaders.Add("X-Forwarded-For", host); client.DefaultRequestHeaders.Add("X-Forwarded-Proto", scheme); + client.DefaultRequestHeaders.Add("Authorization", $"Basic {StringUtil.ToBase64(userId+ ":" + passwordWithSpecialCharacters)}"); HttpResponseMessage response = await client.GetAsync("/rest/apps/httpheaders"); response.EnsureSuccessStatusCode(); string resp = await response.Content.ReadAsStringAsync(); - Assert.Contains(remoteUrl, resp, System.StringComparison.OrdinalIgnoreCase); + Assert.Contains(remoteUrl, resp, StringComparison.OrdinalIgnoreCase); + Assert.Contains(userId, resp, StringComparison.OrdinalIgnoreCase); Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); } diff --git a/dotnet/test/DotNetCoreWebUnitTest/apps/httpheaders.cs b/dotnet/test/DotNetCoreWebUnitTest/apps/httpheaders.cs index 5e8a8fef4..9c0a293a7 100644 --- a/dotnet/test/DotNetCoreWebUnitTest/apps/httpheaders.cs +++ b/dotnet/test/DotNetCoreWebUnitTest/apps/httpheaders.cs @@ -1,6 +1,9 @@ +using System; using GeneXus.Application; using GeneXus.Data.NTier; +using GeneXus.Data.NTier.ADO; using GeneXus.Procedure; +using GeneXus.Utils; namespace GeneXus.Programs.apps { @@ -30,7 +33,7 @@ public void execute(out string result) void executePrivate(out string result) { result = (context.GetHttpSecure() == 1 ? "https://" : "http://") + context.GetRemoteAddress(); - + result += StringUtil.NewLine() + GXUtil.UserId(string.Empty, context, pr_default); cleanup(); } @@ -51,7 +54,37 @@ protected void CloseOpenCursors() public override void initialize() { + pr_default = new DataStoreProvider(context, new httpheaders__default(), + new Object[][] { + } + ); } + private IDataStoreProvider pr_default; } + public class httpheaders__default : DataStoreHelperBase, IDataStoreHelper + { + public ICursor[] getCursors() + { + cursorDefinitions(); + return new Cursor[] { + }; + } + + private static CursorDef[] def; + private void cursorDefinitions() + { + if (def == null) + { + def = new CursorDef[] { + }; + } + } + public void getResults(int cursor, + IFieldGetter rslt, + Object[] buf) + { + } + + } } From b4e6fbfca13aa7aaa7d1e702354ba6759befcd56 Mon Sep 17 00:00:00 2001 From: Alejandro Panizza Carve Date: Tue, 23 Apr 2024 13:33:53 -0300 Subject: [PATCH 137/164] - Fix for services json input to use SDTs "JsonName"property (#955) 106788 --- .../GxClasses/Services/ReflectionHelper.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Services/ReflectionHelper.cs b/dotnet/src/dotnetframework/GxClasses/Services/ReflectionHelper.cs index baafc35e2..8d4c98aef 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/ReflectionHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/ReflectionHelper.cs @@ -259,11 +259,18 @@ internal static object[] ProcessParametersForInvoke(MethodInfo methodInfo, IDict string gxParameterName = GxParameterName(methodParameter.Name).ToLower(); Type parmType = methodParameter.ParameterType; + string jsontypename = ""; + object[] attributes = parmType.GetCustomAttributes(true); + GxJsonName jsonName = (GxJsonName)attributes.Where(a => a.GetType() == typeof(GxJsonName)).FirstOrDefault(); + if (jsonName != null) + jsontypename = jsonName.Name.ToLower(); + else + jsontypename = gxParameterName; if (IsByRefParameter(methodParameter)) { parmType = parmType.GetElementType(); } - if (parameters != null && parameters.TryGetValue(gxParameterName, out value)) + if (parameters != null && parameters.TryGetValue(jsontypename, out value)) { if (value == null || JSONHelper.IsJsonNull(value)) { From 8ba5a1d6d818cbfa28e193b015ded83f07066603 Mon Sep 17 00:00:00 2001 From: Alejandro Panizza Carve Date: Tue, 23 Apr 2024 13:34:29 -0300 Subject: [PATCH 138/164] Fix issue #105929. Error with API object that return basic type collection #910 (#1004) --- .../GxClasses/Services/GxRestWrapper.cs | 41 ++++++++++++------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs index 40e24a0c3..4f8f98eed 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs @@ -880,29 +880,40 @@ protected static object MakeRestType( object collectionValue, bool isApiObject) if (vType.IsConstructedGenericType && typeof(IGxCollection).IsAssignableFrom(vType)) { bool isWrapped = (isApiObject)?false:true; + bool isEmpty = false; object collectionObject = null; string wrappedStatus = ""; Type restItemType=null; itemType = collectionValue.GetType().GetGenericArguments()[0]; - if ((typeof(IGXBCCollection).IsAssignableFrom(vType)) && !isApiObject)//Collection convert to GxGenericCollection + if (vType.GetGenericTypeDefinition() == typeof(GxSimpleCollection<>) && isApiObject) { - restItemType = ClassLoader.FindType(Config.CommonAssemblyName, itemType.FullName + "_RESTLInterface", null); + restItemType = itemType; + isEmpty = true; + isWrapped = false; + collectionObject = collectionValue; } - if (restItemType == null)//Collection convert to GxGenericCollection - { - restItemType = ClassLoader.FindType(Config.CommonAssemblyName, itemType.FullName + "_RESTInterface", null); - } - object[] attributes = restItemType.GetCustomAttributes(typeof(GxJsonSerialization), false); - IEnumerable serializationAttributes = attributes.Where(a => a.GetType() == typeof(GxJsonSerialization)); - if (serializationAttributes != null && serializationAttributes.Any()) + else { - GxJsonSerialization attFmt = (GxJsonSerialization)serializationAttributes.FirstOrDefault(); - wrappedStatus = attFmt.JsonUnwrapped; - isWrapped = (isApiObject)? ((wrappedStatus == "wrapped")? true: false): ((wrappedStatus == "unwrapped") ? false : true); + if ((typeof(IGXBCCollection).IsAssignableFrom(vType)) && !isApiObject)//Collection convert to GxGenericCollection + { + restItemType = ClassLoader.FindType(Config.CommonAssemblyName, itemType.FullName + "_RESTLInterface", null); + } + if (restItemType == null)//Collection convert to GxGenericCollection + { + restItemType = ClassLoader.FindType(Config.CommonAssemblyName, itemType.FullName + "_RESTInterface", null); + } + object[] attributes = restItemType.GetCustomAttributes(typeof(GxJsonSerialization), false); + IEnumerable serializationAttributes = attributes.Where(a => a.GetType() == typeof(GxJsonSerialization)); + if (serializationAttributes != null && serializationAttributes.Any()) + { + GxJsonSerialization attFmt = (GxJsonSerialization)serializationAttributes.FirstOrDefault(); + wrappedStatus = attFmt.JsonUnwrapped; + isWrapped = (isApiObject)? ((wrappedStatus == "wrapped")? true: false): ((wrappedStatus == "unwrapped") ? false : true); + } + isEmpty = !restItemType.IsDefined(typeof(GxOmitEmptyCollection), false); + Type genericListItemType = typeof(GxGenericCollection<>).MakeGenericType(restItemType); + collectionObject = Activator.CreateInstance(genericListItemType, new object[] { collectionValue, isWrapped , wrappedStatus}); } - bool isEmpty = !restItemType.IsDefined(typeof(GxOmitEmptyCollection), false); - Type genericListItemType = typeof(GxGenericCollection<>).MakeGenericType(restItemType); - collectionObject = Activator.CreateInstance(genericListItemType, new object[] { collectionValue, isWrapped , wrappedStatus}); // Empty collection serialized w/ noproperty if (collectionObject is IList restList) { From 2625f1ea93c9100aa9727a27fc96b19d7604dd59 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 24 Apr 2024 14:02:47 -0300 Subject: [PATCH 139/164] Restore fix on #838 (#1008) --- dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs index ce88fa4ec..3374cf1f1 100644 --- a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs +++ b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs @@ -49,7 +49,7 @@ public abstract class PDFReportBase : IReportHandler protected bool modal = false; protected String docName = "PDFReport.pdf"; protected static NativeSharpFunctionsMS nativeCode = new NativeSharpFunctionsMS(); - protected Hashtable fontSubstitutes = new Hashtable(); + protected static Hashtable fontSubstitutes = new Hashtable(); protected static String configurationFile = null; protected static String configurationTemplateFile = null; protected static String defaultRelativePrepend = null; From 9b820abe334fb9ad2b7fa65fd0a2aeeda1325549 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 24 Apr 2024 14:56:29 -0300 Subject: [PATCH 140/164] The ServicesGroupSetting was failing due to duplicate object names (#1001) * ServicesGroupSetting was failing when having duplicated object names (because of a rename) or empty .json. Issue:107364 * The ServicesGroupSetting was failing due to duplicate object names resulting from a rename or empty .json files. This fix is the equivalent of #507 for .NET Core. Issue:107364 --- .../GxClasses/Middleware/GXHttpModules.cs | 116 ++++++++++-------- .../test/DotNetUnitTest/DotNetUnitTest.csproj | 30 +++++ dotnet/test/DotNetUnitTest/Routing.cs | 18 +++ .../test/DotNetUnitTest/private/api1.grp.json | 0 .../DotNetUnitTest/private/api_4r.grp.json | 23 ++++ .../DotNetUnitTest/private/c003_api.grp.json | 71 +++++++++++ .../DotNetUnitTest/private/c007_api.grp.json | 31 +++++ .../private/casosdates.grp.json | 15 +++ .../private/casosdatetimes.grp.json | 23 ++++ .../private/mailmanagement.grp.json | 25 ++++ .../private/mailmanagement_a.grp.json | 25 ++++ .../private/mailmanagementsso.grp.json | 25 ++++ .../private/mailmanagementv2.grp.json | 25 ++++ 13 files changed, 373 insertions(+), 54 deletions(-) create mode 100644 dotnet/test/DotNetUnitTest/Routing.cs create mode 100644 dotnet/test/DotNetUnitTest/private/api1.grp.json create mode 100644 dotnet/test/DotNetUnitTest/private/api_4r.grp.json create mode 100644 dotnet/test/DotNetUnitTest/private/c003_api.grp.json create mode 100644 dotnet/test/DotNetUnitTest/private/c007_api.grp.json create mode 100644 dotnet/test/DotNetUnitTest/private/casosdates.grp.json create mode 100644 dotnet/test/DotNetUnitTest/private/casosdatetimes.grp.json create mode 100644 dotnet/test/DotNetUnitTest/private/mailmanagement.grp.json create mode 100644 dotnet/test/DotNetUnitTest/private/mailmanagement_a.grp.json create mode 100644 dotnet/test/DotNetUnitTest/private/mailmanagementsso.grp.json create mode 100644 dotnet/test/DotNetUnitTest/private/mailmanagementv2.grp.json diff --git a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpModules.cs b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpModules.cs index f88ba3c46..c13b10323 100644 --- a/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpModules.cs +++ b/dotnet/src/dotnetframework/GxClasses/Middleware/GXHttpModules.cs @@ -53,7 +53,7 @@ public class MapGroup public class GXAPIModule : IHttpModule { - + static private readonly object syncObject = new object(); public static List servicesPathUrl; public static Dictionary servicesBase; public static Dictionary servicesClass; @@ -135,69 +135,77 @@ public static Boolean serviceInPath(String path, out String actualPath) public void ServicesGroupSetting(string webPath) { if (!String.IsNullOrEmpty(webPath) && servicesMap == null) - { - servicesPathUrl = new List(); - servicesBase = new Dictionary(); - servicesMap = new Dictionary>(); - //servicesVerbs = new Dictionary>(); - servicesMapData = new Dictionary, string>>(); - servicesClass = new Dictionary(); - - if (Directory.Exists(Path.Combine(webPath, PRIVATE_DIR))) + { + lock (syncObject) { - String[] grpFiles = Directory.GetFiles(Path.Combine(webPath, PRIVATE_DIR), "*.grp.json"); - foreach (String grp in grpFiles) + if (servicesMap == null) { -#pragma warning disable SCS0018 // Path traversal: injection possible in {1} argument passed to '{0}' - object p = JSONHelper.Deserialize(File.ReadAllText(grp)); -#pragma warning restore SCS0018 - MapGroup m = p as MapGroup; - if (m != null && m.Name != null && m.Mappings != null ) - { + servicesPathUrl = new List(); + servicesBase = new Dictionary(); + servicesMap = new Dictionary>(); + //servicesVerbs = new Dictionary>(); + servicesMapData = new Dictionary, string>>(); + servicesClass = new Dictionary(); - if (String.IsNullOrEmpty(m.BasePath)) - { - m.BasePath = REST_BASE_URL; - } - String mapPath = (m.BasePath.EndsWith("/")) ? m.BasePath : m.BasePath + "/"; - String mapPathLower = mapPath.ToLower(); - servicesPathUrl.Add(mapPathLower); - servicesBase.Add(mapPathLower, m.Name.ToLower()); - servicesClass.Add(mapPathLower, m.Name.ToLower() + "_services"); - foreach (SingleMap sm in m.Mappings) + if (Directory.Exists(Path.Combine(webPath, PRIVATE_DIR))) + { + String[] grpFiles = Directory.GetFiles(Path.Combine(webPath, PRIVATE_DIR), "*.grp.json"); + foreach (String grp in grpFiles) { - if (String.IsNullOrEmpty(sm.Verb)) - sm.Verb = "GET"; - if (sm.VariableAlias == null) - sm.VariableAlias = new Dictionary(); - else + string content = File.ReadAllText(grp); + if (!string.IsNullOrEmpty(content)) { - Dictionary vMap = new Dictionary(); - foreach (KeyValuePair v in sm.VariableAlias) +#pragma warning disable SCS0018 // Path traversal: injection possible in {1} argument passed to '{0}' + object p = JSONHelper.Deserialize(content); +#pragma warning restore SCS0018 + MapGroup m = p as MapGroup; + if (m != null && m.Name != null && m.Mappings != null) { - vMap.Add(v.Key.ToLower(), v.Value.ToLower()); - } - sm.VariableAlias = vMap; - } - if (servicesMap.ContainsKey(mapPathLower)) - { - if (!servicesMap[mapPathLower].ContainsKey(sm.Name.ToLower())) - { - servicesMapData[mapPathLower].Add(Tuple.Create(sm.Path.ToLower(), sm.Verb), sm.Name.ToLower()); - servicesMap[mapPathLower].Add(sm.Name.ToLower(), sm); + + if (String.IsNullOrEmpty(m.BasePath)) + { + m.BasePath = REST_BASE_URL; + } + String mapPath = (m.BasePath.EndsWith("/")) ? m.BasePath : m.BasePath + "/"; + String mapPathLower = mapPath.ToLower(); + servicesPathUrl.Add(mapPathLower); + servicesBase[mapPathLower]= m.Name.ToLower(); + servicesClass[mapPathLower]= m.Name.ToLower() + "_services"; + foreach (SingleMap sm in m.Mappings) + { + if (String.IsNullOrEmpty(sm.Verb)) + sm.Verb = "GET"; + if (sm.VariableAlias == null) + sm.VariableAlias = new Dictionary(); + else + { + Dictionary vMap = new Dictionary(); + foreach (KeyValuePair v in sm.VariableAlias) + { + vMap.Add(v.Key.ToLower(), v.Value.ToLower()); + } + sm.VariableAlias = vMap; + } + if (servicesMap.ContainsKey(mapPathLower)) + { + if (!servicesMap[mapPathLower].ContainsKey(sm.Name.ToLower())) + { + servicesMapData[mapPathLower].Add(Tuple.Create(sm.Path.ToLower(), sm.Verb), sm.Name.ToLower()); + servicesMap[mapPathLower].Add(sm.Name.ToLower(), sm); + } + } + else + { + servicesMapData.Add(mapPathLower, new Dictionary, string>()); + servicesMapData[mapPathLower].Add(Tuple.Create(sm.Path.ToLower(), sm.Verb), sm.Name.ToLower()); + servicesMap.Add(mapPathLower, new Dictionary()); + servicesMap[mapPathLower].Add(sm.Name.ToLower(), sm); + } + } } } - else - { - servicesMapData.Add(mapPathLower, new Dictionary, string>()); - servicesMapData[mapPathLower].Add(Tuple.Create(sm.Path.ToLower(), sm.Verb), sm.Name.ToLower()); - servicesMap.Add(mapPathLower, new Dictionary()); - servicesMap[mapPathLower].Add(sm.Name.ToLower(), sm); - } - } } - } } } diff --git a/dotnet/test/DotNetUnitTest/DotNetUnitTest.csproj b/dotnet/test/DotNetUnitTest/DotNetUnitTest.csproj index e2b6fd86e..164d730a1 100644 --- a/dotnet/test/DotNetUnitTest/DotNetUnitTest.csproj +++ b/dotnet/test/DotNetUnitTest/DotNetUnitTest.csproj @@ -85,6 +85,36 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + SettingsSingleFileGenerator Settings.Designer.cs diff --git a/dotnet/test/DotNetUnitTest/Routing.cs b/dotnet/test/DotNetUnitTest/Routing.cs new file mode 100644 index 000000000..030997efc --- /dev/null +++ b/dotnet/test/DotNetUnitTest/Routing.cs @@ -0,0 +1,18 @@ +using System.IO; +using GeneXus.Http.HttpModules; +using Xunit; + +namespace xUnitTesting +{ + public class RoutingTest + { + + [Fact] + public void TestLoadGRPC() + { + GXAPIModule gxAPIModule = new GXAPIModule(); + gxAPIModule.ServicesGroupSetting(Path.Combine(Directory.GetCurrentDirectory())); + Assert.NotEmpty(GXAPIModule.servicesMap); + } + } +} diff --git a/dotnet/test/DotNetUnitTest/private/api1.grp.json b/dotnet/test/DotNetUnitTest/private/api1.grp.json new file mode 100644 index 000000000..e69de29bb diff --git a/dotnet/test/DotNetUnitTest/private/api_4r.grp.json b/dotnet/test/DotNetUnitTest/private/api_4r.grp.json new file mode 100644 index 000000000..26a48a199 --- /dev/null +++ b/dotnet/test/DotNetUnitTest/private/api_4r.grp.json @@ -0,0 +1,23 @@ +{ +"ObjectType":"ServiceGroup", +"Name":"API_4R", +"BasePath":"API_4R", +"Mappings": +[ +{ +"Name":"consultaget", +"Path":"consultaget", +"ServiceMethod":"gxep_consultaget", +"Implementation":"ConsultarIPTU", +"Bodystyle":"Wrapped", +"Verb":"GET" +} +, +{ +"Bodystyle":"Wrapped", +"Verb":"POST", +"Name":"consultapost__post", +"Path":"consultapost", +"ServiceMethod":"gxep_consultapost__post", +"Implementation":"ConsultarIPTU" +}]} \ No newline at end of file diff --git a/dotnet/test/DotNetUnitTest/private/c003_api.grp.json b/dotnet/test/DotNetUnitTest/private/c003_api.grp.json new file mode 100644 index 000000000..f10b5f1a5 --- /dev/null +++ b/dotnet/test/DotNetUnitTest/private/c003_api.grp.json @@ -0,0 +1,71 @@ +{ +"ObjectType":"ServiceGroup", +"Name":"C003_API", +"BasePath":"C003_API", +"Mappings": +[ +{ +"Bodystyle":"Wrapped", +"Verb":"POST", +"Name":"c003_return1sdtsimple__post", +"Path":"c003_return1sdtsimple", +"ServiceMethod":"gxep_c003_return1sdtsimple__post", +"Implementation":"C003_Return1SdtSimple" +} +, +{ +"Bodystyle":"Wrapped", +"Verb":"POST", +"Name":"c003_return1sdtsimpleempty__post", +"Path":"c003_return1sdtsimpleempty", +"ServiceMethod":"gxep_c003_return1sdtsimpleempty__post", +"Implementation":"C003_Return1SdtSimpleEmpty" +}, +{ +"Bodystyle":"Wrapped", +"Verb":"POST", +"Name":"c003_returnvariables__post", +"Path":"c003_returnvariables", +"ServiceMethod":"gxep_c003_returnvariables__post", +"Implementation":"C003_ReturnVariables" +}, +{ +"Bodystyle":"Wrapped", +"Verb":"POST", +"Name":"c003_return1sdtout__post", +"Path":"c003_return1sdtout", +"ServiceMethod":"gxep_c003_return1sdtout__post", +"Implementation":"C003_Return1SdtOut" +}, +{ +"Bodystyle":"Wrapped", +"Verb":"POST", +"Name":"c003_return1sdtoutempty__post", +"Path":"c003_return1sdtoutempty", +"ServiceMethod":"gxep_c003_return1sdtoutempty__post", +"Implementation":"C003_Return1SdtOutEmpty" +}, +{ +"Bodystyle":"Wrapped", +"Verb":"POST", +"Name":"c003_return2sdtout__post", +"Path":"c003_return2sdtout", +"ServiceMethod":"gxep_c003_return2sdtout__post", +"Implementation":"C003_Return2SdtOut" +}, +{ +"Bodystyle":"Wrapped", +"Verb":"POST", +"Name":"c003_returnsdtcollection__post", +"Path":"c003_returnsdtcollection", +"ServiceMethod":"gxep_c003_returnsdtcollection__post", +"Implementation":"C003_ReturnSDTCollection" +}, +{ +"Bodystyle":"Wrapped", +"Verb":"POST", +"Name":"c003_returnsdtcollectionempty__post", +"Path":"c003_returnsdtcollectionempty", +"ServiceMethod":"gxep_c003_returnsdtcollectionempty__post", +"Implementation":"C003_ReturnSDTCollectionEmpty" +}]} \ No newline at end of file diff --git a/dotnet/test/DotNetUnitTest/private/c007_api.grp.json b/dotnet/test/DotNetUnitTest/private/c007_api.grp.json new file mode 100644 index 000000000..e923051da --- /dev/null +++ b/dotnet/test/DotNetUnitTest/private/c007_api.grp.json @@ -0,0 +1,31 @@ +{ +"ObjectType":"ServiceGroup", +"Name":"C007_API", +"BasePath":"C007_API", +"Mappings": +[ +{ +"Name":"c007_getsdt1", +"Path":"c007_getsdt1", +"ServiceMethod":"gxep_c007_getsdt1", +"Implementation":"C007_GetSDT1", +"Bodystyle":"Wrapped", +"Verb":"GET" +} +, +{ +"Name":"c007_getsdt2wrapped", +"Path":"c007_getsdt2wrapped", +"ServiceMethod":"gxep_c007_getsdt2wrapped", +"Implementation":"C007_GetSDT2Wrapped", +"Bodystyle":"Wrapped", +"Verb":"GET" +}, +{ +"Name":"c007_getsdt2sequence", +"Path":"c007_getsdt2sequence", +"ServiceMethod":"gxep_c007_getsdt2sequence", +"Implementation":"C007_GetSDT2Sequence", +"Bodystyle":"Wrapped", +"Verb":"GET" +}]} \ No newline at end of file diff --git a/dotnet/test/DotNetUnitTest/private/casosdates.grp.json b/dotnet/test/DotNetUnitTest/private/casosdates.grp.json new file mode 100644 index 000000000..ac979d9a0 --- /dev/null +++ b/dotnet/test/DotNetUnitTest/private/casosdates.grp.json @@ -0,0 +1,15 @@ +{ +"ObjectType":"ServiceGroup", +"Name":"CasosDates", +"BasePath":"CasosDates", +"Mappings": +[ +{ +"Bodystyle":"Wrapped", +"Verb":"POST", +"Name":"testdatedef__post", +"Path":"testdatedef", +"ServiceMethod":"gxep_testdatedef__post", +"Implementation":"SampleProc" +} +]} \ No newline at end of file diff --git a/dotnet/test/DotNetUnitTest/private/casosdatetimes.grp.json b/dotnet/test/DotNetUnitTest/private/casosdatetimes.grp.json new file mode 100644 index 000000000..ceee82f19 --- /dev/null +++ b/dotnet/test/DotNetUnitTest/private/casosdatetimes.grp.json @@ -0,0 +1,23 @@ +{ +"ObjectType":"ServiceGroup", +"Name":"CasosDatetimes", +"BasePath":"CasosDatetimes", +"Mappings": +[ +{ +"Bodystyle":"Wrapped", +"Verb":"POST", +"Name":"testdtdef__post", +"Path":"testdtdef", +"ServiceMethod":"gxep_testdtdef__post", +"Implementation":"SampleProc" +} +, +{ +"Bodystyle":"Wrapped", +"Verb":"POST", +"Name":"testdtconms__post", +"Path":"testdtconms", +"ServiceMethod":"gxep_testdtconms__post", +"Implementation":"SampleProc" +}]} \ No newline at end of file diff --git a/dotnet/test/DotNetUnitTest/private/mailmanagement.grp.json b/dotnet/test/DotNetUnitTest/private/mailmanagement.grp.json new file mode 100644 index 000000000..085717211 --- /dev/null +++ b/dotnet/test/DotNetUnitTest/private/mailmanagement.grp.json @@ -0,0 +1,25 @@ +{ +"ObjectType":"ServiceGroup", +"Name":"mailmanagement", +"BasePath":"mailmanagement", +"Mappings": +[ +{ +"Bodystyle":"Wrapped", +"Verb":"POST", +"Name":"enviarmail__post", +"Path":"enviarmail", +"VariableAlias": [], +"ServiceMethod":"gxep_enviarmail__post", +"Implementation":"MailServices\\SendMail" +} +, +{ +"Bodystyle":"Wrapped", +"Verb":"POST", +"Name":"enviarmailv1__post", +"Path":"enviarmailv1", +"VariableAlias": [], +"ServiceMethod":"gxep_enviarmailv1__post", +"Implementation":"MailServices\\SendMailSMTP" +}]} \ No newline at end of file diff --git a/dotnet/test/DotNetUnitTest/private/mailmanagement_a.grp.json b/dotnet/test/DotNetUnitTest/private/mailmanagement_a.grp.json new file mode 100644 index 000000000..3a9ede1e0 --- /dev/null +++ b/dotnet/test/DotNetUnitTest/private/mailmanagement_a.grp.json @@ -0,0 +1,25 @@ +{ +"ObjectType":"ServiceGroup", +"Name":"mailmanagement_A", +"BasePath":"mailmanagementSSO", +"Mappings": +[ +{ +"Bodystyle":"Wrapped", +"Verb":"POST", +"Name":"enviarmail__post", +"Path":"enviarmail", +"VariableAlias": [], +"ServiceMethod":"gxep_enviarmail__post", +"Implementation":"MailServices\\SendMail" +} +, +{ +"Bodystyle":"Wrapped", +"Verb":"POST", +"Name":"enviarmailv1__post", +"Path":"enviarmailv1", +"VariableAlias": [], +"ServiceMethod":"gxep_enviarmailv1__post", +"Implementation":"MailServices\\SendMailSMTP_SSORest" +}]} \ No newline at end of file diff --git a/dotnet/test/DotNetUnitTest/private/mailmanagementsso.grp.json b/dotnet/test/DotNetUnitTest/private/mailmanagementsso.grp.json new file mode 100644 index 000000000..b1ca1831f --- /dev/null +++ b/dotnet/test/DotNetUnitTest/private/mailmanagementsso.grp.json @@ -0,0 +1,25 @@ +{ +"ObjectType":"ServiceGroup", +"Name":"mailmanagementsso", +"BasePath":"mailmanagementsso", +"Mappings": +[ +{ +"Bodystyle":"Wrapped", +"Verb":"POST", +"Name":"enviarmail__post", +"Path":"enviarmail", +"VariableAlias": [], +"ServiceMethod":"gxep_enviarmail__post", +"Implementation":"MailServices\\SendMail" +} +, +{ +"Bodystyle":"Wrapped", +"Verb":"POST", +"Name":"enviarmailv1__post", +"Path":"enviarmailv1", +"VariableAlias": [], +"ServiceMethod":"gxep_enviarmailv1__post", +"Implementation":"MailServices\\SendMailSMTP_SSORest" +}]} \ No newline at end of file diff --git a/dotnet/test/DotNetUnitTest/private/mailmanagementv2.grp.json b/dotnet/test/DotNetUnitTest/private/mailmanagementv2.grp.json new file mode 100644 index 000000000..64fc85f3e --- /dev/null +++ b/dotnet/test/DotNetUnitTest/private/mailmanagementv2.grp.json @@ -0,0 +1,25 @@ +{ +"ObjectType":"ServiceGroup", +"Name":"mailmanagementV2", +"BasePath":"mailmanagementV2", +"Mappings": +[ +{ +"Bodystyle":"Wrapped", +"Verb":"POST", +"Name":"enviarmail__post", +"Path":"enviarmail", +"VariableAlias": [], +"ServiceMethod":"gxep_enviarmail__post", +"Implementation":"MailServices\\SendMail" +} +, +{ +"Bodystyle":"Wrapped", +"Verb":"POST", +"Name":"enviarmailv1__post", +"Path":"enviarmailv1", +"VariableAlias": [], +"ServiceMethod":"gxep_enviarmailv1__post", +"Implementation":"MailServices\\SendMailProxy" +}]} \ No newline at end of file From c7d684f3ba694d45d6eca8ae441a2e1d174173a7 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 24 Apr 2024 16:33:50 -0300 Subject: [PATCH 141/164] Add mapping for ini files. (#1010) --- dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs index 819ca275f..b90fd4050 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs @@ -347,6 +347,7 @@ public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHos provider.Mappings[".usdz"] = "model/vnd.pixar.usd"; provider.Mappings[".sfb"] = "model/sfb"; provider.Mappings[".gltf"] = "model/gltf+json"; + provider.Mappings[".ini"] = "text/plain"; if (GXUtil.CompressResponse()) { app.UseResponseCompression(); From 93eaf2265260b41f813f5cf127de1c9fe40b3e34 Mon Sep 17 00:00:00 2001 From: Alejandro Panizza Carve Date: Fri, 26 Apr 2024 12:59:21 -0300 Subject: [PATCH 142/164] - Fix nested url issue with API Object. 105225 (#1005) * - Fix nested url issue with API Object. 105225 * - Old case was failing tests. 105225 --- .../GxClasses.Web/Middleware/GXRouting.cs | 42 ++++++++++++++++--- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs index bd3ae4a37..d2a6f5358 100644 --- a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs +++ b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs @@ -351,19 +351,49 @@ internal string GetGxRouteValue(string path) } public bool ServiceInPath(String path, out String actualPath) { - actualPath = string.Empty; - foreach (String subPath in servicesPathUrl.Keys) + string tmppath = path.Substring(0, 1).Equals("/") ? path.Substring(1) : path; + int pos = tmppath.IndexOf("/"); + string innerPath = tmppath.Substring(pos, tmppath.Length - pos); + actualPath = FindPath( innerPath, servicesPathUrl, true); + if (String.IsNullOrEmpty(actualPath)) { - if (path.ToLower().Contains($"/{subPath.ToLower()}")) + // fallback + actualPath = FindPath(path, servicesPathUrl, false); + if (String.IsNullOrEmpty(actualPath)) + { + actualPath = String.Empty; + GXLogging.Debug(log, $"ServiceInPath path:{path} not found"); + return false; + } + else + { + return true; + } + } + else { + return true; + } + } + + private String FindPath(string innerPath, Dictionary servicesPathUrl, bool startTxt) + { + string actualPath = String.Empty; + foreach (var subPath in from String subPath in servicesPathUrl.Keys + select subPath) + { + bool match = false; + innerPath = innerPath.ToLower(); + match = (startTxt)? innerPath.StartsWith($"/{subPath.ToLower()}"): innerPath.Contains($"/{subPath.ToLower()}"); + if (match) { actualPath = subPath.ToLower(); GXLogging.Debug(log, $"ServiceInPath actualPath:{actualPath}"); - return true; + return subPath; } } - GXLogging.Debug(log, $"ServiceInPath path:{path} not found"); - return false; + return null; } + public GxRestWrapper GetController(HttpContext context, string controller, string methodName, Dictionary variableAlias) { return GetController(context, new ControllerInfo() { Name = controller, MethodName = methodName, VariableAlias = variableAlias }); From 88014da19660a7fd96b6a41003b6f2e1908040d0 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Mon, 6 May 2024 18:29:36 -0300 Subject: [PATCH 143/164] Fix error with calendar in Arabic culture. (#1011) --- .../GxClasses/Core/GXUtilsCommon.cs | 2 +- .../Culture/LanguageCmdTest.cs | 25 +++++++++++ .../DotNetCoreCmdTest.csproj | 9 ++++ .../test/DotNetCoreCmdTest/appsettings.json | 39 +++++++++++++----- .../messages.arabic.resources | Bin 0 -> 48811 bytes .../DotNetCoreCmdTest/messages.eng.resources | Bin 0 -> 40457 bytes .../DotNetCoreCmdTest/messages.spa.resources | Bin 0 -> 42994 bytes 7 files changed, 64 insertions(+), 11 deletions(-) create mode 100644 dotnet/test/DotNetCoreCmdTest/Culture/LanguageCmdTest.cs create mode 100644 dotnet/test/DotNetCoreCmdTest/messages.arabic.resources create mode 100644 dotnet/test/DotNetCoreCmdTest/messages.eng.resources create mode 100644 dotnet/test/DotNetCoreCmdTest/messages.spa.resources diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs index 21cf5a104..3106475bf 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs @@ -2715,7 +2715,7 @@ public DateTime YMDToD(int year, int month, int day) { try { - return new DateTime(fourDigitsYear, month, day, cultureInfo.Calendar); + return new DateTime(fourDigitsYear, month, day, cultureInfo.DateTimeFormat.Calendar); } catch { diff --git a/dotnet/test/DotNetCoreCmdTest/Culture/LanguageCmdTest.cs b/dotnet/test/DotNetCoreCmdTest/Culture/LanguageCmdTest.cs new file mode 100644 index 000000000..c8bbcc86a --- /dev/null +++ b/dotnet/test/DotNetCoreCmdTest/Culture/LanguageCmdTest.cs @@ -0,0 +1,25 @@ +using System; +using GeneXus.Application; +using Xunit; +namespace UnitTesting +{ + public class LanguageCmdTest + { + + [Fact] + + public void TestLangugae() + { + GxContext context = new GxContext(); + context.SetLanguage("Arabic"); + DateTime arabicDate = context.localUtil.YMDToD(2025, 4, 1); + Assert.Equal(2025, arabicDate.Year); + string msg = context.localUtil.Format(arabicDate, "99/99/99"); + Assert.Equal("01/04/25", msg); + msg = context.GetMessage("hello", ""); + Assert.Equal("مرحبا", msg); + } + + } + +} diff --git a/dotnet/test/DotNetCoreCmdTest/DotNetCoreCmdTest.csproj b/dotnet/test/DotNetCoreCmdTest/DotNetCoreCmdTest.csproj index 8b376f5fc..6a65b6f1d 100644 --- a/dotnet/test/DotNetCoreCmdTest/DotNetCoreCmdTest.csproj +++ b/dotnet/test/DotNetCoreCmdTest/DotNetCoreCmdTest.csproj @@ -33,6 +33,15 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + diff --git a/dotnet/test/DotNetCoreCmdTest/appsettings.json b/dotnet/test/DotNetCoreCmdTest/appsettings.json index 31bce50e5..a60e5e68b 100644 --- a/dotnet/test/DotNetCoreCmdTest/appsettings.json +++ b/dotnet/test/DotNetCoreCmdTest/appsettings.json @@ -51,14 +51,33 @@ "CORS_ALLOW_ORIGIN": "https://normal-website.com", "MY_CUSTOM_PTY": "DEFAULT_VALUE" }, - "languages": { - "English": { - "code": "eng", - "culture": "en-US", - "date_fmt": "MDY", - "decimal_point": ".", - "thousand_sep": ",", - "time_fmt": "12" - } - } + "languages": { + "English": { + "code": "eng", + "culture": "en-US", + "date_fmt": "MDY", + "decimal_point": ".", + "rtl": "false", + "thousand_sep": ",", + "time_fmt": "12" + }, + "Spanish": { + "code": "spa", + "culture": "es-ES", + "date_fmt": "DMY", + "decimal_point": ",", + "rtl": "false", + "thousand_sep": ".", + "time_fmt": "24" + }, + "Arabic": { + "code": "arabic", + "culture": "ar-SA", + "date_fmt": "DMY", + "decimal_point": ",", + "rtl": "true", + "thousand_sep": ".", + "time_fmt": "24" + } + } } \ No newline at end of file diff --git a/dotnet/test/DotNetCoreCmdTest/messages.arabic.resources b/dotnet/test/DotNetCoreCmdTest/messages.arabic.resources new file mode 100644 index 0000000000000000000000000000000000000000..2bd618a5a4b858bfd809e0fb182d94d0a6cdc339 GIT binary patch literal 48811 zcmc({2b@;L_5VNDf`|fwQ9%(OI!jrp(m}c)9TY?p1a|2yyNgoP(3_RSu4t6LG*Lt# zvB$Ncu|=OvEU`z8B^r$;mf!m`bMM^yJi80Y>-By8|1p<+cFvhIr=K%3_u1#4`TU{4 z7_*jV#>n}FMfo#xN8}gIo?9?6ztDdgkv~2!zo12GX5qxy1v92jXpuTUzo2mH>{;E~ z<+jp)EmFPb&M2B&kl$@q{@kL1@iSVahRvNYW9r0n^XHG6Jw1O`w+S6OjBh`&{aLL$ zwQZN*s$-`HWfz+}t7z)X{Al%&`9(*-)HMCW|AzJKqyIO1%PcyjMUzEeztm#Uzi?XsmU7hb+};E)@Z z4!UQ`@=sguT7E_S{wr=edG(5SdcM8ly{AX6Z2#%L)vYELtZ6*xtu_B1c;uCH>m7IH zpZ{9>%7-4VbJd9V>s+<0<-J!u+w$|PH?TCXd+qP>?I{4l-P204; zcHMs-zV_lH9=UeWydSPz%(H~&)wg~VX$8(Zcdck^?vTzK>RoXIzTJ$vuXcYgll&22WFe#^}_G`i)sv){O7zW_2^p2%R zF1_Oy$Gm>W3&mgGG3KOi?l|z+w|5-h^`Se{H&*&>g9ABtRr%-HcNNWgZ2h>6kFD>v z#Y#6m02Oy>QFJEic>hhumAX zy!*-HTTUL@Y3tsFUAA_3`jf4Hd%nxIt;Kh28`JCiZ4Zy$y8W));XCeq^1~g4c^~a4 zT6OZSWtFbEC+D_z_B=S?y!-3^vgO_nx3=1QesR0Kh11*boqa|7z3tCBYww=C&U+_Z z*JbZ5ySnZDyLd*XsG>y?bb|F^KfPf6rBC1V_^@YcURnA~YNiqsy_+Z@Q_$3xAl{@Wnp;Z+)>pPda$v#nO)_zO;Y*yq6xmtMHXh z8#lbt=9I7hG-z1oS07#euUCtYn*CbsGv~Y(>?wL})+JxO_S(+6>F+M@kS<-ivh=Jb zzbn1zl`emNe9P&7Iqk*I|FZMN5wBNkbL;Ef9(m&R3v2a%qvWFgZ%phm=8d+`{rin? z_Fezx2`~TjX03*!-)>uF%iHUYyXl=fc)tDV*ms}ZRQKK1ZKuBXL+&^4%^2PP{eRV& z`u=m(-+90JhkyC-gH1dCwz=|dRy1YMpzVO*6KEL;cpM9~v)Ae8Ucxu=`+MVC-%gJ~2`*Pf~v%fm(otwYfdF(A; zjXnOBuU1cd@1IvJJN4_g&P#oL!QKwv%v{&~o79H;|Mk<@{@?xd!sT1KqCq z_s;r7|GB=f=s$n^^{@Z){idJ3U-!G^KO8gh^q*GM%=>9_decwuKRw-a{&;cl;Pj)9 z`nsgbQNi&yA9ZS4rp7Cd*>UaKV=u0>?br`Ly}in!&G#I)ug0R| z?@xEE`tpZes{VA^pQ@g7-_g~ctk$IZaW4+6{>}S0*En_Q-V^WLdGpWie(J8Dz5njI zldpKQ*(qbT|E$)hi(jm@_>|hU&%b$I?b17MsQv5no~!-M&zGP2!MgiSoqW`>r%n5M z&1wI5_s^$2cl*V4UOKfy-R{T#vF_2k8=leqr55#qd4I0g^7gIugIdouIQFe-4TtRe zq2bgIJ2kq!^U}uu%v;&`@ztvvzgzjf#`VWHZ8Cbv_f58M{ISV`=YDE(-q*QJPwP6Y zX-;ZZ)5!%(oA$q~an7_xt8nCw53bHX>&?ZVcevof z2Rk->=A=&VJaJ~HkEXBa^zKu4bouSV=ex}RZE2Ua&HmP9{m`GfJpI|ht{YFT)$P0A zU)(LVx=Hu7eO~Fl^x>;}tl+td=W3qyKi$!z;k!F~)ZD%4>{qVcclJwjzdZZ)w-)AH^y~R=T=c?k zkNSC+ZIymL?y7#{j``Q4mUwpxZvo3zQ*6xdY z4EyxrHJ>dR|Mydtj^A*}+v7*K_W`;Yp8L(T<^AVQ-|^I*>8JKRFr(LjA7{LF#gjAFHvD?#uX%pMb3M-uJU8;( z#B(#xEj(ZF{DbF9p09Xn|KX%rUoTrc>%Pr@m^JgH2D3ZG{c&Fu9XI7Sb5r-fIQQQ_ygB#12hX@< z#l!bpGVjTkFZpNVg_jOH@b#tFeAj+{wMDHK+*mkhL8ou8UU2gJ*Dh$i{kjFaF5I%9 z($rxKpS)_$!bj$RxA2%+4KM3mXXIsdoB#H*%OCpPWk*kV^0KLwez>gOvz0Etf64Qg z-}vpjmmk0GtINlZIPr?~z!_I8*tp?}_x7Fht7C53_Ny;@8B?#7F%S1P=J)-Ld70mL zpKeT@KE}-FY0|)$Gus$*JkQNMb9qMa{Asu`IVT(Q*(t_UKi8O14UPHq9AhqTZ%ke0 z|2)T-Z*#$`X3TP)%WE2QTFRJ?JPWGxoIoFYqA|}^GUh#=$hStV>$QtK&W~`ktTUh7Z#>TYcIi05x&*zPdN%I`V^X?hOJOh5wnef7M z4ZJ+s)R=$qENx~?>l((~*4>!1q1A-vioVD((3pE_A=lBy)EvM%@OU1)zQ)*ke)d8? z4dCNO^m0^HW4_|^@6g3sbZ|QGui^PNbWjuCx+B|DtdVz=F*kGrXOJ;DXweGy8{< zPBP{fJjL>np~k$8o>mMuW(dz*e*X*4V?6)l8H*fEd3y591;0ARXxRNm|c^+o|d)W8r5$Fs5$>;MRp4Z@U0X$!ji#`YO z6a5zPyl|{B{aPAx@sY;#B?kVC><{yNi!Q3OPA49gGKgi~IRSlEG3E}Qxy<{4Ij_Q7 zwK~}AH1tkf{ETNX>vrThisy6u_Ye2|I3t$B+2@#Hsi( zv`<6MO31L{3}nYIPX_0C{OJ>(4fxU(@N;)le4#!zMYk8UGUm%B#=OXL56@_9w4azN zh2OsqM=qY*`Tef`!~&liFg^kO{sKMzisvnS(VU1sVDAUuzr&Hn)W+T$S-%HzwLJ=b zBFC@l;;YQxh%Vcq^M1%P3w=Dt+#Vy42^;Ev?S>e03eT1JQXWr3^f3q78YAbws~M9E z?q9O&saXc3jRj? zVHfld^4x=Me*$&_Yt~0E)p;f&UvuOgf^HUJ<9_gaNo(j350AssSMc$8eb&RiAE4v! zcm_7WZ?WU6z`q983Yz)g7enVsKG&{fOgDVB%|l;rvEHZXb2rZ};_iB$`8*53f4w*Lpb6{MBEQ1pIOJFj z@2~Tm0ADqcvpH+`hwePq`VqW8Aphy`HH`6MbaKrw;s!swzYn@c=SQ*r)zCbFvEMW2 zL-hFsa;5P1pP}a~nA;z_4QLAO;qZ%I7B z5tHzh{$`9BY{r>ZM*lk@`n5F!txRi!+Oh}R*n*XX+1AV}i`mXR$zZjJW>1sHfA27K za^_Hh$v1`k_ZgtG$_Mo_v-xkj=}E*-4AJ}WbC#LPzj@~0Ozr;PPaR=N6qy31Pc%iA z#5Po$;B|(XVNN_EV`!F{Z%${ZPrT3^GY32o84sDM@Hor#=JP}|1)}HhsnGP|lQ``S zWmb=QCOH@OB#IPV2!gaU$BXwxrUoM90nnQR2Srxu0!UmM$~pv6 zMOf|tk3RD~jhaSSMm6 z8XN+hnV3wRP6VMv5@Dtt9#2Xr-^Q0Pp>A@*EF{mji$xZ^6_ne9Oq^MkocvEAqxe)1 zNoRB6J#yk?d<cIL zLvYx*JO=yPKq)fkgDA7kHs@3K>X(N)l;DtCp2tcv%wo`PE?4HrDgXbJ_W`);T%HgS zbE8qCA~`>_d!z>iIp16ZdcsAffI8b6YZ$9& z+HCVcMJTc2p9iI8%(Kh1v&@It!;bXl4ErMFOg;&T3UG9FO9^8q)1-6qelRrG%5lsw zi4-1XROvv0Ct;QARSAYNmUPw}CY~BIt2JDfcj6#2INzbv6UAe2fnm?R_;#zTrENxU>TI1{{y;DPua{x z=)<5aV%gM7*NS9|sW=IG0rW8~ z;3aUcRGbXZ!ALcov0*rl^IVrUNv%xp8q=N~=Fh0f=moLaSX!>>daCT=bUg%o<>&*l zQh*C6ty*N`M9F(HtcWNNEOHF293d9>q7DNjC=XJs94 zRx-)AE&UjjDJHoDJ&^DjPb6m8tobp+Uc7!#)xuvg=>6CEZGM^l;YX0X z<{~7SWER9_+sVcgI!$I-!6``Dm{v#trW2(fe3<~xYbNtO}Cmg}u*S50_kCVF366eZeF zki0%KkmL-KOCokh}>q=|yzj1;r=RD3%2*V3DevO!)R80#3CG z&H>~jEfds}tm-yay+QI`oryHeE}-O`PjZ`7F||1FUkj4Aov69`o^N&l@JS{HIK@Z( zh^qpHSW}YqVPQ39ZikjCI+&__$>(D zwnHFSgo)%4(-YhC?I8J#BBV>%9=HXZ;>&J?t8!T5Yjb&1LzUA+ZUSyItjV2Akf9CU3d-0<=r}L%}P~y!4&?WpjJz2^iuNy zLtg80(JvVAdWg1rqai4=-vac-I<8vBaP;Z3|4@r5SIKs~>Y(|2HPkA0D4A5wt7Dx4 z)SUvwH!!Ykl*y8tcPHXVf>we}wW-(^U#519go``QL7=D#s3V>qwrXXSxRS}mP%|{ucBraZQNR5?Xuh(PMH6jh5>eLf@^p@; zy@y5U@iCSfyP4=hW|oWRnZ8W${!n&;S}eEe%`=6ddV@GrnL#x%%JH{Vgc2w2dqK&N zTgKEzP`oMd)KeAN`y9Vp)M62u>t}z2igzu63wer66;7HnhSizRH}x3y#I!$>>^l3A zt@2HGz&>L}+oy31`XF|LE=(q8VyiaHGQVQb>n0gUv2Jur;S*F6rR=Gdtg6La7TUx_ z?`_G6{Vf{pN=1vu`_Q*R@x?buBRlH81<{))iKq?B9QKIwZ75acXue!|V?#FwrCdsK zy8%|VnV78)XbIaWK=4Y;?Hq4b_CjUPQf>gnS5UDml#wKgk!Cxfgb@{i?#v;by=nw- zM^%3VoT08vu-H>j%{Mi;w(#+$wKEY_N+#mhI>vU1wKo%dQXL7MLbI45pF`btToNb+ z<(aDiCbTGj))C80n=a!G;4KxQDLbh$Ip5s|ny=F%85Vm}psCQ)QEq%j5+$Gqnd0{t zhn|v57Jp`%&##A`rXzfJ!6DDk^JS(qW!ZGn)Zre;yUr+hciZ^r0IfSBnrQwnh5n1;}iLeHew2`_>9$&by1~0AwF*{v@az2B(FW-Ob|Y0)x=-{RP)W(40erKxzuXS zrQ-5?O4nn=N2CGw$UbIAVNt2w5zq-hbky7NP-qHBZ5uf%0L|BpOlku_inpfOezk## zKG-uSsv(X0c==7C75y!y_zg|=l-U?majMQ!j#Y)LXWyEXMb_i>bb%m`EZbM#!UV5SO;9Fs6CTW@<*tro6zAbuJl>JXrq3|JSF;P?r_g-Fkl!!5 z3#TF+W&*%i8AotC@6Di%x7#?Wmr`9l8?a~5^@DC3S!m7yw9hBB*9+hPjMk-$qGl`P+P}L+P`?tOCIsU-@e~tmt4t$!~l4K!IkPV|h8jw;8&w zo6I9k4FcffX@YgMab&e#wmBIW_9BI_r*IzwvKP%EM+XfG3+1bCd7Hy81vv|$93Rg{}?g5I-HGsWmJMatuu8BU~jz%9H9xr&>#C z%Xv)wM4&qqd6e8hryZ)_MJ5L%9{`z1%Hl;C$oU{=a3T%fz+l2poLZgM9tY$jTEvB) zRA|)(<;+#8D>Op^C2W_pmfUy_F(oa|Fb6=)&_rz3$%vUp0y?^3mL_5pmmdmH*FccU z$f2X`BD1VKkn`JD%L6%Q_y$nIs9H%|CRu%+IlECApg_unv&}SsK0&(lrik3eu;wQ2z<RvjQ9W`@8}ZF#ZK&8FM^QJoI6a4-e0NFG?6b{c$~pdf=8tw zrKLi%1V9EMQrd=uT1;A@r=Uz$?^I6qp)a8J^qr0;Xbz*mC&T_ebQW)?P z&CcvuZaeZc!`|E?=7#6cUFMnBvPn8%6mds1Pq>x3ph@OThP+Ok9>!Un=u}TVSfN=2 ziqE?dO6=+5KvLw-G1r2aU`>6&IHS_6czFR}LPriLXOl(eo43l&b>%@W{v*J%qwQU6 ztZ~*dyMwRkh;67G=1LBl!;i6WnEQdk+FmSTHJ;uQTkcpR1rn z=DXxNlR_=JEAtuV$d(BvB4Cs^n*sD*9Rn4#V*z>oB2d0nuG+ABGRf+SUK?XY#C%hl z33O+}u7->^pJftuz*xoAa}%+w&8=(rq-%Es+ysOK&oRO*GrYXH$*!mngszcUBjQ4c zc6j5Ez#TIwp!$W&M+cgP=6VSD-DE`s)b>TNLi0PO_#JRGoVli)ChCa)1bVAOvzSDe zpXHk`4nHZ`^0+?w`@_qUhdGsxSrc8wen?&E!hv`c88Wk@iWh>c_ixAi=soA z*!{nmn7qT$wNJm$UWH~FB-$LBL{vQ736RRyWV7M$^0~dOYVso>AI2AAWM`+>m~t57 zYL_&b|K#@0PG2&~rvfQmSF&6nw#o?XXjo>NXsQBC1c}^RyIyr;tt$exF@usIy?-)` z9IsS5#oP$U@7M)WaaK>J8m8JZgOQDgMskt(4M<)bT}mmDPci4V&KP!0^Gx##h7;>X z!Ipzk2d{WgcEiut9q7L<8z+R3Rtc{i1H9Z4@mm@+@8HmnI z^Uas#(TMYRo;kj4Ig2QX$clQ-1i=dzEuv;Ji8LA{-6+8`_e;5{z_s5Hzn#em94 zA6LZvfD`&s|C7!pHVTJiA>&}3@&ZaRugBm_Edr(>%$Dp^M>qK4G?_T?zo}A;rh33)ZpxR<3 zuMZjY+(d&eb?J+^zFsClE>6dhbK>jf)~4}U{{wm(v*Uk3Z)?VONF>=P7dVTJH_baH zbe&AGgUbiBG3NtFi0zWH-Y4Y_FB>!&L1l^==5av2%T>vo4!-suO6Q$ACE`Fp_j>AB zhJ7$;c)rPF$VY+peX8m@;!z5clN6a*p!g^diuNlyQoaI!&k0F@%n_BI71;|!vz11j z-LI(_#YJV2xg8XL`klFyO18V~(T2a!6ocwZ$xIe;{lp%Iy_RP(s60?)wN+XXsEzpw zP(pUib4MjdcFvGJ21MIXnIY%!NNvo(!y~md3lERf&RlzVr1oar;gQZVj~*VWgZc3A zNFB`)T@I_KPNx0gko5h!VTVU*ZKfU`sg1e(@JMaV^&t7ICiA*Oy(lqnC?6bM>O2hC z7i}GFy0ogk#=TeiDhP@26+&F{|50{!bV#YNnrXhzTwSx1t$gLK8NA0}mrQGv1-sMU zLeqx->KzK)!E`+oxT6_xC~zl}4>*xC#F~n#8e5&XyXJNQNWS*CSGM@#3xf%bMJ=X| zf(y+Zr0(l zaufR)GrV^T=uT^;YdKQQ?g?EBob;~#0DUGE&>cBQwrPM8Y|r-9#IiqLRB0AU-2M#|J??FiYXJG2<<>8xL(nCo>*pQ=A;Y7Rrzll=WdZfN zlq$74=9U2c*`3@|W|T-ewQy%S(q4h-1)^t9Ug=aT^qQ4Tn_;7-jD?7$U;H&YT21mQ=zHVw+u<=^<4n?LMD=vLT668 z^DjWkSXXIZZD+J$)gQL-3B^%y2u>XeiHEZ}hDozyc~9=9z(qLJ-;-5Hi&5 zC}d{P7s^Msl+uq2|eL?lF(1^{ls8T^}(!osd-A4Hn z+})G=8weMGp5f3+#wr670r+$vIto4Q%9M3y1N7NeKn*I-W@o5{ASSFf8Pd93Qe8FM!OgxHge*1wb zEaJ*$bI{pLv$H(nIve3j7`9ryTb8(L@+INgr=DAexazWd0kEXEv5PPl1+6DCw; zj9yY%3MgR;fn0^$2*6hcop#9xFK1$leJ9(r8 z5FMAC55Qa1=|;Iv{#alpWY5xBj~en@%Fc3~giZuXD+abPrwz#vM!O<6^HSCm@yVt+ zC|-?XNoI@tEd7lmANd07=-IWsYSMLwEWge(<3LQvtR0T)Gxh-R9gu4oU(6o5#C*k& zcPmASROTvaouOGE-G-~3&o|8hCG@HK;aPb-U%>_79&^_eSY zbgqEBn}}NlEhm>e(Ix7;p!lqxL~-RViCSk^B8ewarCaA6e9sw+IX4~(x>uG9&dBvv z0P>-xu0U<#y39fSF&QrN81%Z6v9vviUI5XbZt`YVyeeTv8xpxebU1lYd5EqD*Xz|f zkkfSH3q)UTBZ^V89(~7P4M+)|+_I8e??BxOFd=mW)PCk}K;DTX;;uHyO|}3|C`IJ* z%{`fGDfzlBnWF0Zih*rR-4PjFCTF%ay($K_GkFyQ+ncKa`h+Ayy8zq8un(-Hf1WTh zaWN=>Oepu4!s7D)7w|4*>oCQiH6*8~iHFv-dnO&S7dTeM7au%C7M8D=Ly>+TV7 zC;+}lP3t)#gVkP0kruwBANvDgzyZrKAUu3)^?iOlMU*JUfg~5 z?*Z8;iwO5;wIcHx5_ z^G$>EvjD?bRc_iU8!!rO>bzwjfY4tCqx-oyMfCdoXh5Ni5h(UjUT4n+%V!k7ZsUGs zHevngHusl_8`NdHQaF0 z5nswC))$T1F0w2@Z9$PaZgkf2@=V#U7Jv+0#x7egdrst=&9VWJZ+6NCM80`W_A0Wm z5=Oom4Jbo%*=~C=2pJ~LblX{gGZd9{+lA!;Bez`%FpPDl;$&WPv3`A76tzkEHi!Pc zpQ2+6C>e&8muiVe0A%p3%&LCI&3hqx-ucYasrg3$G6d3h$=%D0mzpET_|>$|9Q&1F zxzXtWLN|&4a-&As_>m2p0|@Qz@MDW~0u(atK$!~f3Al>39`2h>gZVY6lHQ!&mEM`& zT)Hecdts}~Q|XQA`%0HE`anv9rHe~frgx|BOSNf~N?(;KU0%8(mENA-Rl2HlnMFu% zDP05N3T6}sO)Z7ZF@*{-2Zw9zXLUGmYb_~VQ@Y%JT+a9=C~r-bE=%tyUE(&$$m*zqX#+I_~(p0(_Huf_R zBBFUq6fLibD1{n{iHFpJNv!z)0lz_I2?E2*f}_&wOV)C|!z2ARTDP zy)%6;0^t>!wLHB6r5B?_3k!7`w3lP#q|!UE>b4Y99!RfGp$KU*g}1Cp??y4ZBa+dy z;iW63sr7glB$u<;de)Y8wI0J(rOaI;589Ewr*tvoWSNk=*e>;3H>#gX-x<`v`uBro zna83yZM*b(JLg`_+89Mc0wa|^APy}Dm?M!cDSws|C&D694IV<^ zED4!Io*meIReB%P8tQX;-=U`kN20}`zE*(^>qNyYy1k4)1+^hAez2E}B<6OPE@iD< z!2nrF{wI90#GDfM%cc$VPZSme&&l%(ReKo@QDYzvN;!wV6bTZ0;QiZ{hO zi#8#HfI?XgC%YAdv5H}K2h-}OiL~?qe!ENSmn-KD0Vs-AEg1Qrk5sL(+G!wmF-;(W zv8L!sJJxTIQJ;4M@_=HSc*qFW-Mjz}Qz@?)t;#j+R2!x)MhxmKC-}b+TrT&2D|k064ea6wP`5FoFkfZ8 z%W7(stVtp$U4!qTRF^BP`v*-jm66_vLGF`wBkR~-aE_Chxf42J%1|IHC{J<2kjCLt zv7UoUtWP+o+>teux$ok$%_ku53PPJQ5~lIU9U*Kh3MQ2mHmA3w_ea@f3u0_@?0f&p z&CLx?29fy?4(+`sc4DN6 zlM;h5-^_EkvV5ORL18mdvR%h;uWF3XKl_nm8A~b-(tBK13PzT$l*i-Uq`xhs6u`;a zf=-52$1Db_eYJQpzR7OVHEs7 zIMwFI-BDWgE~BJQY( zikRRB>c#3GafIzsdB%d}qst-0cak>0*nVxj4an6p4mPIQwu#h#cItcpcD4kkM2bn< z$|F=MXGLHeZLN?1*acSy$1tbm!q#*sn#`j3EYgJ)IEzlhL*s-bPs9rMLkSJ5qb9^L z>l+ZJLBeuq&ujY|^?BW7!MI8p}!-1r1=3Fi`Wn*E(T&&7j?sW%1=)q!{JddX`(I ziVSxu!ezRZdi(S)MRzS1`H=!cG(qZxIpJz?keseUg#(ipn^c5?ZHXbYxgxz)h;_0^ z#CcXLog%319PA#z7P*uF_3`Xo(6VXN%7)`n0p*4JrE@&pdSz#LbbW8wfrNH(=!pdg z*aRI5D7OQJVMniAs1#ZrK%yRRJs>KP)$DTGcW;uv+lGY#5L8i0k|=D%#@Xs74aA!$ zDahGm4?eh5ky25HkvzUP-pDUuWcuDEXl9vM0n0l@hzZzDjhfAIRv!rD+Vf$hE0vwK z1KUUhY8Ouq-VOWYT=5jnlnKIuPAXd&7B9CqvWGO_s~z2^oE!ZlG3Tx&&2Md=!fpqQ7yH0rL2;n%1= zLEkz{(AkActSPWu%ay=_g7@&CZq`Cj(0p64N|)pYt+7g6-Mo6lM)})0%X`L@C_b$9 zb|M6Jaa;N{yEdwzD$dfNDq<{#%^jk>pJA8xt4Hn@3Kg0oAy47}z;<9VhRsHpqjaTn zny9PUnj17i$x9R=@*aC)l1!YDF4bK_O-)?rced$@6JLZ#WYl57upY`mohA24Ol5** zR<6CJc6XfJI9Vo^+scPJgEOpBi-|5<>mBdOHnFiLWFu*VNd8y1BAHNd(1K5JFDuEv zZLe?$swjTXe}Q)r`p8HgHk}5wvxego8Jx+|_gbFOVnPs#1%;vPsfcaa!U@^^j83UY z%fV^sjdI{*3h-TvGze+>DeItaw?o!f*T#IMF$w~kOtwT`ZJJ>RWv$rlF znQCcG7$dgILPR~wYy|UTSxgWeSSAnT23?gcb)F|Dfvk0Hu;YnYBokC}aX~MObw}kw zxCu^BgNS0Ijv^->*<*Lt%X09Uq?21gifsU>Q#~0DU6{eQAFdZP1vaKebI)CE1m6dH%6}Id_dr6!^Nj8LK zr|b=7+<#aB!9*v``8V1JSmkgU1reLOv;#%q(uPCs#?P>16{BK?Ik;e!FqZKPTZw4b zssLg;lHQV-E_W)|V4>zoEjw7jo*LS&E?zkY>Q3)ibC1kxT^z3po5dJa*07BTt5sms zXb0p4>k)G)r*`)ytmMv}wWKtHKiaq|Yb*8+E_b-jEcW)8F2~2-zoc+H%KJ}eS675ZhfgIY|NYdjZDQy?t zRWCR_!;$0Oaddv~DdUTRQ;1nb44&mQMiyk^uAr-S6%7k>vVw7QeEQ<>qeMikz%|a! zzguj9$BBcQma6Z=dKA zBF2fl0{v_*T@qXf6}4AL5?%)>lZV$qq(H{yZ+A(rR8ko!EK>SN6$7Z-HK%Kkh*#!l ze{d&x(h|qk(uxwQ?|PK(_Q54-;*caH&jD-A`+{{xq9U7PBc_sb6HB{dKp4WyVqHJt ztX6FJ^4ls|AZ#}eEeMGO_BoV}lD^(D){3bS%kd-uU1Gz=+vSNqF?mHL3SVw8PCAiT%09YU zwj4y2A0r)xYT}%hOOvvT1ub$dllI!&xj1`oC2zauQaWa{gP-e&akD!Bk*3Ae{Z_AX zmN4@us}!pr2Si669M?F_8G)jetCHgyLn-vopjkq7K$S-+#=>&~Dx`@j9A-PsR@58X z^`eb97MEd@m{k(X)pLsT>sz{VKv88L`^s|=OQFk}VO6pl*a*`ncX_`JLw}W+y>QET z;WGTE?@Tpi8RgA0ZGp=nY3Yhs*N5BrT%6`c8YSw4++G9NvG8n({g~>-=F*ieZOOl+ ze)1jDNjl_1M?9n+oFhmIg!tUjmN|kW+{!xv70C9SNPZeQ6iAXyir-B&a7WqUj+{-u z1Ef;jx^?RwZV&dblDo~8-*V3HsLSnL2tz77u;gS@3Ev)%XccYob@ri)0}7j4T1P(k zntfNqS{UkBC&+Eo#%fQJg)|N|KWGtaEF)9K-n>PDW#{ zC5K&nJuCR^X;5%>v~GC?h81KsJWC4ZliLUK!hryG)!bkz9}~PJdu|}*@)PFC@=Z4Muq90nZuxwv0ciP+UWuoIWH%* ztkSWrbvbThqMQ@AJ2+ZyP#3<#z?6O>hb0Ru-Q7v{$XXGUcp2=gTyIatlK~bsn+Yqj z_g6C1VW$em)v0u%31LC5yd^RD79L+WeTU_N&31aNiLFdiNX>G_rbF*yeJ4mYal}3OcwxB!aYm9m{fovg5_nP>}U$C=MZO zpvqKUS0ytiWTLN+@vMHr{KVl;42Vpm2HEyK7BfkvAsolOpmt);jkFvT!6)b0W4WYu z;{g1x`E3zKD#ox`p9E8}pK$izUp^8i>X>yTkvKn>A0#+OXNT=#buFQN6++_wyMyu8 zbHbDwbs%tMdkVFpq;nqJRT)Sz!LiGQosy;?7<*QXCVce>ZjGqh}Qf@RemA*uD;t&0Ze(5ObrB5Wyc z>^@)@##B0&arMV%M)VHNCep@BR+vOrsp;I^sC-Ell{=oc7EgB1Anxa=DuX6P+~c!Tg}TuMP`%{3E~+JhNe|?90PQO zS==PDhI8{cAv=%K^&4)Z6t_l#-!a~^LAqJTtj=(!#R zWkT z@3QVJ6GjW@jTGCTX)kFRB&SroPA+b2=>^qnvhp=EIL(Hn>w|5M+9Kh?p0sl5YNp{M zK_iP6ZkXwgQdmNVbSqNzFW{X~iCKS0{UFy;PjW6zDdo5wqm*hzV5+uKqbyl;DSBZ) z@6Sh^tYIFCv#5L+4*f}0m@yOCvWc}%=KfQj+`tJg_JAt;Ct`QyoKUoWKlKi9c<2z# z3q4Kz!a6v$>xasAyeCqgx@w7FZJ~veovb@2h~AC{rGjqLUZwLAmGaXrw@=w043!>j zHm@IQj++)GQd_BrQLUTcMCoFSt2I8?g&RYxN7fzre?ri^uOnIm9&OPGIia`t-#WT; z{+Iqwr(K=_XG*{2@AkqNOsZgj>Aee`X}J#E|#HR+Em$d#iiLklPoS?LD`IW7AxxulGF}3pVmY^{*+k_5bb(!i0aG}WmJxjGzaiiNM z#HYI`#VI)Dss~fy#eDg5bJfaMKv%UYJS(yNhZ4VS;%G+{*%i%$WX64Dg?LqCwiWoN zCn=$kBXIgmNO(%{kt>Jc&Q!dN%s_-+TrK^HbNwvsbd^JlP{3sfnLL!w%tpmSj zv{7LL*|2Zn#8kIbdZRKVjO|bLYpvg-Q)l~9T==q?;!bVAna<_;jB6e;<%biN1uirc zSaE)5&GO^KIRUSmYBjB)h9;4TiX0~0ir@*m! zS&a)anS7(Y9G1ViTxly9!%@Wl55k16Xh|4XTTpOxBUW18t53o6L9{-%B2rwjO;ncs zXl4cC%j**=2+6x`8Ks&&K*}T{_(GoYsNbK+nz|%ioNCf?>f~9o3-Sx{3+K+vZxU|G z)ylhzl@a-~3nq`BHFd%GqN%fIrH0PYk3wfSizWTJewhYZQApm7bGZ%DWLmLX`D5zC z3O6Hc)DwqToPSt7?sDigyF|>Jz@OIlYNB zLa=}R5ofK;Fv*Gc%=pBActKE&Fo?I(#%&`Zq3h(`L9PB{Qlw5UVVq(-r|#?@1Fdqr^W8IjgN*Oeaq+4XXM0%T-sOtr zJG{JS#>g=dJ0|Wz1tna@orbVn!eHd7uExgbG?EWy^|Vx5;v6Cbhmq#0C4z54c^BxoNJYP_Hzha#FUq!lqGPHey7;AzrjBWhV{&m4R0}`otyG0_ zZ4nB|fXy`~-YYE^N4J7|kzs#us@kemFtf(iHD+sh)rT$YMUx8atUw zW7V1v4of*SV&6)h;BYMYtKMs?Z*h5H3*zC;zZCN^S8w>N=8eCLqqF&wMfb|yLqtPUdtseeg2 ztj|%XH)pnOx2~0Ob?NLfvF&9n?K1MP8>Is(&$F# zdpc{kP?twmLeB1u+D40qjfbb~l(vdJchtB<4R0>*@r3nPQA4j6En*pQj^)lBr15(~ zlk+ioEQGBjw)GVhr6eMAx$I$$rGsMbew)E6g=CFmU!rCba^gGpaf@wq1`BzYJlOdQYjlg^d$r_?G(rHm5tToT2@UT~X9HTZeUT zb323SE5`Kvxxol)jHI|4kjVV2moUiD8C{gU8rI%LNg{f;nO~Knp_tyC8=PTPRJw-w zG8qQbixIIJ1LsX%P%A>>%sr92ed^5(#@LEPf8$QBYz<3bI_LJc8P344$dQ5)({^=7 zd}S+aI8!xj}9$A@Aeb$SPeKeJLdT8jX|^eorFkBn2JH)yfD23wAe^ZQ?SB zIBmE;^^yl|{FxydqiJLkF)VpA%(fA(R_pY6G2KN!w4HHiDE?6n(+K_Y466H?(!?p2 zJFl!~*NF@$gYtwa7K3x15}zq@7DvOkT=og7lZ))@zc!W9%tR-T&|7K^FRUtdQ(|{E z!O=rgjZ^1Jw=T>1L<1Nz;YP`CB0tf{Ld zQM;gsUMZ`A+hE}^KyhCxct-CkD@d0B&ax@|5DCosD-%#W>sW(tFI~yL&nki%s>Q-? zQe?5{Gg{WBav)6$hm>qbU-TZ6NIwzEhb+IKX z?f~6RNCZf3aCS&jr(0Qg-oYz4fV7(q6*N0h2N$-~I@vQ82~ptDx@~!H2k1Dt!g`nK zE(Q6MCXSymLsc^TGb%gr%;=plBFXM*BD-j>zn@skje@V(W1zwing|SS3iamfnH8SS zhgx?RoBkd?v%QuLe6qru9Z$Gj=X4@H#~7kXmQvZ0Pic?n^r#A=*U)s3)l>S5ztEPB zucDA7%;9pjSkI)rP4a?NbY97Kn`PxS39hdCL4f;0C;2!PKIjQ5-#hm>n zkzGs$4uRMUI~kNuBtth_A#;N6&eo-CI zAQEvSY*x-h&vaVmhL?7H`9jS8SAR^xi_uyupq|B148+u-m2fbh0<>RqiJza*DS%ja znvo>oJ5(9deaKiQ{VG9QD`I@|mZr4;<&X`cRX#?K&)hTv32-)Eag*PveOjGmG`_3l z{>TE<%d}Ts0DZMN@dY96e#$@X$aP<-&r+WCB1Ln!VYNKqa$$cBM4WMw9mY~>WbYBF z^li!S!3`TRL?e=jSn4-m5H%q|FQx@NQM?oHPwF-Oq<-WV=oK4T%?5odOwh6p4jx{{ zSzg_XU&@ODLN+`n;eEybiHw4&LRFp#Ox;A{??Xh#G0F>J0LC)eZ_ep$sb$L6+V*oQ z0rjn^@bFx$hG&1-U;1!S?_41i$@bKcAkOck+l}iqq}2;Qz_GuSy#6O{@ z57%KY<*F zUubpjV>oQN;*Al=l+GyI*ca2u*N1Fm)f7shHj77UcDiH*_3=$Y3@mQ<6_I9KI<<~x z4a6<9y=_nryq=!3s(lB7R~*w<5ix|BghZ_PEd;BeM2{$y_%@@d6R-T1H3PGS!;BlA zL()B?F>I8{P~iqp4ORy`J**Pp_QN_nS!Zu}D;w?hFdZQJ9td(WDzrmP^t(&!@BT_s zdpR%cuPSAW>F27QbUBv4B8Wx9!WFmkCnbU??z4j7FhDb-of9JRi)|uYW=U*bc>lJ% zKwzQ8Ovd9hL%Sd+tSU(P*t&QBH<+4WW%Ea z$GfDT=*~BZCB<9WU9W_9P`@f-NGgF4LCIHYGB*nu#~b=u9Fdx+3Ls-Ac4i54=}$6h zY1C{_s_dV}kvHuwU9GPp`>?a0!xLQ$#yCtW8Hrc+QVro+FD2my%5C}@dzjQQAU@la zKh~C0@s|s`VrzBs(6Fx`I46l4c2@CQ)X)s7dG=y~G>g`03Ye-6woFD0{lcohBme$a zuh&CT;o>TzGRKLo-4dH|3x7Vs*)J5Y7k_K$-d9Bd9eHE@cHw(-;`>l*%V%{`ugl#t za`i``n%Lcx=-Lil3x_ANK`$ z?KIotLNcz>QPE?tI5>i<{8LbpjaL3$iasbemP}Bksm8UV$U4h*A^Jv9bsQ`DN{c9STj>6%!jYGyx&}w^Z5}y;KPnH7?4G(T2)YMB z*9>p21kdV6Vh`UHG-%3NQr>|qwc8vc*0<)^Z<)Ga-`SZz1C(%jsUURx&YU|H8i=(26O7S$qBWK8#}Gg{0Jlq}8gm~OMmZN_?&Y|uS~u3RUbM9$$mw_6_ip(W zdt-k77MAWZ?uT`EhpTB@B0<8W6jW*KETTxW5;_2{iA(mK&~is-*5)TSCfs%C?(VJ- zMyrQaBi1#ZnSrJw3gyn?pjH{}N8j|zfMBULs8h4<%_>2eUZ#R10b_TWH=Z F{{fV>3jqKC literal 0 HcmV?d00001 diff --git a/dotnet/test/DotNetCoreCmdTest/messages.eng.resources b/dotnet/test/DotNetCoreCmdTest/messages.eng.resources new file mode 100644 index 0000000000000000000000000000000000000000..71d0327a1065b27557db6b825488fdacbf9eddf7 GIT binary patch literal 40457 zcmc(I2Y8gl7WRBVLa)-BOA7=-fY7@k2@oJ5Bte?@!e)1qENph;mV|(CLBy_r6-2Nh zU~gAc>@BE(y`Wwj#oiT^YvF(2neUtZcC*0!pXYy`UmTL1bEchs&P>Rwul(?oA%xg~ z<}0cRg*_GNg`Q9#5_EY&`ny7p)9neSIVwV~K+xwcNpqa-35L7@|M+3)gZU@TkrnZU zBSFu2zb6t7I(=!5f=G$a>zeMVDGn_0_{W!w9O)eH8a`sk=%K?rgGY_-Rd=z7KkTjW zSgRL#!u7DJ5dXq|1)16WzyBv>)^pe4@;H4=uKDqS2)9POq>CyDE4?gX5*;7ws#FX-ulu# zKdv9Q_xSqWjs95w;Pb|Y+P_+EcqX&ehRr{8+2Eg)y`jdvWP@|_WgAM+&Ykzph6&|E zu4;4brB{us>2l4rWgD-V{@GpEjQZr6YuDE#T{rQ@Vb=}xG~KxW?FAcaQp+|T4eZ)@ z(+_(#W^C`aY2&qhHf=uZqfJF$Pq<-ay#<@sRh++h-?Z~@{0i*~XXh=`E*`$6#8tAT zHYc#9UdG5AVPrQ5EhadfU+m>x-Y}<-<6WaHW z&e*o|xNlp*>b2WGAF_Sh%CkP&=DlFX?RU=EetZ6%58r;}+P7~1=$5x`pO86Xdv(8& z+q=)0vHk8bJGUSE`OfVxy|ib0ivurjAN1s#+v}}ryyMx*)E&)cUAtpqubX!i`fl4% zd(QqH4<~=Kqvo&R&QUExJD(nS-p&`&H|;$1&GS3k&m4WnuH|Fz82R!ycYOKk*t_ny zbL(AmC;fTX({t{)`Z<9EIGb>^>Jn;B`_SQar zc+8O}j`uElviiDBPo~wr`&5^#kDuCgtm5f)MVp>};m${%?*8OAPrq=(zn-~e`J2yv zJ!9eH9}ZR7USYY%>vSKF*K zzqV`k%-ZMB+T1d;c2&5bcIlCV+Sl65svUCXtlII9%&NWpuEJX1J%zQ6($B8#aoyb7 zA!x~O&94>T&aZ8fyrA}{FBa6Ux$7Ubp1%LAop;GUYuCMXZf*JHC_oJcv|NGIgN3Z#~)mtY%?$~?IXG5Fp z{A^3p>kn>4`~5`YLwmP(KQv^h_wZlo#}51EOgZvfSMQPiEe{?U@WqE;e7^nOFL#VQ z@ztTT^S&OP^z7G*&$#v5Lr*RE?$FL>zx!j?!{0C2{M`3j+%NpFeD8}tJotLsA0Hci z&5sjbD)?#G*~5M=+dBE@g?j_PG&s2NmwOv;`elBzO}|{?I{fR(3pyYDWVYkzyj>%Y zRcx7X%(3m^-%iY*a{RN(Jh>#P!O_|#4UA?R8+6VdmDJFEJn77fdnaF?a$&=J z)@^9KDEY3&Uwn6ClT|zJZ~AEKRm~ngFsk`mUyN;jqRTtYr#_U_Vo!^{Et|eEt>v*J z8(Vi?v+Ilp@7>t;)|YN+d*slT_A5W`-(l|EZ99Iq`i+jOJ9O%F_Qs{1-oNSEPFKy| z-|5&t)^`4U%R`;Z8Z_>*_~@lweme9)m;E;`>iTBqk=-XWd#!uY1HI4O*{S@@32&zL zFqVGMW8jT<^fWr|@74H|7QOQy{j0b4i_v{<9J40nSNBCJ&tGy$%ArONrSx?6>pSQC zKl|Q&``>++?LX0X_R;iyUB(skOLh4Bl?B)In{r-C>f%0^q&E2Q)6~Bwex5r2-Rl0^ z3Ob}saIZ+~zIkt2F58WJ(^l@>n^yMJ-Zaned(+VHeg>`&ftA% zhllP<%bu|>?aQitX@8;pJn!wa<~wd1bkiUA4Sr-|vms@}HV$cW&5J`?EPrRn*lS+T z`1}gbh>utQFmm34Cr9;rrQPU*FAf_0)shQGA9`u)*qfKXI=1HK_s4GN|K-@*W}X=P z^7s43-QK?A_~TD38t=HI?}QE6Z%eS7ZGQJ>_F`g7K_v1s3IEt~dB zaQU=d;eONS{|d5i8iZ_c853;c`T z>iEE-i3Q&+y7c?=o!@p?-4QOX0aiXvJu=(dM9S zxX}^(;T|kRxTO%i(Po_? z#Nr-8T!hxC6YbeCeg;=|p5NBixalE|{tuXhL;X-so`wHt`jjye+ z?uZoZVXP1%M+h+#Yu(USh&5>=eWA@*YK2hkc&!ForRc$eea(t#JUV2dQ8Tdn+vfJ zd+Lk*J>OA?CxF)%`%b~QE!bZc&R5n(h-({wP7{Ubnvd~~FlP%Pe#3tJ{e<{(k`Q~) ze#e=<94N$n<3RuM7>m95F#jr?@dC{CCgz$A{O8f`MB9lyJb-hq#rd|PJ%Tm{G(3v_ z#o*&^oa;cU5V@eie$00qJZ;kpXGg2T5*7G-DcZ&0^PUMpbS?lr(G0ZF*lS_B5G6B( zcn)hHLF*45-|rA2r>79j(Yka&KgPa*v((`8D-E%JJJ2#sh;3N&DacK4oaaK!_cCZz z(O!u4Xv6bBYtZ)-^sj0qL~F>=``EXbB}6G&9@@Xqj-Wk+whv8U%s;WlRcL*1_F~ZD zQpn1?pighC{|I=q0cdj|gRi5%8}{B3d-yO}h)2<;VSL~$tdF%`1+RX@`QAfI!F+dN z-!DQgJ_pWW$iN9SqY3tiIX2YCd|5(xz=LUMYd{aMSd2!)@kBn_>efQ^YbwNR7_+^x z5b5A`1bg^LHzB5?g&_}<(H_IP+t4b}7NGTo+%&}==A*R+&r{HjjS<3$iN8Vn3i3Js zEbs^ISIE<^;OQr5VbJp78Q?qGY_!2x|9xy~$C*ML1YOJPK@KtJr

`oeFt|9J$dJ zVBA5-=q31ib0eH9TZoNlM=|~c&RBmEn0Fr8QK)gu@!XrHVv{0y-Ek28-RZ|VSkSppizJ5 z5?~Dn3h{Lh@Eh_`20r`?Yi&bY1%58Z8n>MRxdHwcU9l&e@mH+*4%+$X{~dGWKzD|L zUdOQJYxsN}zORonw#FQzFn?Q&`v7y#K;H)7zT*HbAgfcr`+1PPDzsl93ym@7Ptcjo z(2*BF>lcRzk%`X^v=i9(^BJ&jeX$<)TMb#7g7!^{5NW{ekMDz6>pRf;E6}wGbYmsx z@iz9D3c7!Z{g*?Y)`IuHV*OV@4|fCD39R|*nXqrz!>^$2)0slN0XcXQ^f*BpW8MeA zQ~vifefv%fc3b6wFEJ4eFJ`cwpjzI2KHidk)5h4kDzlpL8 z+)L1ZNwN^h*wnjnjJtiFO37A@(tN7VJIN=mI)*1#K@y|9#Db=n2}i zM04ScCqS<)4)76teh@eZvF`xnC4U6$FL={Bk2Zka z!rt0py~n|yrsy{??z+}k8*4rW*&B;J{s(k>2y?xTwgRm?X#6s>=XOW#hG{42M4C5{pjm6^$vEhpK>Hi*5ZX&xEK*!N`6A9OFm`v1Y4_u*{)u)iQ^ zdaMy>SOj^%o*Uy#kAa38Q-#=tv0q}`D}AAF%|UmJpAGzP(QZZmH`v3bk>DZPA+$!L zgcyich*phuBigfQO~Jd*@pU%74o3SX9ec(ZS74v#V(pi~n>)dmMbpuTmV%ar))=kR zEPTb89so`M0sd?Re|A951bElCKl~`<@OkiRG-z}Mc?-JU4SidOJ&p%W27reBAY+q2 z=cf3&5^~=KaqrEP1eUD=ol=92#8L6XNCYh<2#26OdQ`iOjM$?g*9iU zaO2Mf=xQI^6%-y3!k8lHJ+Uu2?2p*tpu8)$IC#r zk<3EQ#e9|6L0FP0h$*T~;^bqhFj!rM&t4GCDM}>iUdKdd*;ftAt#MmqqdITmJ zAWjtkVLV_J&*#S<3d1-cPO@e^6(VUI!Zw`Phz~Jy1jG4RF(wbwXf93y0>NRdNb;9U zZdL(R>D#}6tjz;OoHJg9&aT!*tj>JQQvsH7ryGHwg_Q^uvfGJZI5CfJ!GP}e8U1p7 zE@p9XH&AXgVsZR(I`W=6M!Bcfk!BGb*b-v9Lgk{Lo1myGeYM1_K+ZwU^+0DS94=TM zr7}T5l5+l_-CVNc2TXdj8mWjtPT%9kTL@XODZ^&gIbouixO8pSmWZE- zQ#i4oTY+TbbL?ssQm)(}`TQWzwRt+(oCTPf$S(m|8`(t2W%6`k@zJR^VaaP$Onv}* z#>oy=1gel_5&Z(5hqI>P{xBHfFlu-T?~jc5=h$as+l}u8alNK z*sWev1qx1v5MRn2fg9jbjm|4G{FimgPDVo%(z^z>0bg`i2UO zq{UMHAQy1*HH<%M(U9na33RZ_2?z=!!i*PQ8ulo2xUFmq9c7BapB^Q#y$YPGZAdwV59IKOT6Ak- zPDTfJxgVWcTa=b~>O?DV0ZH@8LZSeW_6#eI13~lJj=&II9l=08qqW&WAqgyzu=?ot z>4#`q+@cAFwT+U4o=j=6698>>)K~?`#8@}XIKx`XgSYO&3Xz~R2`lqM&+Wn#_v;6E(ppp%%yP0>-Rkv zqUDh@*Bw$UHG-b`X&`F`Ooft^$a&pj9{}1)Dw5feNgNG(zH}= zgo>y%w<+>_Et#?CIno95Xaj+y=^2YO72q&7k_RGD5(-Z~A041dQI-NpvoLl(Yo3dM zqD{BuItdJ7ky`-N!HNa+N&??!Uq2R<2^+4`xW|E{r8*X=KrTR6;DIUS?S!UIEMnBl zdpvni`;_vvK+9Q>yY4eEgs3&P@ zi(e~>sE9Ni$l7!fS+Qj*x?{+yx@W=z&IBli9ST$?!>;)N#t^^?MalutwvhIkfncQ_ zTN!auA|$E+(DpA6IuL)1l|azk$j5YHu!s_|#8y4H3`p9d5UCo;h+04qzHZvRA47B` zkZ1@+^yFFQVGM6(*)V#E=BR@Wvv(xc)VdpKje*+lai&~2OCP>ca5EuSF8MuGG6%<2 zUU6vMK}6t@86YH1;CvXQ`N@@LK|wDMK+R7ANt30RX)^%Y7!eSwEp-ocCkAMi z#tz`2LgJbD8Dr}Jb!U7F1GFjPj7;Q}R8ym9ORaj>F`%}vv!PlvYHB;cOc=vbX-i3` z*^q8Rmt>tY^fv;m z<&aShU%ZJ< zO&hzKMrm^ZDB5P)QR~7`7^tPqK5&XebBji}8A-T!G!btH6de!P=ZII) zR3K{h*b$krRU%2Qk*YN2WJ^XFJ^f@eQT=k|*($)ce*(?M8!Ct!wx1;q3SK0Bp}NJS zwLsBMom(bK5v)p)xEdfE6G=@~bh$ZxRSTeMbvpr$Ay+Jz+oMv|h<^i7>l@dOMWkD$ zN24cGX8Sb^(AJd$>LGSZG8V(M@jdl0UT~=U zB8m-LaqMa8Zd0A+JfLa0D#qSbk;5u4ZUR_ym|zC@O2Pv&(YO5Uj`(?~1dIz5>0SX? zAEg-NQklLL^(Lycu#d(kBo1J3f#rnM;MvlWF|bh?vC2YOBBOa%!62)t3@yT@gJO9h zDw4-A>HOG9DHc|-JPSjWIMTi-|FIP8Wx0bAor#@Mj89f??1d{`?J(4y?bF+%tYV;M z*WC%7WC-i{Z6O}(KU5Hg1d4wQ2CWpX921>mpNJ_00|AT7vBf3IOf<-`EP|R=X%&O= zXf-+{uD}A?12AW0G2)rn&LCz*@dKUXqFbq!R8w|3aSW^ikZ1vUA12VsSPYJm>}mp5 zEUZHKH>X0QLNd)Q6Mq9uJC)eka)A_0rQ_u)1Gmds*<%MX7LMi}l$($|`V0)wp;`Qp zKwR|h2C|M@>LT-QP+bUBV>P!p7wFoM#GQMISkPzgF~2@M9t`j0Bh52(UVkWE&Z!RKud}L08sNh>LH`&$ODPXL{e*; zY9&IWWU33vbfCt}$Sjb1nFOkk03nbyD6)X2-IEoZDn+0~){W4MF+dZP189lVfQs0; z)WsT^q9mM)M>9zBv>F4nH=Bq3gv5Gu>HJn*$AuwVB>+Z=aV?NE8(1h{BE@1c&2w11 z0kGbp3Kmt`3wsKX4uohwOQe!SXUX8dI08LOkAPCV7iks?=V-=%9)B>O>t;ShveHl9@ zDs%PlqDTv7iDVq<W5A(i|nMGWIXDXoMJwj4iv5E3WX9yF<_yE{yQwj0ZA)BEE27F zI0o4jzY|jMQgqtnM3GfdZ3{p)2H8PW8IO1|(O8-~*b#tiyt8wQVq6KGA{BkYz?-fZ zN<`UOhGV*6fJOo(h7wT}Wgmhd*AgJrIR{JcVX-w4NXhLpi9kvi-UZ0URIbE)id


Yew)m?=J z{R+@wB|!Q_)+)*~1jPmbwTP4IN(X6YX*KQzSf7bto@sJe<;G+D2EE(1{83#B>NqRX~Nnjo5`ka#wJBHAWO4g;Wf0kj<;YPghdI9hj7wL=5X zCgWBM;}AZP3V_xv?yL%Oz~r71&PiQj4p3}Ix1%WKah)7N-Prj~j-Yg`1_(C7({Pa( zw00NO1uMW2sU~A%fMZ6fbfgoy^$t0i>aIj|=@vcXr&K^ozM!XUWRE1;ZL!9F6*ohS|O5*PT*1F8(Rt0>dwW<#r zU1RnfMevKx0NDtkKrAt^3NQ%3IuqMNrZGSmXYt%xnFv<;w-CouH7IJ^WOHv;DKsRC zFhTn1CSXixO&$`9F+``wR(I^0lqhvs;1f%MKKRrt*wHD39&yp>2Pu}Tct{1=>rQ_b zH+W5BMMa=mU5_C;j7xl$D4TZzdDy8>LgiYj$y@|-^NsC&7&zg78EC)#;q8*euaI~S zQ)HZa3d^&o@(_JnnK*p<^Qpv_4*M4%pGFp<$cj$}9`~Pyxy+5q@P|5~_|yo4w4ET) zdA}SMZP6X0396fHa)~Yg+O(eH&6Jp-+JuvVGQ?y%h>vOfX3?r#%m+xvwgl00Ghm~G zqvPQto5iO_Qku94NcuRu&Z3ns7ca$jtBATnycRp9)g2p~e+4A1_f|As0kds=-v&SQ zp&gRdNd)elCnyu+fTBg4C@ied4cY5L%%OR$Rt98E4PMz&yDD)Kd*!wUNZK*-WkjX8 z7+u=paukaw5PsdNF;O6F=EfP>Vcs zip2nFF;eLc32`2}wfAH%r* zEk?Hw4t`X8C#g08otlFxOjRj?dNG}CAEUsiC)+z2Gt+ooicY;7t5cb-^#EyqX$L7i zT?m__!XL`&5b@yu4SI(B(c%Aj_MxJtht0@Zwm@;riCT`08p_1dVq0FQHNaY=6j)i{ zZixXI@@JN9R8cmYFLm8w493KO%0LHl$|ueSNIL?0)Fr@Y?m}ySF@Rc42viS$uSU1l zHFnpC8_=bdggGOfKFdS2P?VvtxCtowL`31G49n4X0H95V9YAhb4(q=71+3AuvPvv= zog76eZCE@36n!ZbyA(aTx+qfbah?OJ?d(1o%P$rC(5*>XfliueMk%oza(<2QR^G=U6LM%Q#(nzuV^hl$` zy3-?#7TZpT#2s9RQ29kD7>fsm?RCL-5o)v+zj2se6 z69Fw>v^o~Z!hbaWxEw(38Y-|IhP2A7s(LrKq%Lsze(+kL>wqy4I!mS&leYueW?a>+ zP%J0!1&X#-w06}nurBcuy0zU=-Hbu2#Tx)<(pc80g8qxPtmDDwf*R!6NLLWIBzN)_&{211NP*^4X>!~^*bi=LVR^-BQix*x@p zY~+zx)KGOGQZFdp1ft#^rBacW$cF&Zl24&K7hC%lom$|Sh;Tv{agG6?52IpXWoP(3 zBi%n@r>jJ_Q*`fV3y_r13`3Vbv~?X}DfoChFg_EU37|fU`ax0a!PY#0^tO2wr;4jV zQ4$Lv*Z7VI51M0FB1;)asgUPo0JRaJFss<+t@tsjn}3&y4*=BUR0`l0U!c>rFO~L^ zoWIn?4vRnH=U1Y}tC<>+oN7D0x>RKakv!@Jkk$j9gd@n}pbW>xoC=&Fvg{Lcw0cv{ zw=lB+(%V-cWw_h`XlbwmRAmfL8S0KCnL=V)U4WAMM*+}|j8m4H!fY4kz47bPfivv1 z^4TANpgn||MIk71P$k;-k2{nVV~mamP+wT5Cu_VlC*>#7MEH zx<7s?>#;mVg{t-<5Mn44kD$^U^7(zB>gPAyW?j^%I+DbnV1SM`5)V-KR_dRl_!8(b z0!?E~H}E3>F)XI)F)O3h{T)DUZMg_LX=mdtRK2tqu9abGUd+)-u?}+vz}kRONR~ms z!cu;70J3e2Ag1LAVe3w*RFMCSM2WZ|(Kxz+-2m7mL`_KhL!ZV{82`nolOU+;#MT4r z97a_v)yjhbwo!}=@Y<8Fd`d(ifN_(PZj=T!x~lHvd{{!mO^U6nJ2|acC1_S5wkMjL zrIQdEz19A@lhY?xnQI@fJ30Nbdc4~?z0RrCmek>f0&HU;O}X{JWePwx780a9x#~g-Pks4Wz^*DK%=l~Q=MsA60i^f@l0M?pM zFe}q4>}8P7`)A5E3QIt=otYVqiZe<9&?O=jGFHWRRf%=z(qcs|A<4KAx40u7#G7=6 z^Z3UC0J71O{zEUzHfIvhPbNrzLuu0n)0*sDNSO-LakgXL>y1 zEp%$yky%U+tj8n20I1nceWk&)5)z7mRl97TkpNM};C!0Rf*gkjMK2&~cWcdP1?$$& zCkz6TZBJ@ho}cfhMgyotBsv50nTY^tA+|uuH&INo0k#o^(|N@7*tKYURZ2#!Dmyta zLo7QvaHzQWp{mTbZUOFlO<#3IWCc9$G6J2 zi|qJSz_-~DJHBP9tI(+l!%k(2%f$5nXeo+XIsy2J0s6pN#@;zu3cXK!1fUdm3pf)1^|OnGk_e0>`0wOOwYQK8 z(P;&I#aN<1Qkss9KI>1QONLnJMd&8i7(*#W@P`p;J-ZAuWywNSkEsWtTk1({x3%dE zfF;Kkns4oM<;r~7Ix-5HgigQtQi6H!1b`&D7vdo@L0Kl3xw*Xfaaqz^GEABsKQ7xm z4o`ayfYQENliGoqm>5B2{M0#ETTzPtfU0>AwWZ0Ri@MjY0Z3|@HSrXz78WbeErrSI zo+>wkcSG@j8B)^1;-Yv!K1Q&hcNqZE?^siji}vLDN+3usSO{c0uY~Dc%f$wOW9UgX zTM@(!iGY?2+zOx+x`nnM?y-1Sj9Iw7JAq`LbSgwUX#U(NoM}9u0IO0=`OnhEj3@>* zS#Nm;0F%slpnU{FVLiRy1CV(}3lx>oka#T~Oqrqns>J>M_=(j|eADq9syotd?Y;rn zB)(cV3u>gqf`5m^Q6QLyi6YRwh~Zi=EC4mOA-YX&sBXI;HU}_fvK&y9KD1k10N-VW zMele3C6oLc06+{aqavFTKgN>HG4TLPHZ$V^mTXRqUxhrT!SINg0L4%)UTo(8A%>-~ zVp{@m4592|>q`W*#C9owrmiaz+wGdt_0@Gz7$)&2LHJKCQai2$N(?V3rCee&05SWf zWo100#@!k}?re->)%o0S7{cg`v$MPX7 z(i~xDiO=I$K6pjCafXK5Iy3N#e8OssH|%x#992$V#1nFq27(S}I2`nrM8f#!^+#ti z+F&||(-*|A9jbA7mU=_skWoL=?KT?Xub?LsGUgSRdqWOqWu?O%z-WIU>?n6uc^pm` zes5985e_(N@H>ngu7E%6bcI9dj(LHI!{zilJbt-f6A!Bv1ie*GSB=BmX2=-ye>pXF z=JVk%e~r;Iv$7Ju^vD^;uSUXZu5u4{6>^k#JoxDIID;Oyk&%f_1cNwzz~zbr(d7Vg z7^pan9vt!nt2{wRKM*1ngtgB*yVC6p%ZY*>p3)J*?_HALR6G4)9zE!(2!Ixx(8b-^^NVq%@^e*!_r2Lj=8N4BTR3l19%vVdqb;1Qo&o~*><@VLEzq#JF`Jp?Kt6tfFwjG^ur zbIjfliTeL?U)}5zSC@OCtE2#T1I8L>SYVIe?Wln2ILkanv#jz!0B0^J4}=5y)7dJ3&Ht?>;tO-^1Ki1^(`S9W>*5pW)o?<%L57fG=u$65di38%a^ zAptsNX=0Uuv|c~#Lxof%qh~D07cdpfj)UneTKfV{H>e!*+2O6=!On>5tz>5_duLf7 z5;odJdn7+3H`9%dw(hW#TMs&2OGw3blf6F3gwkNJ-&EVy=D}&|`r?p%(~Sn%&|RZh zwh};-z~(1K;HL5uW+jyz(iXX;(9?YN4Ld5FOFWKB{C+lA7AV4?Y-#EomhMxYv6N{B zJQXF_mQ6_~8tIe09!Mo|wCMz)!5`X-P^HJ^E%o9Il`zf_bL=?a_ZTg*1J!;~*4$WA zY3hMi-~~z!q{--(qfBe1Cs^SP@wda#sB5#@6+Xlpu8CC&rHIgql)6??39GrLMZeBD z(sW82h^;tmhSBIg+3E6>1OiK9EGea331re_*e#FIV6w*(HhP0)ic+zDCf!l!sq|qY zhc`UYNG^oGsDPZCoyP2w?K2##;eKF!BbD5iy7EI|TzW)Qz~&uBzOO%4VsjAVXS955R5>p(hRqY(kpel(t4$+ZD8T1n4WirsjE zl|ipRY&4y0`;a`frX=Wf8^dj+i)9M84@=c#cF-%0Qg z_qt(Fu^uc6En%;mD)ZFe&tF!^5o{cmBE0^!#SI9SIuUS8-VpS{BPlQs=GD8u%}@1>>wt2V75eAh;wxictCz zl|$*nlv2k86YcUn)ee|msi9F%Ne6~gF{;7})vz;*VYcevr5p9~1BN3%KqU*28xANu zjWw3yVACItj2cUb2F?nH5pgpeJk%V=%&1|o=wypQRJd=SywKrUD zBq^0onh8rBG%~O}!qq^etQ?*hvRxyYV+CkZPbA6pdg(^%f~fI@F2Rl)o#ABsaQYGH z3aFCW#v9$G19HspmIR$@dcyT~jTWZ$s&;zAl+UIGK~E{91R+((Xi?~KdAwC55CT%C z(JuNKEQNlS$w<8;Jf0IFsmoKT!s0+hC8ICsO&p{Yp(naqVxB+{qT+X`XtkNyq5LD3 zmC>zB1sp~b^D`Y$5`K9oY&*U{4UEP`P+*@A{5BdeSY-#d%ab%QC}HW8l51fK};v}2y{?*JQbDU znslRE0+81aqJvA}bfb~>+4V6$K8E3~kR%w*xzT<;Wn5Fuk8qase5pp;q8h)eJQ(nM zmnrEddyNk9y^6~{jFfnQ%MuJEG%|}Tjre>uMwfUzyKprtW;En9Bh?uUtqgLdF0>5l;mf0!WWt=?sNndf{mzAr0+t>#vyJqxKebvYrA^j>#RNj+XrcA3b zL>d`$*E)m?MJg);SRw?mATl^-#q-FPit&qe@pmxdF}fAQ*63i>bZk_66(qGbV}EL& zveib0l>#x=r_BaM^(3Y}w?%sCa12IA%X3?Z79EZD`KJ3qjELO8N`j51u+ip_AZ3-3fjE1xQOOQhPjSkuw+rl2HRkLNdhBf%9)oidE?kAdj zG-8j80sF>9+6>=lw!td+2@Io5d4dzoEQ7H+dsHrHv^*Q327TS6V4xaP8Xe}qsPbsc z4lDuX9vaPY2K@l^0E#E8+zGLXOOK8E^I(6+BoG!EgdrkZ#)+{hmOY9i5K^@_nV9qr zrJ@c{!Z@R0ru5cG=A{XO)K!##!|;;8fYI|AZE|I$hfX(8>Iga!R2rjALLk6^g6hlz zSqAK_6kKYAbP6TNQBXVxMqK>m&=ZY#8U{UqV3`vZLnYz#BOHRjJ2O%S9W%Z(3M~|~ zs=`tN6{O6AVgeRK9F2-c#Lx6HdlIDH3|T^sa&H;g5-x`04CJbuSf4^|(OF9MLVo6#p`Bcswl!24P`YW~ zCT#@b1z32=WJ#8O z#gL_tvS>8DsL`-E(z}3R1E#RL9B$YMCRNnSpyymv4w;{;qK>)VL`T1QgYr|2WE71+ z$!Jj`StZs+vWm-%uG!v@3yutlf*VP$vV9?I_)yF$%NHTbLsuXQcLY?}!h}r)PB7-k zmntgI1AmgGzH^KpKYoJIfQ2qPYU$!#0bd|!^vMeNA{BlqO%N`#GCCx#zIk#qT6o$L zSq3#)=Z2(WIRZdZjC$GGM!k9S z5HjWzJF+v2a~zp@Ifc1dnfXQ+DyrQm!?F)qF>rYXtHo!cNY35L`G^RX@r2SCGh1%0 zH)ZYHXi>~uR-eOYq3pgodBATpm%EnaLjqtlS9KAG92GK}<&pgkQ_WhdQKnFFRimRN zCwk>PryntMkjf$>RFxS^6Q%cR`aNx4X(1YABa>h%WAwK|3@nX&A`RxjC;fpf%Az?3 z1#mMVaS(?2q<5#&HM%7hH8tHtqlq~N{@RG@nBI)yx0y?sro>3oHy{Dj*i2mq2WUMM ztw9xL*YrU~6IeT!#|>Qx$qEzVH)Q*BnA;aP{T_s%&1_~egoG)P{W2P&oBrKsnvHY} z?h!II7|3ueb%nN+5KVi-A&R8lKcHaf*aq*%&`s{14lJS1bCLFT+R zQp&6dDv!x2D&ZTYe2z-8VfSR|00f8p+oC?C^HSpA+AV1`CT3dUHbV;;2~%|Fy0tWh zu&D}oOixhz4vP-ypbzVkM)Mq5>mu1Hc5O55cUV?$gPf(U`s7KaWK?Bw?4a|q6n+J$PK0_J;^JEUtj`pQ7XFxECJRll(#|>o39FjtD zkpYhi?2TryU1sSN*0Z_k=vC=d2M?BCZ%GkX*bZi278hE}xp8*f8998;AYxWWo)ei^ zq{6C$K!$lR2>4Q#5h2>mO;N^KXtxCCFS5A_jm|v^p-RCosCVPX3MS93=jB7zw z;9j9NvYJkkAe~0CXe9S6rg1gefSQnBo5}BKw4h;BVXQ0x4K%f-?-WnCuarGhP+_b< zDqUb!j7P;F-S}V7O_xjbq$xpXW%((rF_u;S+|mrtP1sdm<+N&C`wptsBqlYy`zQsLT=i#;tWi4EeB<1l=*{Gj~xTg`q`!MQlD0H#PVwq+o zD-H5-J76?IRwOBJbn2O}O5r#qi}p4b&}Pb92X9{F{R7faXa&|mM+hpMlbdNc^}!j@OAY*lQ`(JsM=N_+1k5LKmR*QvKUl9k?pN ztvV9l8Us#OmrX3wVYJCvDhq({y4EWaqvdS48{7c$B9H8hrre!~wzlcfQb+J*Skf$)Ub zveYBNW`zQFfeA4J>DlT|oEezRK#VqV_hQ^l8`$=8ShwiS3q~p`+TK%iv3mfXN0z}% zW7z@r4ius(^PANYstE#fj8Y{G_2f#L7J`hPF+&pL3_g{^m6b~v4OIJJj$~;j-RP%g zg@wXCJ36pyaOVZ5cv2XJ}jaQ#8E8UOXiAo%d{{Q>ljXqE~ zcpB>sTZzXPp#2X>0~~_cro^Qi=|wdmToBnS)3lb@s=f})3@fi#Oh3%KIC+O=&p$#& zqkOyzlgV>S7(pa5G~&{O84YJ52w+;>Xvlb_h(`UHDbtM}ri_PFt+2UiZp(n>;iwK2h11BH7ElTEXU2l*G54xf(}q-RPv# z!)W?PD~co$DWyHA0wvVFu+dw2ojC1<-FCQAo0pJTve-G)2H!z`p4sZxq*TyXtIJ^U~civK;v&JAoCg{otwE$4-F0E2GE!p2J#d3zFW%c?HnmM%l}jwoG285= zk!`P&nT*<(WsL@RNC=o^i7hCfB$x$1tm;7aE(^x?P1(wlP(wKZqG-M!G|x`6ucZLN z12ly1Zi!%<2h;Px0P8*wvFK=vz-HbVok``urha2|e+whzcUIyC3~vz->BE|;I||!U zC?%^G6ZZANYJEG3Jw|WmxfMEm7JMOXF=taIL%nEF{vU_M>{8quMOlSoO%Zey6y}eW z<(tX5GmLKXk%Jxpg_Ck>+1$3)No>X|-58~7c>#Ij=Qdy6;OP;Jha?!Rfh|lnA4$N= z{!b&LXY7Xc8G*)B7jsZhlAh1#Ebm~(XIal+9npkV*PgAsPQEj>g3XDB$_uzxRdwVG z51H@uR=$}5CesiVwOL8Ne!-D$hSG_=BOfWnyTw!CCvu}n49CY9?M=sz;K&vl*_0)4yjna3igw7S zLed_#C0@4ZV2y_NOzAF|$jUbWP~O;|ZAgR=d+XOp&A^d71kYv$5H?AXI3d(+7$$`@ zDXnk>RJTV$-6fh$m*e1yWH8?T5ZpUW(~LkEg^M8rGX@TI^b1#{8co%muvB`ZNtV;+ zil7pWoVgLcM_lI&;+cM+vc{;Nh3Z=pfgfosgIQ@aTF>#6I3P`u%Kh--D%EI={5$B7`EwV!Yeb@m4PmwAMHTL8 zc%Ok+;j(ODlYc49XChd&LRVQO0~6q?;8<`cPQj9|HW=}#1Qfwa7gHnky}~eguMn!l zgJzj#>O9MQk8b44_ne)gkHVqMF~Rz2Y_J(sSV}9^&6uZNs3i46E{}I&ynLx~nAS~K z@sqOnBNc{K%(t%FnEq=L*E?^VQI8kvviMhT!g+=TIP2v=C@ zL`_f!p{XZ>8=5td*y0E(C1EFZ5l>jLfUL_jN+}KmP$XlA6sCqLa}blU!Vy(LMMYB) MH3^fjLto(k00U93m;e9( literal 0 HcmV?d00001 diff --git a/dotnet/test/DotNetCoreCmdTest/messages.spa.resources b/dotnet/test/DotNetCoreCmdTest/messages.spa.resources new file mode 100644 index 0000000000000000000000000000000000000000..be1420bb741efa7c36b4338ce1ac2eaf1c8a53b7 GIT binary patch literal 42994 zcmc(|cYM@E{y#o%q=hOVy)6iVKnT4zLlPhmLLhVtY_dzTu-T1UsKSAqo>;*ODkv&V z#CoEKr>N1OQml9C*~NY;dJ1Rf`+Uy4XWsAKBygWUevjXAV>a`8&CF|FeO@yQM_)Sr zlqH1Nh!!kd9*z0SGN${Z;drFjA2pw*`@KGYB;8XMEe=P5fueNJEPo^#2!}=w%IL>G z>7J~3Fcy#aM~D3JSi~Dl_Y}m7f`Q`6{^c{mi~XU|MMH;r2Nw?>(tr5CLH>TjhM!w? zv3MvJDD&&p3;nTLAWHrRKMOLm`Tt%Yh&8R#d#pL}TKbw_ZohENTQiQYx${V~wNH-j zvUcMAL)Jd|?bx-Ohs|I2%bvixMmNXS?YQldb$wQ@S~n^GrgeD_mR|Nv{|7Ex-F3p{ zx3pS+`Nx?bUH-|7g?}0R&ExC)6-Ta2&HLcWUnZS(RlG~XtN!(2+pC^B(BbOopLV$V z&wU=g`cR+a*X-z@du^Y$*I)a`C+n~M*KK>QZF%^UYkLkDeBG8`4_vpP*3;LmS@!#N zYtb%6t7zMD!#_XB+A!-5--ebGqZ>wNuiJ3pi&tz&YjWF$UTD41($V^$WuVP@{NW8v z?tF8@!h_#!7CYEJC|@ z?msq;DeZrK^P8@`e$?{zH{MjT>Bh+)?YVK-2T$L$VR@aK$KF2Z=05(0n~uD3{-)(= zC7Vu!_iei4_`yvBc68jl>89?RZ#(b3&4pi$xpj4|^KZMZ?9$r~PrCH>FVU{?w%ao4 ziosioii@^X=7hIgKJBh8_icTDOU5lHw)C#GZtJ?U)@{A0-n(00x%b4@IW13a-T&-Q zTN{mf>W;T=u6yUX`_r~H`0>1L*L{hxQg^WJZFZ@H(% zJzLT4K>PObynA;29K5Gs?Pd3T)_=!6tIvDyp1_~;w%cHB2&*N&6_xp&74FC5&_*u3l5zbkgNnmT;GSKo+zMH@!$+x)=jeJ_8Nxo`ib zkN5S6`XBr6oQ;qDk(cuLf+NpAe#_|ZAOHHtA^ZRKm&yD8x~6o0gQZvP|M;e3`;TA$ z&=b9GedvjI4^=+#$%s$?{&Tm&Czsy5`N{Oke?HYd>;0$poh&Ekw95XSr&W%AY+B{^J<}_L zd#6{{&zM!&<>on+{n6^aKCe=IJ+HDs-SaEI|NQ*Qb$c$X^!K=^a_;(zDzAI};>wKO zw^p{Xn!NDHi;G`eare>}Z>cDFsrglJzf^z4)I%qG1`d68Fm%ZG=#z)XUj4@5mEV1M zczBOaN7C|dIP(4M8;-oW;G-ieip9}o!)qOFcBIzPCx5Je^o!J#qs>O99NlrtxvxA| z-0juu3AesF0qrg8l~>>Xs`$0Pd6&KR%(mzo!?)k_#`c4s|6@Sw6aUC781c_%F8l94 z@2wqvvu)q=eL>gUgZT7-YXtC=e>bPetGZY<2Sy4_UotK zZ_{n|M*|z|`e;kTTRz^3_S319V~2KhI@W(+;FI4oPJR-cJ>k>;b_jfWr0K_>_Wt~x z&p+F7{};K9Qoh_d^wgKfW=;8Oc%5gyTGZmMua7--{x`>VJ@d`4`yTyv@omq3yT$k1 z@s)?3KmPD5=Y03K;WvIa_JxA)2hAGvpOUTP|1l+8cPYqa@?^~In3 zxcblSPJA%ab7Jnkp(o3>j5+DK=h6S3nm6I+Q@_vo`IEzoe%?R&+F$PP8vFIeXzbT7 zuD|}*-*%k(ZOapv{a&xQ|+T*6e(+;p5HLGxFISe0pq4tJUxKYCY$^bJ~2f_SH6P zTeodHYtyo}Z{KlK+v{f@X?ya*%i4Xm<&kzJwNu(JI&o$D?~nbf{gK-jba<`Z&`x6- zz1*qJL)|*>YFpZQ%xmdgtY!b|(&zTwU9C1p&Q1BCNw@sRfA1Ffe0cZUN32Wz(f60s ziuLPLkJW!9wX3&hkJ*?0*5khIfAm;!F`i@L8* ztNqT0X@89UEN$LDm-f1+pmq8f->URZw;f8)WxM@Q`s!VW(o3E?lnYE_rvKOdmm2E>32B&lYxiRv-1w8f3f6n`tNA}nfpe1^$Qxf7@Yyx~A@8p}K6LK+PY&z(Qp@2VKi_xwmy0hSe(Z&! zbma0o-yXTK*B2x2o_cEJi{Bm|wY^oF(Leuv!D!F=9%D9UzcFUrfosNIj&?QLHE4IA z+B&w|vHQn1e`v>fZ(R5Id9TI)bKdQjb>iqHZF4{1D-obk(ytRGU#D_P|o>-9ekBKi$@0@$t6B}}Kf7+3| zY}g06!+x7KX(ZY=TT3SW5Lr2CU##ckIp43H+~)1qCg1h)8IkYs0iPYag3-aQj=+cK-0zv<}VNO;2swsj#aj zQh3+j{4+bgoj$wm#c$2d7<~Vn{I&z;-aLKP-2E>!o>zJ6`SYf2ST%3hl@HE)>zuR; zK1xfw;F^VL7i2F^yWrMn+6C7yfA4}3{6yfgph_q!}O zeq;86Sx-+{u=|qP3+A35TJUoFzJzFFF$b3f_5s8zwfMH?Uca8c*=UoEO1Ke_0#3Gu~yU-;|db~*clza?-0-ju zi^^+V+WX?^Tc%%Jh&BUlCfaPYjkkLuA9S7?`KIB-=(zVjj(TE$k9|7-yI8~08{(cv zUyc9r`}^@vp6tBj@&gYpS$6RCB|oOFTw1XI#L{bj9=yECntm&8j^?cx{?j!pT77!m zivIU)SnW1HTdaO-QgHQ(?f0zyRziG$HhHiR9nikPy0_rxIas$&Drguf#K<8+48>Z39zsk<8;RBptufk3;B-Z^ zu+|r#>l4s%1nrN$m^TgUfwpbEg?I%t^g0jw#oYVQ8c)DpCJS-2tq}9-00;Y-44fZ9 z{|WSs1KqDq6yk;fLUbQ5#NCaBC%xNV@XIrdl5T!@=$gSN3k zc=ACQW8T}#1@hR+UC-&L~Ja`rJz0g^RkGf*-=L)d|>HH}C zJ{Rq3$obG1AvzU+pJ;W^MuXN_8A2?aDnupL{t_(%GX9eXGQb?~V$QGHp&w(P!(Jw$ z@1=S|q_h;`)^s7FfL{Z>`2nA=#C%7+o>qvd0c=y^iii1l8Byne(U-$6S8TK9nV7oi(p0p|oK%t;OF1+gjkO@ z7p))Ge;Y(C=`6%U;B9FwA)dyZpJWPg!9?iv1oWZJ$GC@}r`O=;o%OM=Y$0w(JAv_M z;b*;Z&{4F@FfNETfa5{aXU*}spAb{f0)(V;1<+3;P4?pJ;#UBE+T8kHwI|I;^t`Z7Sp$ z!WwtC5MnU!_jM4W2ln?9)_fc7QuH6h9J#Qav%srgu;y0$?#Jh|u)mg=<0#}^5Az>u zFT`%lpNIaNfPaq%ynwz=fb1`X{;fcJ7W&l~^F9r`Sp++I0la>(zYu5R_v1Y=7uvxA zLcEy@JAi(z#N3n7_T%?{z|FwtOsw@ic>N9d*#!2n8a#QU1!#u+zrY?!p-<}}`wFao z6g=_OhHYcbEs)(UprHc1t;iJOAJBuV!IPusz!os?L$!qbU&U1D7}{>=)um|Tz>{mS zx0}J+%}udC(Apnu2yA*dX!tAEUEL7+*&Ox>+V9SS41qfb{p;&u9sbOK4MQ)o8e>lI zZUt;$IOu!`V-`c63&F3)A-A6azilFH12Wl%pPxXs!?E`}(B7T|-v=58fwuN&Q_zm) z!{*RNqJ4>04|EKg27iDxzC!bWx7VWofkyDx;7wDsV(ju1_!aa(mXP&6;Cu$UqtKb@ zu*+tU!AIwUkC1a5G+cpJ+D(Y@kfk5+7WjN%3hW#EUk%>P!u*r4&%@B;_E_gV=*SC@ z%MbV*!n_{P@doxj66-~v3#~EkS?u?6toJ$gnTvInK^Ak-Zb93JHVyplLVu6BI>HW8 zU=!US^JU;|N67Io_OPdk5CcKmX6VIe?E7)Z`A5+G3Ff;J@@b0xS0KNen+Z{lHLrl~ zjRlP#f^Uyut~b!uqIGHjeC%x`cw2Hd_6qzPFi(0t#Lt0LFt(QZMzuMYGf2eA<{D1dCv!T!EQ+X>o#LCXMLS=i?VSi3#u{etVZ6QXbu#$x`p z=+A8m9!&?YnuG4~;6M1@73=T8oDX1c>7Z{3czUuvelLX20L_iDr@w)RC261?W533@ z%{|~Rp^wMG@43ML4s8ee_k)HlLm@-7&(RtUgFT?lLR*P;C))F9O(DCl@N+JH4njMg zf#0#;wV?B2ti1^`y&rP%O-3JDFSH40jnO(z!%yt#QSkIa$fpGS+5>*phU`v)#!k?~ z3dpKHc(jqS1z%Uf&TasWnczuZ@Gu=Z)(rlrDSobo-hYMlazT47>~C=!=zb=64BH!k zz3;})+p*@?n9~A(H$cBLJHn_!uYdT zWWwr;ZS-vX42b~#>l625=$QX~=yW+nOhhoeSj6NMXM?paT7x1evJ$&OV!6mgSGKcI zxhMx7C-GvM0B8(}EPO5&rI>UgK1IP9KmM>kh@W08N{VM-qCuyhs1S$|q+tAS4q61$ zN5onTOh5g=nV`xiDdI{GVnDt#fXmOtOmR_&=KMAr147uu48X{rGW_J)GvrpX@Ef7r zT1*_pls%m(<5-1zr$nMaAY01~KYj(Wi)9))7xR^af|z7e1XC=vnUjyHVi5Hb{2l<) zyrM|5u2wBLGWV)6NgB!067bhRLms9q0ai$)ViK38aD9sEf0?8Zl#nBHF-5O4(J=$7 z#U$Bbpu^`YJIj2nT zM_`ULl$e+WM2a;mwga_mb*NKe98}AhSScu82HK`-_pFuj|Iht?3+hHxw+T($Y_O4* z?6>8v`9Om#5f>m(8GE9Vke^f!$}0p$O~FqF2rrQR;tHUv2>(0ow66TGA*FKxq6EJT~s_jA$LW-SG)ei%W zYbHTe2hu&!jA-F=3Q3?@!qMuMIoq}_O;YT(=L>w<| zKsgTv=CtaN+-g9iOduJ*t7h_x+2}MT;P!fs30zbYinF)HKxw1*=FFmYupB^R(*!O7 z^>oE<1D%3hEk<7f6h~>Ua+^_cIfjpN<__EbQzseYFj-gz1D%8=2d9TIfr%X1K&A^& z2E|ol(oX2SOOP8agR}eu16+)vjrc`JB(N?iyw)keDk#l)~|Y$J@x=zD$G z7EuNP!Az_@*I0C#{pA45i5`p%Wf)11rQ$&@;FN0&f7GH;Sxqp>E+-%;h72=VdFj|4 z;gGCLv35Vr+Z?Q>5<_hgY6bdCDxJy$z2YtmGS=h_a#BS#EK_d&AdtuC6~<#03cd)O zQ8{>ZS#Pqh`wCMS|H>(X(nq(zfypp)JZ2@8?a*ngMOlfzO19zwl97`}q5_cjOe>}U z!N}T;z!Y6=VGdA?HER^IK&yoAW87yPqHDpa1;fs9*uhAqtoS7WjMq_P6(AF1eQ@JU zYpD;fS6x^kQnFQ3=J8UbW#SVI%cySQ>W49PKaL?uTu>`bHyio|C?;aLsdi8_0d;T= zH|a_Bs9dx$&=TlWoQr_7OmnH+$@bj_LySIh=Bh(xNQ+=(J{QPF025&(MRH!B=na7J z61kXzX9ga~;5elwCm+rRV}OZ4i37;fg^~~&qO#mD(2Zs$qUXpE%&lz#lHq3}(nNq` zAY=-dL``_1=J{y8>WK0SkcA(y0NJ=MA}g`fZJ5MX)jbsvur)vl;!vOx znRcZCn7{y?ii`rl_(J+?CW3ixY~{r1K%$}$0OS9rzy^}HaXt`?Z1XW)3?iaNEOu27 z76HjvDv_4rFrpSvjIVm^-iaY56R2(oRkY?)=3^M%Nc%8GiFeR3$lX!BrB)^60}M2A zk2B>WSO)Qvikk_&DwdyVl1_kY)~L!LB5=!05UM}GO~W7~Pp*^)rCTm%$MFI{BToX! zlVzCcdH{?wA|TOPs%~fx1{jeh4&bJu;$ZTOiFJUgGk$;p#uaf!9^{o))1v50b-k-O zN}^5NVpuA=qsxejdYz6A!v}pLos9`OZ9f2wnK+?tB)Uz=m?|;J>||{n2Q=g4ree1- zgv*8UsK?4v1niy&6l1gnAU!#+qQ}-1z&`=m%oMDE)+)h2Ka(o{K8yUJw2TXOzsE>hQHmWpYq1+2;SGCOl0>!Y5DGj>= zGUH}c)aQpfOCtbBu*XT zaUut**_1-1%xH!>iY%%L#R(0|fReCpN}dN>(nc#~))o_&1I?U%xtK;%`T1smjUEyl zMT^O6m4t4dG?t6Mx+mj#k9%h=i?Z^IrvWxTSsw=vq0?Br>QpxMdLlNXPe^=-PQx3w z)j7QR3Mj?}x>2fD;V4xurd-yq7-+Q3J#d0V^NIGjG^uuR=Um+vC?>qS=SViuOduNZ zxDj~(E6164xiqCYH7)4~`r?{qqT1!ky_G?1mjcZQnhP?C&Vjg<;%!Y{sA_HKL7wUY94ZD-lfcXjIF^zkz7%jcX?&GDXe|6r!87mts!ZCF|BsK}dV2ats-uz3AzOxIM|07-pRB>4)*YLS6q*ZP>Oa z?xrf4YBz_0X7p+XXje50T`l|qU?X9InXfAi56g4A4x2wF&qE_%m{+Xpj7v$gl^I}{ zI=C}iuBmXsVhWv4R1C%70?j@(c&7AZ%v00>R~;%@@uGWIxgCq6%oJjFfMT`4QOP1q zIxlfjs)eq7XJM#PNBS2PKbC=7Rxha0nV^hnTvPe*R!naKhN9U$y*p_-1k~)RlrTs# zxevKAHkNZ}AWR9A{FvM66WK9Lbb)&!o(Px-Xf`L-il{RzSJ3X9g0h-cSrv0^r??yy zjd9& z$4-YvgXF2TL|g?l6I2ps%LS5iGEUa3H!#o`d*VQ*w$3qvdJ~mf{|!S-YL+}CoRo~W z#Rb1Pb5}*?RUd7D#W@=F2%sBBl8CNSP^M&B9de`sQ@SM>W?cVFY`AIIbH2!jRKyAcd0%&CJL`Y{JQ^4X9@f*;LX;p_t z%~bb`-S7@0VMZS6NXs~Ig$#&-tr3w8G!ve5a;gl08d)_%pM?R2p&UR@qy~f&=Ti4% z6pGStF76x%Dbtl0V4~Sv&=VCmqstsu)$Ljgx>W?A!;D*jWW>O8KhH(1{n9<7m=CZa zQ6-D&6dM)q0%Q^)`p+V1Byl+dD{hO$XFxF-A}3^~6%;4YZE`H`n)|0WgYLBn3x4h49=&Wy*|-L9rTWE|Mr;jmC2GdiTm4M_)mOj))uFBNIVX=z9S+ zgt=EdlsqM~8)i%)`N%D43{$TX@om*H7h_A*>V0U=oZ(1ZITF zf%9-X42XtfiHJ;i^ieIVW;8}StqfCuW{i&MTZx#9F2n0$tVmoYk-YSXiIo5w{MKv1CUEVZV*kzFRrX^EL~kxJPeRac5Z1=jmu$EQx&R3=#1lfJVj1b!CI}v-BFT0BrU|F!$A8{83%^0MQX|C97Z$ z6a%X39wa7K*F9J)sIGg6h@jiWD@6%qa}59qJ0OYlwkqE51lYxX*1~m(`elHOqH}Y~ zb{ysU3J= zs!pmXyrU{0hD`*;>i`(rB4taU2dZAKG__dN$E!%!*4-$|c-qvApf2FL){LNRtS=B; zjHlxwGwAKcR0T0*WZp0vAQ$bbtj9g57)Ebd3=|hL$)$2*p-TaDiGVh(Lix=A7%sCY zMi;Rht16Fr5MZOas+7V^?1RKn%J(m{4Zc`DE=?Gvjw8Qgl%bH5sqS)Qmp)M!4{Ke7 zXrQ*Zo&X!QVivSe6rjuSMDbxhCZaP|rJks`1SrPuY7|G)=VPC={BrRZAi79nUNB!U zG}B&o0_Y-50jX@1=yLHu)v+paP{sca;CcFZ=Ll=Ql+1i7d>-*xozfYaswq<`Xs(PE zwLDd*b1XRvKo@n%$KFW*yJVq5ygU( z?*qutr$K(nT&7{~Cr-;30z4SgB9;rQi)-UNpwdC87~&NT0CY{PfDVhh18i(rkEPUf z;dcZOTr{ikL&V_9Ng6`;JjiQOsFdLWF_GS{PtppSp^u{~9TqP2~;_oYjr zQLzgXWSnUN=7f6ksHnscb3E4FiEC1$)MY_XyaV)pr(eO1P9^kyZ?@yhU8Rgdl`3wr=AS;${#*i~;1P@dt_(LO9 z!o3TFjB_E=dB+?RkD@!ld{j5ZR4kqX&}DYC37(^w-~CV%Xn^?D4dR2E5TXX1bE)WX zt}7uXh~b`D9-|_o6(8F4Iz5sy-(nz{?eGqap`lc4P3%@_c$wIhIHm4ROy~~*$#@~1 z!k59<>(Ac;!9+3LNd(f)9h8Vh-CU|o6joyxyWGVj9=v%M*B8j&K00x_o=mb!e-8(V155O*d@ys(m zd9r2T7G;J46F^3d)ESA4Sc+~Fa@oz!HRyD)O?A$fK~PuSt^}?B z3}m%PB>)8g8J;adcaX_&awoZV5ju?oRc@=!5$e^n-#tcwqhhnWlZiH+*F)$u)aXv- zy8Z@`39@dGveWtSInM2Ne{uZ(f<8dZ?D2n?eV{lDbmL^TFHjQ0Yv!IVZYUQ^kFBH7 zT7Zox6j*uS4b=k%h}!^gaYgxTzSf1+CWA`A2TCd^UIoa|$cVZa_&o5?+n<%@G7|#T zUK%J$>G;#jf*J5A}ZaOg>J*;GIY{S#3Z-Y)&v?L zZUxA-caBrFnY#dR?cD+Bb1%j4{F#vkh<}_JX`ncMW~4#lk250;7WI3bk?1fNzNtqZ2=J1yTNuFlc!J)9Q5Kp`yp>z{5np(}9PJkpR2whHEqCs>3I%3-oQ1fn-9HdToX%giaU7bOy@W zb5ty>4ya>MI1$L(0w@2t1V9sb%0LcNS`}4Qk(?x{TVK8*ybS2(EL0sj>#SPHn}O_d zuIef&QIhun#ds@vyQOfj#i9b;#_y=LzCiMH z@`T#GewjR>GBTydwfiLPPIc?6$8G>8>`omDRe^3|GEmu!s!?7Jpb;pyu7Etfv9`jr z@&TYEaEB-=iFpSgV|N_QyL#vQ()BZ3mrDfG9C+Ktmj?RVs6H_pXbH2BQ(Pp9s9h{p zR|P8y6!-yv6Ud|WsOKvm0AzfYT0e>mfw!6}-K*O-iEr-8%$Q^#A8#>IGohXdpeYto zJt;D3UnHU<3WTIvhuSY0J9mD3oAdv z&&+ghNSv-5-Cj|NPLm)hrFjosMp^V7hBole-N59N;I9Chy{IpX>Q`R%`?<*G{hcb; zMnsE509AyKk78mp0EUd@l;=tSjT0eIjkj={hGBVo6+7uG5Gm!TM4;iS0n!KzB0R{&@-X$52njz7H-cUVK z;;s%SFQp%!QB`Pa{Cm+7IFyW_jyII^&pat7yl@yJE zo*-g6V-`zW1CStMnjTMO^t${@%#63?BJ8A}P4-YjfasDMDxvV#ytiT5VVRf=u*=d2 zrbDLwUJj6pFoJwA-D2@j)hU$;@~@I85?@s}j$xqn-~OSST?0J}KG1$bA=r$I&HxvGq`5J|en;dI4q{`%sXywrDGSM4A zm-2IERT+z721cuSKuDsTF?or-_BB-}XIxeWU03hEWLp(CNZvE)YzJiy+V9F+3)|N4N2xifIf8P6{3sO@_Iqrg7;@LG6Rnfnc^q7U*)xc>oxd zQM{q=qdrE&#N<(|^)Mk{RdtlgBpBNc)C?RTege?78J>#N$fa11lb487Krw72Nfeut zXLTO#vV4MBnO12plXPBMQ?GrZ7Z6>0<_SmT85aOxG9Z;QUYy*uL|l(9qgJ#MvW$fI z#NK2Ouiu%@`^94bx%kQWq27LQ+)Dr&4Nz{~edzFsFRLQB^G}~h8IeGgJ9F&~kl`$; zrP2CP<8qEJ&jbQ<1KSUeu+7bn(8m)L2qbeQ@;LN(B}%f8hisvMl}xml3o@QBC+q6xQp zMxCtdFE!)?$wiY|miy(b~pKs5~3uRxZf)5wdREE)5hQ!LiF z@pbw3Za4lC;5$BKmm6Pu>L<}@7{gBGic7@%02nQDJe?x=2LSu=Mz;`Of5?Kts;AI= z%2Wc{CW8t3tAB)04nEOhw7ow)C?BBi=#XJrPFR)jmTiQut zwE^q>5u{}}1GA94ra-cHIuWXkuL)psvaMY*pa1}>Y1d@H3~-b6 zmUIAYeVGE@$DtJZz5YOe>^*9bqoq+XHW^Hvq5aZ-`NgEBjw)%K_AfLd*9k2SWgSnT#|%GR4#MPZu6uaEGrTcmY#2TFoqsijysM%Kod;Juz=l(Cb;*Z&ilX(uL#d9-kBCZ~o$dpQD4}sAq{c7>@X( zo=J)i;oUVCov(Zzu#S>8~wKWIo^oF4`=Jmpfmq%28%5hd&OTpTCo9cgM} zo%x`bkn%$B68v|GKN46N;FxHfLV^*H#oSxW9|`$mR!_YcX7~H3$DAIT;wKR>y<+^k zUgUw*QDZ8lj|3uAk(tx;Mo6Oyy1`0T{~waw3#%yxMZLi#Ai4~eihpS=>Tp=@1|qOJ zXv(<7(2{`KVwpb_^)B*T4ReD266|GRI2N`V*}u%<{;hg>fwFR-TXnPiP?iV`F&tVL zh)}|<@KO2!xnPI}AZ@NE`vV~;D7jNqu|Ep#``~^OjF4*46qt}t3~Ng-Xmxhc87_*! z^F$!0g<-6xTvWd^AV|{=7t?<25zSm9ioFr~y!KVPNNAwUTjCETuu9<*SYELWrsTES zx`#@RXroP-)s~1>qYSH)Yn<}iwDyuX!UBXAwpxu31Q980cLOQe4(Xh6hJEEw<{mKc z9vN1h@&4jcuhnoIy_}Yt{fm;D0@>Er3x3P5%*}R0A+0(Qzho8sNVu$=&Y<732eSQ9 zzn4BJLakQ81u-HF*F%XW`lPYe&>R>GLlSw<0hqiv9DvWl?@$UFQ#k??t(Wbm-=H~t8R`oM{9VtzX-vkRL2<^V#@uIvOpA`j3Fn% zQIilm07=gS4m13au<|%~i#T8h2(NYSOi(3bM7TH}iNH5_yo@hY6p!Y27ZpWxWU!rc zLTu=v1PoVAGpG_fJmbB^{-SVrF=XcrM#EO^f`C6NV;OvJDT4!9w_FG549~L%Jk$OD zvhtu8o*aR7td%m|9}1Th(Fz+lAj^lCRUQfZ;)}wbxZVu*K>r5&glN@f>~#>dXT|++ z7%(}l-(aGKdi)$%u^WT2C>R-v`(BM41a3JHe{eSYQT?nxv0`sg1RmZRmX|0^x7Z}bK5s^YnUR2W zx(%ilE%Fz~@EI%hkoIAxEb)*R^e>dwM%}|SODeVnp$QpQ26WcHgqEk2g8rOZ;m2I@ z7=3+%EEOn6G{E+(e!wrQ*d0SEqI8185Fru8q#8oMpjP3ch#%noG|~1lrb`a$s2&KZ z^}|+or7X&OQ(=_1q_HRqZ_t3-K~$7#SXQwuN_W{%{%)H|GyWoTLYYz!-bTX_ycoU9 zBYwDgLL{rGKCjhGpN&s4@Vib8czv$ zTx*O}CJO42FnJJ&VqQuYzr(Y|kzaWuNGNP~WD-H!%Qne}l6#pd$o$LdI?=lvwuD?I zq2HCUWLUNG!&bliK&XUxt}M}x$;PqDJPPSEvyKdFjFP9i<~MPk?DMK&6%ZRBTgD=HOuG5+-VguWoDFCt*Mi( zluWn)2BVNwM|qdpQz1)huuVWTj@Tgy_LTX{kmcgo6QI?}6Od$e7zU|Ae};8-fr=4e zZwRLyDDb)Y75mHl2()l-{)G@ppjf(qguv7b4yXv3c_19~7fabNGjiosF4nYgGEL4A z@k`q(i1-)cGxPSSb@p_`ydqEy<@R|ok<|)4{&IE1LiB?7#%T;ep@XX*8X=Lv3$M%I(u4NCb|eccC0m-9%73Q9ac)A z7qI|mJHJ)8P-dA{L;2HoLiKU9@P_<|NKNguQLaxObh0~W9>^iNKP3OoIiYzWB%o63 zh^HhHU@SP>9+N9mG0xJ`VENtF-rCh23zSPcFY}gr4H_FsKWT&(5$~DO72^W+(6~X$ZG2uSZ9sVx{q_(3UcJ5FP?lnH9lY zpdwM6IuOK`Gb1ebMx#rSwVL4}C;$$G@D5?CukBIXrwcoRqofjvAp6+0RXCmgIUF1smc_6?TK`X zDfnllu{u1Kl?sXx!ko|nQrvN8#?n9xjycg}!0;>?VXO(pQKeI=GRA;mKyX5kJ;muW zYS4isG=bgVlpg9NIqlty0V7fAD3i_<0a_mPR5>bSuP@6=I`Sbi#%@*VNhVm#^QD^5 z8+zr55$dP6+{@0-!9$h6NxnOgfTGm64SC!Mhr&3XAfHJ{SzO$twVypB;tfS{*p;rE zJ#BJbXHiTV^vqNWhp?8+6f0Gqq_j7c#uVl$PwP7BG-DHvh8lnvh{v6(OI%!H!WpX!Xohl}-#_0_TQ_ z!k#i#C|7tE#z8;l#V$(1R_3z@@DHj7;dN;s^7x6m7aR&y94<5xM`8(lD0PJgMDgX5jb?d_Q&W}J%1AkKr#8We&RDzVU71u?+N zv&T&-H%DlL;y#Ut!LnQ9c^N~H5BrWh3OV0GmIlwN$E9#A6w^YlHih9b;5m+Qi_LU8l~ z3t3XYa?Hh?gHoRv{$ebK%`S{9&EgRI97U~!c>JESFv-Fxai~H+4GIpmp)g%Ak7VV@ ziDWh>55lU5fU(p)C;{_ga2rX#%-HN0iB;MsQl3b03i4Q4zlHNm)n!Giekv5V9H(K_ z+2v^;l8`aPRGw5fc7*NP(S_m!3rix1HCBByS8M4PY_Eiu$&w1ol>Vrm zD=S|IO()roNJ)q7%o9R|*edo@$4p&@D6mqb9F%9HDe9AF^ytxJta`THSS?)X7to8t zsQy^zW`%?CGH4Q|13ub!5B=R$jng1O?kXT;aC3RI5t++Gk%4H@o6X@oZZ1?L8Y;d} z88QHcYPwiESlG473@bHD)h(s(u343RU#lbtyu$1`qv?u^{RiB>1-t`1HJf{acm#r9v-XXOCi52ZWWq37j@ zssTrqqdJ~;msX1eurwE3>?Cxm2#N!vN=57=CEc-9R~{|xlAvb>uM(qHTjL}&dxIVb z4~mHLkS&qq=xL>9`fxpo^FKpgL~AUUN#MNI5*nh*4$cLPJl7;>9b*Kdv!j?9R!TMx z?o1q6Oq0f|2n4DfPSR!VA|WA%B7naZf~g!4@t^`HnVp1Xb)TM;KiDP?LqycKt$VE1 z*i5uAfb-@6`&X(d4bO3d%9oM@&L$+i*1&`@9vljg^SEwW;Z2JjKFgS$VKqTyD8_A! zs`f{%`YMq`?$mI0II`G-vxPs1nwE(y^yF6S8eF{9z{I$S)jT_ZYM%;IjI25KB+8Jb#ghSt={)&gZR;oFi;4rK(KzEgMoz<(*4<$idM$}!w^h^d( zoM!{&fpA~cdW~s7<5IIxH3%$3s4>?1`016Gq7f^F?vn zfuj);LK(+n2xGSYLy@A6OiWOjP&p`7l_rsNpI=99pf$Y_vq+h3b}j4*db;L!MQTC- zL#!*=>zkN3)nt|#9#%t>3{KL}C6Pmj7O11kBpCTCy$S9Q$NORO_|Vqne9Wr^ddUo{ zg-X51N&70qAF|rX>nvrMI+ef{)FhJY|6kDRLomvx*jiJ!b~+`)avLCU{Jm! z5<1MVi%6ORuu7ggS=hH)*pDSNeNo1+raB))_K%BccY^4oY|f|lnY?R{;oQt*!`!xb zFOFC2)iOrOOhYIrACw{*pq3*84dHr)+V5XRKT`1sHD71OxF0~3LMH!uVym%jd|(l& zZKCSyxO7y+*0X=NnweA%Nek~cq898nz>FKNj>$bJQC5aNcta&vnST_=S(&tL8IM}% zgsi$bTq$6-#r*LiRY+@c^aX60fJn1b>W&6(={NtCd^< zIVu`}lNr|V|HD8hKa)f2Pl!}(LqR!gbwQqsqqFUw<+4dRiPfdXz^db=)u9TCj4CRf z`(M^*o@JN!WDbpkFob>%N~~c>Ulnh)!-PwXDu#nt9BAValviosb}U69G1b1Y?>yZf zjR$$DW$!CFqNSwTz9nL{g`ZCX;~51DhgO>$6u?oo#MTqf>w>5jwd^j5bWMFzW?aV<#C9l?#y5euEZMTGX0AEvhRPe zeIL|EVOLcngl%dP)o{5icECU2`qVCtQG%w>!E%J7U`lOp#AWu&o2s~s7m!E*0hfg^ zm9+R+WeIuIH9j0&K&}GW*-Lnk9@vi^5CD?rr~RuEj`1?O=u@#9IZuYQ$tuK+BdRp^ zvCEJv9bNK#@LbGQ8S?RXC7SM$E)ehj=u5ruJ7v7a^z`TxC<);;ACjVYnO`|PUfk-s zjbjorE0|i&9}EpaQ=&q>+`0Ho3e#3&I|8aZT`Q&QbRC&nFb|9HR@a=Bx>}ua+vXgZ zkSZ0y=5+duRjqz@hAOGS^D<9v)H6OF45oX^@ZgVuxGWI!z!gQp!C;ZMc(K)Fia!*` zj%1SN4O(@kcq1$D{$UF4Cgp1)`dtLsvrwUOLXXzNltO(&iF%_gA}g({zQtpFfEF-y zcg4kE#a>Xs>Y&vc)c`-jr~T@Wv_Nqt%;7aMKU!TTx=>}N zoMniseCwfeQAXkxGgZ{(6DlY-YHGN~OFoGtoIf;EY`?{Gj0);bc^d^xb(*Z7Iwc(S zGI&<=G%O{xFbOvV8)TkR~)F$A`~qvN3Mf$P4p*E>I}XB zO-NK!SKS`G9LDe|`hf&L-~@t_C424XZOyd}lpzcvv+;qMDLNmFSRI`N0@Uzrn=9$S zF(RK2U}V1AfFI$;cyx3rrhZ(>93&cwjjE7OS|?FrMb(-j>BizD2|$dIWUQPK%Vpk|JLlVDn{wmtNj= zwU1&dAWrnCkcp+v@+`h;;xH9Yc&#UMK5j)G;OwLiwIdr*nT+&Ly5z~HZ=8c=M|nh2 zC3RUhhJjgK0oPYSHQ|gpL%O5NedYd`$%!D5@#NmuDrRby)S@@)q zr0V@goisOj%kqMXxK3QHv1X8AP091x{@RXaO2y#kWpSAfy-Gw1g?Th5Yf!-OW}tAc z0vYJ!`ysFW%GVbj!Mg??zHs{H2=my1cbtxBWnxerwLFWCu^+$?`*R^mHfhZ4URPG_F+F=TQxHZS=5T_evR?byw@^ymM(s{EEDQTg=BEw7U zQc_cObPUDuI4eS5RBtM3z1U|8%5KztLV*!4IhRc!% zp5{-rE9MF0TJ_m23pLG|66&&{eW%qh%c(V3DFx=HgRhP4loXrN8lV)|wr{)w!i3i3 z>_7>_m^_u?AP>8dK@CKzR36MX4|t?wfip<=sEZ)pppZCK4$p8!&-%G|jUiog6Z;ci zrZ53-h%=)vu4=w;aLU=leV{&qi+#Scu(~{Z0GT23HgLyz)gk$$FCJ2%jl~fV&P*75 zv{Px`_rPE2QavS@T*mT@W1wxRjkBY_?pCrM?ZLZ9F)R4msZ8BmPU)`Ep*?` zqacZ6$i_jBagaCCWLWhhGAtbARI!)Sg8xnp13`p^6x2oZO@MMU`mAMjN`@p=*!2Tf zeSImfFc?K4G5h%1A7X{JN-qNM^nLEee; zEb9cAf3znb&she6ukcm!eJ=8R_0H8*4Karo~G5Pk%s;^&=SUBgaJ6d>v z7%mqp9zyDaypPw&xT0)<%nFH3;)#DaU8x67g$d(w`It=Sj5ttX30$n(7xIZpgy%GB zsI8DvZJ3=Pmx*F1+#Qlfoa(($Z#?FfwH0phG;`8byEQO_7r161{8Yu>VrD<2goX9; zI9}87OGR{-8P+gKkZZ*0meMMOuR0;}xd!nmLA76Y!VRKaz?2Z}E&COTIF)5sJ*V>P z1*$q_4oy5cQwI}>?W^Vr@>P?xXb3HiPzy|ZUiWDdr!kZ(aA3rP1u`*dvNm!uw;`)J za3`jC;#7H|q%|f7e0u3%Mnm56XlXd+;TITUwrtG8biAC~>Z!gnM5@e=39P#1&dyUW zVnfmiCl|bA8&@4W5;dYh9xn_c^uMU@<9yB2zo#&3`bc9Eo`UK5BXxE@J~z+mh?`$C z$_X$!w6t+;TC+#(ZPY}seewsr2;zQy$?qyk*Hp95um+xSbTvG1%GR~vn!YSAW3jOl)D>Ha>PKXk+IvCf^vuI9t%DgUl57&OCneRb&>t4 z=h-l1=Sw11hpIrbSr$C;og)S15cQId+cDWyhNE!w&=MEV?)ZSmk7Hi730ykdSrAf? zN{&k<8`CNmWiiw7NAjdK#2_U#7`DJtU3jF9EZcaO_J8^Byw8Ff`P{_V%gby6BfN#JeH?G zT*0f~3lgtvo2g#+b!{Wn#c~kJMENQQb&8Ta1u>U{=YtlSw>wo`iR*qe;vDi^B?{Mb zpvHx`z`=CtV#_+m`TDMBslUk66Hk!wj>x|6lrNHG#-?8>At1pdWCW8hWiwRW&9SAZ zl7O_OsXQlmm9*6X1^JNuT@~u4e1gmqr^%3E)17!KQcg-=Lk{9KBwQ8azjZcJHamf~ zzs+Xl%P&))h>1jm?mYP@b%vZq!DtudEa))>ngWz}P7$CojU=WggyX)C3t z`oakE-MaE>U<8sv<=jS~#19=GVKv}OHT#KW3O?IPS|4xO5DHMDHy1lLJ*kKj4fwo? z`3#&F;L0@W!8B578_jVflgU}coR5HIf45HGedC3ktyA?=3+xNPx~Xb^^;0WuRrdn* z3-H}GUN+*+Tv;4wWOWg*A92XmyKj)H0vENUQL38-&D_6vRAny}-#=E*L2;z*YG$U5l# Ef3Zjmc>n+a literal 0 HcmV?d00001 From 4e993e0564a5a9e8c1d569dc379724343318099e Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 7 May 2024 07:05:01 -0300 Subject: [PATCH 144/164] Bump Microsoft.Identity.Client from 4.56.0 to 4.59.1 (#1006) * Bump Microsoft.Identity.Client from 4.56.0 to 4.59.1 * Add redirect for System.Diagnostics.DiagnosticSource required for mysql connector Issue:108272 --- dotnet/src/dotnetcore/GxMail/GxMail.csproj | 2 +- .../src/dotnetframework/GxClasses/Core/gxconfig.cs | 12 +++++++++++- dotnet/src/dotnetframework/GxMail/GxMail.csproj | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/dotnet/src/dotnetcore/GxMail/GxMail.csproj b/dotnet/src/dotnetcore/GxMail/GxMail.csproj index b9210f368..688b7724e 100644 --- a/dotnet/src/dotnetcore/GxMail/GxMail.csproj +++ b/dotnet/src/dotnetcore/GxMail/GxMail.csproj @@ -70,7 +70,7 @@ - + diff --git a/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs b/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs index 5dadc513c..48dc0151d 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs @@ -505,6 +505,7 @@ private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEven }; static string GeoTypesAssembly = "Microsoft.SqlServer.Types"; + static string DiagnosticSourceAssembly = "System.Diagnostics.DiagnosticSource"; [SecurityCritical] private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { @@ -518,7 +519,16 @@ private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEven { return SQLGeographyWrapper.GeoAssembly; } - else return null; + else if (requestedAssembly.Name == DiagnosticSourceAssembly) + { + //MySQLConnector requirement + string fileName = Path.Combine(FileUtil.GetStartupDirectory(), $"{DiagnosticSourceAssembly}.dll"); + if (File.Exists(fileName)) + { + return Assembly.LoadFrom(fileName); + } + } + return null; } #endif static object syncRoot = new Object(); diff --git a/dotnet/src/dotnetframework/GxMail/GxMail.csproj b/dotnet/src/dotnetframework/GxMail/GxMail.csproj index fc8df79cd..fa8a83e9a 100644 --- a/dotnet/src/dotnetframework/GxMail/GxMail.csproj +++ b/dotnet/src/dotnetframework/GxMail/GxMail.csproj @@ -11,7 +11,7 @@ - + From 00f416fed7ee6535d542a05d951f3ea15892caf4 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 7 May 2024 09:43:10 -0300 Subject: [PATCH 145/164] Update Npgsql Version 3.2.7 to 8.0.2 (#980) * Update Npgsql Version=3.2.7 to 8.0.2 * Disable infinity conversions for datetime https://www.npgsql.org/efcore/release-notes/6.0.html?tabs=annotations --- dotnet/src/dotnetcore/GxClasses/GxClasses.csproj | 4 ++-- .../src/dotnetframework/GxClasses/Data/GXDataPostgreSQL.cs | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj index be360c140..883469816 100644 --- a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj +++ b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj @@ -161,7 +161,7 @@ - + @@ -169,7 +169,7 @@ - + diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataPostgreSQL.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataPostgreSQL.cs index d61eedaf5..f89acc4dd 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataPostgreSQL.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataPostgreSQL.cs @@ -587,6 +587,9 @@ public override string ConcatOp(int pos) sealed internal class PostgresqlConnectionWrapper : GxAbstractConnectionWrapper { static readonly IGXLogger log = GXLoggerFactory.GetLogger(); +#if NETCORE + const string INFINITY_CONVERSIONS = "Npgsql.DisableDateTimeInfinityConversions"; +#endif public PostgresqlConnectionWrapper() { _connection = (IDbConnection)ClassLoader.CreateInstance(GxPostgreSql.NpgsqlAssembly, "Npgsql.NpgsqlConnection"); @@ -597,6 +600,9 @@ public PostgresqlConnectionWrapper(String connectionString, GxConnectionCache co try { _connection = (IDbConnection)ClassLoader.CreateInstance(GxPostgreSql.NpgsqlAssembly, "Npgsql.NpgsqlConnection", new object[] { connectionString }); +#if NETCORE + AppContext.SetSwitch(INFINITY_CONVERSIONS, true); +#endif m_isolationLevel = isolationLevel; m_connectionCache = connCache; } From 8e048f1dab270133e452d8661037d7e92bc89823 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Fri, 10 May 2024 11:15:56 -0300 Subject: [PATCH 146/164] Updated Npgsql to a newer minor version due to a security vulnerability. (#1016) --- dotnet/src/dotnetcore/GxClasses/GxClasses.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj index 883469816..e7c0b5573 100644 --- a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj +++ b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj @@ -169,7 +169,7 @@ - + From 3e3074baac6990ce3ee121a7850145b5089021b4 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 15 May 2024 20:00:14 -0300 Subject: [PATCH 147/164] Upgrade libraries for Azure.Identity and OpenTelemetry. (#1013) * Bump Azure.Identity from 1.10.4 to 1.11.0 Bump OpenTelemetry.Instrumentation.AspNetCore from 1.7.0 to 1.8.1 Bump OpenTelemetry.Instrumentation.Http from 1.7.0 to 1.8.1 * Fix unit test for package version compatibility: Update Microsoft.Identity.Client from Version="4.56.0" to version 4.60.3 --- dotnet/src/dotnetcore/GxMail/GxMail.csproj | 2 +- .../src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj | 3 ++- .../Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj | 2 +- .../Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj | 2 +- .../Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj | 2 +- .../OpenTelemetry/OpenTelemetry/GeneXus.OpenTelemetry.csproj | 4 ++-- .../GeneXus.OpenTelemetry.Azure.AppInsights.csproj | 2 +- 7 files changed, 9 insertions(+), 8 deletions(-) diff --git a/dotnet/src/dotnetcore/GxMail/GxMail.csproj b/dotnet/src/dotnetcore/GxMail/GxMail.csproj index 688b7724e..f8899a0f6 100644 --- a/dotnet/src/dotnetcore/GxMail/GxMail.csproj +++ b/dotnet/src/dotnetcore/GxMail/GxMail.csproj @@ -70,7 +70,7 @@ - + diff --git a/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj b/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj index 172d64c86..522adb9f8 100644 --- a/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj +++ b/dotnet/src/dotnetcore/GxNetCoreStartup/GxNetCoreStartup.csproj @@ -14,10 +14,11 @@ + - + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj index 47d2c6a5e..5aebdae39 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/GXAzureEventGrid.csproj @@ -8,7 +8,7 @@ - + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj index e9956e29f..7ae7307f7 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj @@ -8,7 +8,7 @@ - + diff --git a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj index 251919cc3..049e25bef 100644 --- a/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj +++ b/dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj @@ -8,7 +8,7 @@ - + diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/GeneXus.OpenTelemetry.csproj b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/GeneXus.OpenTelemetry.csproj index 171a608cd..64f9fc9ee 100644 --- a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/GeneXus.OpenTelemetry.csproj +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetry/GeneXus.OpenTelemetry.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/GeneXus.OpenTelemetry.Azure.AppInsights.csproj b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/GeneXus.OpenTelemetry.Azure.AppInsights.csproj index 6fcea0822..b627b6bd5 100644 --- a/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/GeneXus.OpenTelemetry.Azure.AppInsights.csproj +++ b/dotnet/src/dotnetcore/Providers/OpenTelemetry/OpenTelemetryAzureMonitor/GeneXus.OpenTelemetry.Azure.AppInsights.csproj @@ -11,7 +11,7 @@ - + From 1dd2844a01037ee03532ba7d54f59fee89e2edac Mon Sep 17 00:00:00 2001 From: sgrampone <30872877+sgrampone@users.noreply.github.com> Date: Fri, 17 May 2024 13:15:44 -0300 Subject: [PATCH 148/164] Bump bouncy castle to version 2.3.1 (#1026) Delete HC128 test previous to delete because of library malfunction. Fix deprecated Algorithm method. --- .../GeneXusCryptographyNetCore.csproj | 2 +- .../dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj | 2 +- .../GeneXusXmlSignatureNetCore.csproj | 2 +- .../SecurityAPICommonsNetCore.csproj | 2 +- .../GeneXusCryptography/GeneXusCryptography.csproj | 2 +- .../dotnet/dotnetframework/GeneXusJWT/GeneXusJWT.csproj | 2 +- .../GeneXusXmlSignature/GeneXusXmlSignature.csproj | 2 +- .../dotnetframework/SecurityAPICommons/Commons/PublicKey.cs | 4 ++-- .../SecurityAPICommons/SecurityAPICommons.csproj | 2 +- .../Cryptography/Symmetric/TestStreamEncryption.cs | 4 ++-- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusCryptographyNetCore/GeneXusCryptographyNetCore.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusCryptographyNetCore/GeneXusCryptographyNetCore.csproj index b3d135f44..174ed6a9a 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusCryptographyNetCore/GeneXusCryptographyNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusCryptographyNetCore/GeneXusCryptographyNetCore.csproj @@ -68,7 +68,7 @@ - + diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj index 299927dd2..7e72598d0 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj @@ -33,7 +33,7 @@ - + diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusXmlSignatureNetCore/GeneXusXmlSignatureNetCore.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusXmlSignatureNetCore/GeneXusXmlSignatureNetCore.csproj index 7d3b069e0..666954743 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusXmlSignatureNetCore/GeneXusXmlSignatureNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusXmlSignatureNetCore/GeneXusXmlSignatureNetCore.csproj @@ -26,7 +26,7 @@ - + diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/SecurityAPICommonsNetCore/SecurityAPICommonsNetCore.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/SecurityAPICommonsNetCore/SecurityAPICommonsNetCore.csproj index 64daf268f..98801732c 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/SecurityAPICommonsNetCore/SecurityAPICommonsNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/SecurityAPICommonsNetCore/SecurityAPICommonsNetCore.csproj @@ -34,7 +34,7 @@ - + diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/GeneXusCryptography.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/GeneXusCryptography.csproj index e5f90a379..1d9a763cc 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/GeneXusCryptography.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/GeneXusCryptography.csproj @@ -7,7 +7,7 @@ GeneXus.SecurityApi.Cryptography - + diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusJWT/GeneXusJWT.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusJWT/GeneXusJWT.csproj index 8d481a451..2cac667b1 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusJWT/GeneXusJWT.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusJWT/GeneXusJWT.csproj @@ -16,7 +16,7 @@ - + diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusXmlSignature/GeneXusXmlSignature.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusXmlSignature/GeneXusXmlSignature.csproj index 80c197f05..ea8ad6834 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusXmlSignature/GeneXusXmlSignature.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusXmlSignature/GeneXusXmlSignature.csproj @@ -7,7 +7,7 @@ GeneXus.SecurityApi.XmlSignature - + diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/Commons/PublicKey.cs b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/Commons/PublicKey.cs index ff4018494..5360256c3 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/Commons/PublicKey.cs +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/Commons/PublicKey.cs @@ -189,7 +189,7 @@ public void setAlgorithm() { return; } - string alg = this.subjectPublicKeyInfo.AlgorithmID.Algorithm.Id; + string alg = this.subjectPublicKeyInfo.Algorithm.Algorithm.Id; switch (alg) { case "1.2.840.113549.1.1.1": @@ -236,7 +236,7 @@ public AsymmetricAlgorithm getAsymmetricAlgorithm() #if !NETCORE ECPublicKeyParameters pubkeyparms = (ECPublicKeyParameters)this.getAsymmetricKeyParameter(); - AlgorithmIdentifier algid = this.subjectPublicKeyInfo.AlgorithmID; + AlgorithmIdentifier algid = this.subjectPublicKeyInfo.Algorithm; string oid = ((DerObjectIdentifier)algid.Parameters).Id; ECParameters ecparams = new ECParameters(); ecparams.Curve = ECCurve.CreateFromOid(new Oid(oid)); diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/SecurityAPICommons.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/SecurityAPICommons.csproj index 3b984fcf5..8d6925609 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/SecurityAPICommons.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/SecurityAPICommons.csproj @@ -7,7 +7,7 @@ - + diff --git a/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Cryptography/Symmetric/TestStreamEncryption.cs b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Cryptography/Symmetric/TestStreamEncryption.cs index e90e28551..de1ade552 100644 --- a/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Cryptography/Symmetric/TestStreamEncryption.cs +++ b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Cryptography/Symmetric/TestStreamEncryption.cs @@ -70,12 +70,12 @@ public void TestRC4() testBulkAlgorithms("RC4", key1024, ""); } - [Test] + /* [Test] public void TestHC128() { // HC128 key 128 bits, no nonce testBulkAlgorithms("HC128", key128, IV128); - } + }*/ [Test] public void TestHC256() From 0e676c0e30c0dbe21744d27f8731ad7684150c6d Mon Sep 17 00:00:00 2001 From: Alejandro Panizza Carve Date: Mon, 20 May 2024 10:02:52 -0300 Subject: [PATCH 149/164] - Fix error with previous commit #1005 issue 105225 parsing service uri (#1012) --- .../src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs index d2a6f5358..5851c9081 100644 --- a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs +++ b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs @@ -351,10 +351,14 @@ internal string GetGxRouteValue(string path) } public bool ServiceInPath(String path, out String actualPath) { + actualPath = null; string tmppath = path.Substring(0, 1).Equals("/") ? path.Substring(1) : path; int pos = tmppath.IndexOf("/"); - string innerPath = tmppath.Substring(pos, tmppath.Length - pos); - actualPath = FindPath( innerPath, servicesPathUrl, true); + if (pos > 0) + { + string innerPath = tmppath.Substring(pos, tmppath.Length - pos); + actualPath = FindPath(innerPath, servicesPathUrl, true); + } if (String.IsNullOrEmpty(actualPath)) { // fallback From 0e1e7f95770f64eaa59ab9dec4aa75d08e08f130 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 21 May 2024 09:38:42 -0300 Subject: [PATCH 150/164] Update Microsoft.Identity* from 6.34.0 to 6.35.0 (#1029) * Update Microsoft.Identity* from 6.34.0 to 6.35.0 to solve dependency conflicts with Microsoft.IdentityModel.Logging * Fix test to check the right version for conditional packages. --- dotnet/src/dotnetcommon/GxEncrypt/GxEncrypt.csproj | 6 +++++- dotnet/src/dotnetcore/GxClasses/GxClasses.csproj | 4 ++-- .../GeneXusJWTNetCore/GeneXusJWTNetCore.csproj | 8 ++++---- .../DotNetCoreChunkedTest.csproj | 2 +- .../DotNetCoreOpenTelemetryTest.csproj | 2 +- .../test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj | 2 +- .../DotNetCoreWebUnitTest.csproj | 2 +- .../ProjectHealthTest/PackageVersionsConsistency.cs | 11 ++++++++++- 8 files changed, 25 insertions(+), 12 deletions(-) diff --git a/dotnet/src/dotnetcommon/GxEncrypt/GxEncrypt.csproj b/dotnet/src/dotnetcommon/GxEncrypt/GxEncrypt.csproj index f4518c1e4..080986242 100644 --- a/dotnet/src/dotnetcommon/GxEncrypt/GxEncrypt.csproj +++ b/dotnet/src/dotnetcommon/GxEncrypt/GxEncrypt.csproj @@ -6,7 +6,11 @@ Encrypt64 Decrypt64 GeneXus.Encrypt - + + + + + \ No newline at end of file diff --git a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj index e7c0b5573..b2165e979 100644 --- a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj +++ b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj @@ -173,9 +173,9 @@ - + - + diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj index 7e72598d0..96047c388 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/GeneXusJWTNetCore/GeneXusJWTNetCore.csproj @@ -34,11 +34,11 @@ - - - + + + - + diff --git a/dotnet/test/DotNetCoreChunkedTest/DotNetCoreChunkedTest.csproj b/dotnet/test/DotNetCoreChunkedTest/DotNetCoreChunkedTest.csproj index 09b55c7b9..4a09f0df6 100644 --- a/dotnet/test/DotNetCoreChunkedTest/DotNetCoreChunkedTest.csproj +++ b/dotnet/test/DotNetCoreChunkedTest/DotNetCoreChunkedTest.csproj @@ -19,7 +19,7 @@ - + diff --git a/dotnet/test/DotNetCoreOpenTelemetryTest/DotNetCoreOpenTelemetryTest.csproj b/dotnet/test/DotNetCoreOpenTelemetryTest/DotNetCoreOpenTelemetryTest.csproj index 6b8ae9e00..6a7ec8719 100644 --- a/dotnet/test/DotNetCoreOpenTelemetryTest/DotNetCoreOpenTelemetryTest.csproj +++ b/dotnet/test/DotNetCoreOpenTelemetryTest/DotNetCoreOpenTelemetryTest.csproj @@ -17,7 +17,7 @@ - + diff --git a/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj b/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj index 1bf70900a..942399345 100644 --- a/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj +++ b/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj @@ -62,7 +62,7 @@ - + diff --git a/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj b/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj index 9e1a026c4..5da562bb5 100644 --- a/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj +++ b/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj @@ -19,7 +19,7 @@ - + diff --git a/dotnet/test/ProjectHealthTest/PackageVersionsConsistency.cs b/dotnet/test/ProjectHealthTest/PackageVersionsConsistency.cs index bce4ec15e..7b450fb6e 100644 --- a/dotnet/test/ProjectHealthTest/PackageVersionsConsistency.cs +++ b/dotnet/test/ProjectHealthTest/PackageVersionsConsistency.cs @@ -101,12 +101,21 @@ private void TestPackageVersionConsistencyAcrossProjects(string targetFramework, XmlAttribute condition = packageNode.ParentNode.Attributes["Condition"]; if (condition != null) { if (targetFramework == NET8 && condition.Value.Contains($"=='{NET_FRAMEWORK}'", StringComparison.OrdinalIgnoreCase)) + { continue; + } + else if (targetFramework == NET8 && condition.Value.Contains($"!='{NET8}'", StringComparison.OrdinalIgnoreCase)) + { + continue; + } else if (targetFramework == NET_FRAMEWORK && condition.Value.Contains($"=='{NET8}'", StringComparison.OrdinalIgnoreCase)) { continue; } - + else if (targetFramework == NET_FRAMEWORK && condition.Value.Contains($"!='{NET_FRAMEWORK}'", StringComparison.OrdinalIgnoreCase)) + { + continue; + } } if (packageNode.Attributes == null) From b0f5a5dec358ea24a68920ac9844ebdeca5a1eda Mon Sep 17 00:00:00 2001 From: sgrampone <30872877+sgrampone@users.noreply.github.com> Date: Wed, 22 May 2024 11:53:32 -0300 Subject: [PATCH 151/164] Delete CH128 stream cipher algorithm (#1028) --- .../Symmetric/SymmetricStreamCipher.cs | 3 --- .../SymmetricUtils/SymmetricStreamAlgorithm.cs | 11 +---------- .../Cryptography/Symmetric/TestStreamEncryption.cs | 7 ------- 3 files changed, 1 insertion(+), 20 deletions(-) diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/Symmetric/SymmetricStreamCipher.cs b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/Symmetric/SymmetricStreamCipher.cs index 55b5a09e3..ab4877476 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/Symmetric/SymmetricStreamCipher.cs +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/Symmetric/SymmetricStreamCipher.cs @@ -134,9 +134,6 @@ private IStreamCipher getCipherEngine(SymmetricStreamAlgorithm algorithm) case SymmetricStreamAlgorithm.RC4: engine = new RC4Engine(); break; - case SymmetricStreamAlgorithm.HC128: - engine = new HC128Engine(); - break; case SymmetricStreamAlgorithm.HC256: engine = new HC256Engine(); break; diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/SymmetricUtils/SymmetricStreamAlgorithm.cs b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/SymmetricUtils/SymmetricStreamAlgorithm.cs index b1e2c99e4..72289d62a 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/SymmetricUtils/SymmetricStreamAlgorithm.cs +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/GeneXusCryptography/SymmetricUtils/SymmetricStreamAlgorithm.cs @@ -15,7 +15,7 @@ namespace GeneXusCryptography.SymmetricUtils public enum SymmetricStreamAlgorithm { #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member - NONE, RC4, HC128, HC256, CHACHA20, SALSA20, XSALSA20, ISAAC + NONE, RC4, HC256, CHACHA20, SALSA20, XSALSA20, ISAAC #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member } @@ -44,8 +44,6 @@ public static SymmetricStreamAlgorithm getSymmetricStreamAlgorithm(String symmet { case "RC4": return SymmetricStreamAlgorithm.RC4; - case "HC128": - return SymmetricStreamAlgorithm.HC128; case "HC256": return SymmetricStreamAlgorithm.HC256; case "CHACHA20": @@ -74,8 +72,6 @@ public static String valueOf(SymmetricStreamAlgorithm symmetrcStreamAlgorithm, E { case SymmetricStreamAlgorithm.RC4: return "RC4"; - case SymmetricStreamAlgorithm.HC128: - return "HC128"; case SymmetricStreamAlgorithm.HC256: return "HC256"; case SymmetricStreamAlgorithm.CHACHA20: @@ -109,10 +105,6 @@ public static int[] getKeySize(SymmetricStreamAlgorithm algorithm, Error error) keySize[1] = 40; keySize[2] = 2048; break; - case SymmetricStreamAlgorithm.HC128: - keySize[0] = 1; - keySize[1] = 128; - break; case SymmetricStreamAlgorithm.HC256: case SymmetricStreamAlgorithm.XSALSA20: keySize[0] = 1; @@ -148,7 +140,6 @@ internal static bool usesIV(SymmetricStreamAlgorithm algorithm, Error error) switch (algorithm) { case SymmetricStreamAlgorithm.RC4: - case SymmetricStreamAlgorithm.HC128: case SymmetricStreamAlgorithm.ISAAC: return false; case SymmetricStreamAlgorithm.HC256: diff --git a/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Cryptography/Symmetric/TestStreamEncryption.cs b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Cryptography/Symmetric/TestStreamEncryption.cs index de1ade552..b22e5e610 100644 --- a/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Cryptography/Symmetric/TestStreamEncryption.cs +++ b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/Cryptography/Symmetric/TestStreamEncryption.cs @@ -70,13 +70,6 @@ public void TestRC4() testBulkAlgorithms("RC4", key1024, ""); } - /* [Test] - public void TestHC128() - { - // HC128 key 128 bits, no nonce - testBulkAlgorithms("HC128", key128, IV128); - }*/ - [Test] public void TestHC256() { From e41c62a205e9afcbf6b8e73098a17b9dddbee50d Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Thu, 23 May 2024 12:11:48 -0300 Subject: [PATCH 152/164] Update npgsql version due to a security vulnerability. (#1030) * Update npgsql version due to a security vulnerability. * Update from 4.0.14 to 4.0.16 to avoid error Strong name signature could not be verified https://github.com/npgsql/npgsql/issues/2031 --- dotnet/src/dotnetframework/GxClasses/GxClasses.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/src/dotnetframework/GxClasses/GxClasses.csproj b/dotnet/src/dotnetframework/GxClasses/GxClasses.csproj index 3d89f45e6..7be48a51b 100644 --- a/dotnet/src/dotnetframework/GxClasses/GxClasses.csproj +++ b/dotnet/src/dotnetframework/GxClasses/GxClasses.csproj @@ -16,7 +16,7 @@ - + From 7e691f11d954dd3b9ca94f1376714b18c6e65094 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Mon, 27 May 2024 16:38:22 -0300 Subject: [PATCH 153/164] Fix exception when printing null values to log. (#1031) --- dotnet/src/dotnetframework/GxClasses/Helpers/GXLogging.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXLogging.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXLogging.cs index 9a66cc57a..c27480c41 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXLogging.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXLogging.cs @@ -799,7 +799,7 @@ public static void Info(IGXLogger logger, string msg, params string[] list) if (logger != null) { if (logger.IsInfoEnabled) { - logger.LogInfo(msg.ToString(), list); + logger.LogInfo(msg, list); } } } From ae0214432c2486c0abce7fd1b0ce03fbbc35dc7b Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 11 Jun 2024 10:49:29 -0300 Subject: [PATCH 154/164] Bump version to 1.31 after creating branch for v18u10 --- dotnet/Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/Directory.Build.props b/dotnet/Directory.Build.props index 1be77468d..73083e09b 100644 --- a/dotnet/Directory.Build.props +++ b/dotnet/Directory.Build.props @@ -3,7 +3,7 @@ 11.0.0.0 1 $([MSBuild]::Add($(MajorFileVersion), 100)) - 30 + 31 $(COMMIT_NUMBER) 0 $(MajorFileVersion).$(MinorFileVersion).$(PatchFileVersion) From a93b64bf450fe23f5ea7e810de90cc80b2a00d33 Mon Sep 17 00:00:00 2001 From: sgrampone <30872877+sgrampone@users.noreply.github.com> Date: Tue, 18 Jun 2024 10:00:17 -0300 Subject: [PATCH 155/164] Load PublicKey from JWKS (#1034) --- .../SecurityAPICommonsNetCore.csproj | 1 + .../SecurityAPICommons/Commons/PublicKey.cs | 61 +++++++- .../SecurityAPICommons.csproj | 2 + .../SecurityAPITestNetCore.csproj | 1 + .../keys/TestPublicKeyFromJwks.cs | 132 ++++++++++++++++++ .../SecurityAPITest/SecurityAPITest.csproj | 2 + 6 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/SecurityAPICommons/keys/TestPublicKeyFromJwks.cs diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/SecurityAPICommonsNetCore/SecurityAPICommonsNetCore.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/SecurityAPICommonsNetCore/SecurityAPICommonsNetCore.csproj index 98801732c..7bdacca1e 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/SecurityAPICommonsNetCore/SecurityAPICommonsNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetcore/SecurityAPICommonsNetCore/SecurityAPICommonsNetCore.csproj @@ -35,6 +35,7 @@ + diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/Commons/PublicKey.cs b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/Commons/PublicKey.cs index 5360256c3..10eed5399 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/Commons/PublicKey.cs +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/Commons/PublicKey.cs @@ -2,7 +2,7 @@ using System.IO; using System.Security; using System.Security.Cryptography; -using Microsoft.Win32.SafeHandles; +using Jose; using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Crypto; @@ -109,8 +109,67 @@ public string ToBase64() return base64Encoded; } + [SecuritySafeCritical] + public bool FromJwks(string jwks, string kid) + { + /******* INPUT VERIFICATION - BEGIN *******/ + SecurityUtils.validateStringInput("jwks", jwks, this.error); + SecurityUtils.validateStringInput("kid", kid, this.error); + if (this.HasError()) + { + return false; + } + + /******* INPUT VERIFICATION - END *******/ + + bool flag = false; + string b64 = ""; + try + { + b64 = FromJson(jwks, kid); + } + catch (Exception e) + { + this.error.setError("PU016", e.Message); + return false; + } + flag = this.FromBase64(b64); + return flag; + + } + /******** EXTERNAL OBJECT PUBLIC METHODS - END ********/ + + private string FromJson(string json, string id) + { + JwkSet set; + try + { + set = JwkSet.FromJson(json, JWT.DefaultSettings.JsonMapper); + } + catch (Exception e) + { + this.error.setError("PU015", e.Message); + return ""; + } + + foreach (Jwk key in set) + { + if (key.KeyId.CompareTo(id) == 0) + { + byte[] m = Base64Url.Decode(key.N); + byte[] e = Base64Url.Decode(key.E); + + RsaKeyParameters parms = new RsaKeyParameters(false, new Org.BouncyCastle.Math.BigInteger(1, m), new Org.BouncyCastle.Math.BigInteger(1, e)); + SubjectPublicKeyInfo subpubkey = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(parms); + return Convert.ToBase64String(subpubkey.GetEncoded()); + + } + } + return ""; + } + private bool loadPublicKeyFromFile(string path, string alias, string password) { bool loaded = false; diff --git a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/SecurityAPICommons.csproj b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/SecurityAPICommons.csproj index 8d6925609..4a9c504e2 100644 --- a/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/SecurityAPICommons.csproj +++ b/dotnet/src/extensions/SecurityAPI/dotnet/dotnetframework/SecurityAPICommons/SecurityAPICommons.csproj @@ -8,6 +8,8 @@ + + diff --git a/dotnet/src/extensions/SecurityAPI/test/dotnetcore/SecurityAPITestNetCore/SecurityAPITestNetCore.csproj b/dotnet/src/extensions/SecurityAPI/test/dotnetcore/SecurityAPITestNetCore/SecurityAPITestNetCore.csproj index a0786cbb3..a0772bcd1 100644 --- a/dotnet/src/extensions/SecurityAPI/test/dotnetcore/SecurityAPITestNetCore/SecurityAPITestNetCore.csproj +++ b/dotnet/src/extensions/SecurityAPI/test/dotnetcore/SecurityAPITestNetCore/SecurityAPITestNetCore.csproj @@ -55,6 +55,7 @@ + diff --git a/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/SecurityAPICommons/keys/TestPublicKeyFromJwks.cs b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/SecurityAPICommons/keys/TestPublicKeyFromJwks.cs new file mode 100644 index 000000000..78f10bad7 --- /dev/null +++ b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/SecurityAPICommons/keys/TestPublicKeyFromJwks.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using NUnit.Framework; +using SecurityAPICommons.Commons; +using SecurityAPITest.SecurityAPICommons.commons; + +namespace SecurityAPITest.SecurityAPICommons.keys +{ + [TestFixture] + public class TestPublicKeyFromJwks : SecurityAPITestObject + { + private static string azure; + private static string akid; + private static string googlev3; + private static string gv3kid; + private static string googlev2; + private static string gv2kid; + private static string facebook; + private static string fkid; + + + [SetUp] + public virtual void SetUp() + { + azure = "{\"keys\":[{\"kty\":\"RSA\",\"use\":\"sig\",\"kid\":\"q-23falevZhhD3hm9CQbkP5MQyU\",\"x5t\":\"q-23falevZhhD3hm9CQbkP5MQyU\",\"n\":\"-9dXkqvGEcIba_TAwmY_ezbn6kLFl6ZMyR7XFCacMf6bBQ0CLlOy9KrDYxI5bm2XAb7qHMKb40d1CyAtO40BV1MZQdrkmLay7RFjQBV6SB24TrC4P0nNXWJCchzzlyesb6S3mqvWVaxRkTS3FkFC8UMsqg2itVcKJW1S2qQCOwF3Sug5GBPYezM_F56_ZfLBpA2aRHzE4eboWoiFjjXN9NqUELACl-DyfWXiyqehRIjuX6hG7lT2erkwWwFgFApi3W4zRtjCx5kRzZtqjDBLWYypBdBBFF8teaCjOq09RF05ZMRlzQKIORb0MxJw_XxVCzXPkKsdchZMBbH3PIuB4Q\",\"e\":\"AQAB\",\"x5c\":[\"MIIC/TCCAeWgAwIBAgIINKBA6Wcz+Q4wDQYJKoZIhvcNAQELBQAwLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldDAeFw0yNDAzMDYxNzAzMzJaFw0yOTAzMDYxNzAzMzJaMC0xKzApBgNVBAMTImFjY291bnRzLmFjY2Vzc2NvbnRyb2wud2luZG93cy5uZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD711eSq8YRwhtr9MDCZj97NufqQsWXpkzJHtcUJpwx/psFDQIuU7L0qsNjEjlubZcBvuocwpvjR3ULIC07jQFXUxlB2uSYtrLtEWNAFXpIHbhOsLg/Sc1dYkJyHPOXJ6xvpLeaq9ZVrFGRNLcWQULxQyyqDaK1VwolbVLapAI7AXdK6DkYE9h7Mz8Xnr9l8sGkDZpEfMTh5uhaiIWONc302pQQsAKX4PJ9ZeLKp6FEiO5fqEbuVPZ6uTBbAWAUCmLdbjNG2MLHmRHNm2qMMEtZjKkF0EEUXy15oKM6rT1EXTlkxGXNAog5FvQzEnD9fFULNc+Qqx1yFkwFsfc8i4HhAgMBAAGjITAfMB0GA1UdDgQWBBRRZhKrglETd/OCIUfwuGTRJkwNUTANBgkqhkiG9w0BAQsFAAOCAQEA46UCoAJlXMuxB/21GTP96KHx8zoYt2UnvCFxkLpRrkRThVBhTbd/txAYPb3eAGuhjJlNstKxfcCUaquKktQAdeGPA+Kn62DlksFaXjrcC0rGaiD+MiY2B/ATS0ebCYL3s3BJNmKKB9+1kbbcWCSQelcM2cNjJHJDqUhTyWMnTz4UK9RXwHFLq/T3yYP0qz/FZZR6RfCWzXz35SkZVObDMhPcyLgxy6CLMQotrtThsqn/2JZ7We/ehl6xCgVym6hfuv0Ju9WtZal+k46XDw2R3IoHJueB/vD0hLOqdZerwzD5OsCrTW2n3njN2nDHhCzlxGrhlleNDJhawFoxzSOuhQ==\"],\"issuer\":\"https://login.microsoftonline.com/5ec7bbf9-1872-46c9-b201-a1e181996b35/v2.0\"},{\"kty\":\"RSA\",\"use\":\"sig\",\"kid\":\"V1Y09OFMBXAZUFfJ-vWjlrH-ZSc\",\"x5t\":\"V1Y09OFMBXAZUFfJ-vWjlrH-ZSc\",\"n\":\"qinPWt_43NIzlluP8oLBaKXBHMJ0pZWNOu5yxCD_UZ7B5yrdMdzgFhr0cpDcp3vkkE97MyyIN3a2tg8UhHCtphkShbKiO36uNjc0TC-jVnhwI_mLZ1piP0gkItm26YTLw71rY9JpS2dY4CxnsHH6V8vsVaaQAGQByM6BdwUiep-7-Cn69iWybZkga_8gZAy9O1hOyBV22mKVRuWsLwLeBcahlOEGJeP4tx8vVSjKTX8tV2HJlL01JjxBojGdwtiqwr7iEOoUAwMhC9b80ASkSRcb-mU-SfGhmSP-DVgD1nXzFcu-v2bVDr4-OpLuOljzJVEz0r4W4tmf3KwToAQNcQ\",\"e\":\"AQAB\",\"x5c\":[\"MIIC/TCCAeWgAwIBAgIIdZL3187SZ0EwDQYJKoZIhvcNAQELBQAwLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldDAeFw0yNDAzMDYyMTA4MDdaFw0yOTAzMDYyMTA4MDdaMC0xKzApBgNVBAMTImFjY291bnRzLmFjY2Vzc2NvbnRyb2wud2luZG93cy5uZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqKc9a3/jc0jOWW4/ygsFopcEcwnSllY067nLEIP9RnsHnKt0x3OAWGvRykNyne+SQT3szLIg3dra2DxSEcK2mGRKFsqI7fq42NzRML6NWeHAj+YtnWmI/SCQi2bbphMvDvWtj0mlLZ1jgLGewcfpXy+xVppAAZAHIzoF3BSJ6n7v4Kfr2JbJtmSBr/yBkDL07WE7IFXbaYpVG5awvAt4FxqGU4QYl4/i3Hy9VKMpNfy1XYcmUvTUmPEGiMZ3C2KrCvuIQ6hQDAyEL1vzQBKRJFxv6ZT5J8aGZI/4NWAPWdfMVy76/ZtUOvj46ku46WPMlUTPSvhbi2Z/crBOgBA1xAgMBAAGjITAfMB0GA1UdDgQWBBQxCpcti/aMWYbvhjLCL5sKhcQ1pjANBgkqhkiG9w0BAQsFAAOCAQEAK+rZEgIu+e7ARr9IIYxMXSxJ9gy6Wnw0ZMtchoDvUufFmWnwHtj15zByNpaNRvojHWaWrfqQsk+bKzazPWXTOiM7yoLxKfzM4fYI3QP5TRizGvz5p4COLBiDB7XvOiFsm0SxJzhhba5+3J0CmDhsURfzhw7AX+OCL7arF5gPv4PMIQ8GiTlukVzWN7EhQ2DZbm74jVOYwTN74+ECynB/NZvprn0MOWmDMxD7ysi2Wv459tg1nGSMGkcIHOo2DSj18nm25QHzUjjbmkma36uw2lM/Lsjd0HsueD2nS+4eiVYqsuC4cDO/LvlRdMteuZLgvdqX35Xm608VGUPoDaFDUQ==\"],\"issuer\":\"https://login.microsoftonline.com/5ec7bbf9-1872-46c9-b201-a1e181996b35/v2.0\"},{\"kty\":\"RSA\",\"use\":\"sig\",\"kid\":\"L1KfKFI_jnXbwWc22xZxw1sUHH0\",\"x5t\":\"L1KfKFI_jnXbwWc22xZxw1sUHH0\",\"n\":\"ojzOLoPAa8DykJWn0dz9vB_lPTkwtCyw1oR8WFpszoBaG-hKmBhYLCuyyOWIoIgmxETI5-bulQzsCTR79WWxq6sNxXPTlBy4i1ihjwhnD7CrgRu0U_O8GPzMMPlQXYs_C-tt0OdPPYEYv_ZzbNkgMTNaR5WWe-d3L4nDMWrSP70Sz-8_kcmA1qaap_MT_N9a5QidD20bfOvdXttNxu6_azAVN5UYeBevrTaJHO2HRVicw_zKwJSZV26jljpsmGMiNUu2anARS2C4KM_HCIfX7cwE9A89pJ1Uh58bBL98b1NDzGkt0hVCBTilPakhR4RHP0U9dvHFo3pUJd1Qrl9AQQ\",\"e\":\"AQAB\",\"x5c\":[\"MIIC/TCCAeWgAwIBAgIIOdwuMdHVGkEwDQYJKoZIhvcNAQELBQAwLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldDAeFw0yNDA0MTExNjA0MjZaFw0yOTA0MTExNjA0MjZaMC0xKzApBgNVBAMTImFjY291bnRzLmFjY2Vzc2NvbnRyb2wud2luZG93cy5uZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCiPM4ug8BrwPKQlafR3P28H+U9OTC0LLDWhHxYWmzOgFob6EqYGFgsK7LI5YigiCbERMjn5u6VDOwJNHv1ZbGrqw3Fc9OUHLiLWKGPCGcPsKuBG7RT87wY/Mww+VBdiz8L623Q5089gRi/9nNs2SAxM1pHlZZ753cvicMxatI/vRLP7z+RyYDWppqn8xP831rlCJ0PbRt8691e203G7r9rMBU3lRh4F6+tNokc7YdFWJzD/MrAlJlXbqOWOmyYYyI1S7ZqcBFLYLgoz8cIh9ftzAT0Dz2knVSHnxsEv3xvU0PMaS3SFUIFOKU9qSFHhEc/RT128cWjelQl3VCuX0BBAgMBAAGjITAfMB0GA1UdDgQWBBTXp9LEVP2CZiM0hEP5t18l/sDAfzANBgkqhkiG9w0BAQsFAAOCAQEAH5vIhhDC8d+31sm9Lo5Ohlsabmv7eA3JgXKw7x4VDFoQxrZHMw0qsQOk9bTrwJHa09o0CQkO8VZG5zJ0ZpXplRtrN8FaKCLb1qstF2P6wuZIZR1EJTJb4L5VvhaSUiFWkBfQPBDMVJd9g2CEOhW+1jIKEea0wt3AC2zUvNybhbSzDMyPNSwu0EiZLJsUMdbOxdGmCZjvIWMaddDu9GVT+KtPWYDDKs2POZoYPDGCp6ftd2+L+ma2gZCL3HvFBWjCIctsu20aHP8retkEOiVzMVbt68gDyT61VTlhBM/pxlcHMO6wfA1nQzY2qDwMCEOocmsYt3mrITolYxxyBjSVnA==\"],\"issuer\":\"https://login.microsoftonline.com/5ec7bbf9-1872-46c9-b201-a1e181996b35/v2.0\"},{\"kty\":\"RSA\",\"use\":\"sig\",\"kid\":\"UxyGE-ffaoAkooUxUFn0ar7fvDM\",\"x5t\":\"UxyGE-ffaoAkooUxUFn0ar7fvDM\",\"n\":\"2fVfr9fJb8m5eDwVp6WhzO7-ezI9OfeQPTpHKB8j2wlBJNu6oYGPC4McDysfNyKtUaYQpyckupAquEjAcP8CDjcv4B7pjdlgR25JLXuemMl8LD5bOu4s55EwmPewoHlBInWDK5rgRryoApZNQGVuI4u7Q56DNNsXo7I1qS13MmXKrwO1rp0PIetHesDNT2nnY6xjHlTGPkc-aydV8QNulStdiXOnbiV7wQzQmtqjK3AWE_oJHIuTaGwdVeqSqNaJKSCGEPb9G8J1Q-tFh0TOgqPjk5Qb_uO5X_0Fw_4OI1xeGqoMuOROi_StRXv4IvfbGnZgbsV4dOUL0kJEBRPglQ\",\"e\":\"AQAB\",\"x5c\":[\"MIIC6jCCAdKgAwIBAgIJAOnFoXSbn2jjMA0GCSqGSIb3DQEBCwUAMCMxITAfBgNVBAMTGGxvZ2luLm1pY3Jvc29mdG9ubGluZS51czAeFw0yNDAzMjQyMTQyMzJaFw0yOTAzMjQyMTQyMzJaMCMxITAfBgNVBAMTGGxvZ2luLm1pY3Jvc29mdG9ubGluZS51czCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANn1X6/XyW/JuXg8Faeloczu/nsyPTn3kD06RygfI9sJQSTbuqGBjwuDHA8rHzcirVGmEKcnJLqQKrhIwHD/Ag43L+Ae6Y3ZYEduSS17npjJfCw+WzruLOeRMJj3sKB5QSJ1gyua4Ea8qAKWTUBlbiOLu0OegzTbF6OyNaktdzJlyq8Dta6dDyHrR3rAzU9p52OsYx5Uxj5HPmsnVfEDbpUrXYlzp24le8EM0JraoytwFhP6CRyLk2hsHVXqkqjWiSkghhD2/RvCdUPrRYdEzoKj45OUG/7juV/9BcP+DiNcXhqqDLjkTov0rUV7+CL32xp2YG7FeHTlC9JCRAUT4JUCAwEAAaMhMB8wHQYDVR0OBBYEFOBFoFzi/Txj04qIPOx5PFEPf8WFMA0GCSqGSIb3DQEBCwUAA4IBAQCKdwSHnxHX2KZv63dhMugnBXR0qA6gVIOL3d60Nh7TReEhJ98DsSYtxSM9vrdMac+4m6Yg/slvRZD4jet/cH/qCjA+I+LUkrU0MEWqhf03BsEwlSY9ZGbOtWdgPwobFK7Y+M7wuPKSSrwPiBUgrG4UFpZbDVr3VYMljgYfXu3WwtshqdgslvQFQZugKLsoAaR9v1SlNRyOL6qDaqN9x3cHbIniApRjBJFrVijhZm5JRE/vyMgKl6EaBLDoQtvSIOARi8NwZi5LFB0361MR0eE18i87rvPO6cF4Vz2kg+cC9N54wf+gbINHREkbO70B1Q+QbbtlkfWR7y9Q1HMrnA3O\"],\"issuer\":\"https://login.microsoftonline.com/5ec7bbf9-1872-46c9-b201-a1e181996b35/v2.0\"},{\"kty\":\"RSA\",\"use\":\"sig\",\"kid\":\"EHu9neGZBCDyv2IYq8U5JiRMFng\",\"x5t\":\"EHu9neGZBCDyv2IYq8U5JiRMFng\",\"n\":\"w1kH9dFGdaJS8fvQulDssuuNhkczzy1Mo6IiNoC3ih3K-L_VF5TQmSkqXrovWCUlhBCfc1VPR9Cn2G4UP7Sygn0nTqXBY1NFQQZecqwGESJFIuonRqjdlDhNYXjSF_eg63KyuyLV8A-Sn05Ufuc8ax0tyrxPbkOql0pB2hmRhj94iDAFB2LBoxfEgxCG3VT0ascVYW6voTCChs2P65-4RLC-ib1w1FjuACDwsB7KZDxxaUGLfnIoLWUjmw1zCaDRiRvhxB4jQXpB64IFxaYsqxA_x8bj2JEE7qALZ2dZ3fPy9yYSAnRfaTMetgouR9x4SKy4HxUxsADMm_7p9LiRZQ\",\"e\":\"AQAB\",\"x5c\":[\"MIIC6jCCAdKgAwIBAgIJAO8yTjZIibNNMA0GCSqGSIb3DQEBCwUAMCMxITAfBgNVBAMTGGxvZ2luLm1pY3Jvc29mdG9ubGluZS51czAeFw0yNDA1MDYyMzA5MDJaFw0yOTA1MDYyMzA5MDJaMCMxITAfBgNVBAMTGGxvZ2luLm1pY3Jvc29mdG9ubGluZS51czCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMNZB/XRRnWiUvH70LpQ7LLrjYZHM88tTKOiIjaAt4odyvi/1ReU0JkpKl66L1glJYQQn3NVT0fQp9huFD+0soJ9J06lwWNTRUEGXnKsBhEiRSLqJ0ao3ZQ4TWF40hf3oOtysrsi1fAPkp9OVH7nPGsdLcq8T25DqpdKQdoZkYY/eIgwBQdiwaMXxIMQht1U9GrHFWFur6EwgobNj+ufuESwvom9cNRY7gAg8LAeymQ8cWlBi35yKC1lI5sNcwmg0Ykb4cQeI0F6QeuCBcWmLKsQP8fG49iRBO6gC2dnWd3z8vcmEgJ0X2kzHrYKLkfceEisuB8VMbAAzJv+6fS4kWUCAwEAAaMhMB8wHQYDVR0OBBYEFJ4xtCt3JpPxlUVH7ATgJGM4ofg7MA0GCSqGSIb3DQEBCwUAA4IBAQB9WAEvE3VtO5wIOtN5N/QbIU63H5QPgMW3M9nOs43AhLgwvWupxaiATyMqtK53RPvcxYPe7QwSw/xH9McXii1bOBVmc71AcjlXYfuMJ/0IMEFEUQwZDEwj+vIlg07gWh0hleehyAgMblDUQRRN+b5J+soa9LBBAooY/48F/++y4DiTzKyoWn5cV4H2kdIFVyB43XzJRqDoK1ZhplVLTc1a3K1NL1/qP9rhvtx62YDzfNh4+FTJLu31ALcUbD+Qx2m0U9wuWq3EdUzEen5DeLvhx55YD7V1BASHNYBd8lGhHk97aTw53CMGAuTELvWO+4x7dFM9autw2KvSn76n/4Ql\"],\"issuer\":\"https://login.microsoftonline.com/5ec7bbf9-1872-46c9-b201-a1e181996b35/v2.0\"}]}"; + googlev3 = "{\n" + + " \"keys\": [\n" + + " {\n" + + " \"alg\": \"RS256\",\n" + + " \"use\": \"sig\",\n" + + " \"kty\": \"RSA\",\n" + + " \"e\": \"AQAB\",\n" + + " \"kid\": \"6719678351a5faedc2e70274bbea62da2a8c4a12\",\n" + + " \"n\": \"oAP5OnSzKfkEV2QMm2XCuu4G8VGRBOyhKg-4H04WzYzPqM_Tmqi60Vod96JTo7SfM0OoGeNnlkWNjjBWkSS66alNLrvTNLi0A-KGeBsZiIFmrbsP6HHJfFzPd0Mci7-e11fNKecZgbC1me9PtRXFZb9JprZGFOvBiMwU0rRvh0GWYmTFj1HFjOIMAwTGOKOVGNuPjv0b3V0YaAkUNklzi4MM6qgzUb0tE0so1Ii7kBe7roMScS2USPeeJkeoPjLEbQcrT8MxOSxH-JgPLfq-zOnEJ6ERW3mtXdZCNzqmVLn5yjX5lKr5E2vgkPAHx9NLZ09fo_L9woeX_5epl6cIkQ\"\n" + + " },\n" + + " {\n" + + " \"use\": \"sig\",\n" + + " \"e\": \"AQAB\",\n" + + " \"n\": \"w-l_VE4KNa22n4nsMwcabujowm924YoQQnwOz_dPYHmDI1O-r2bqw6mHmByXwii7aaeIMHJZWpmT5SkR3OYIu5RbSgiU-8JrQoplW_vZY2IqG1y5-frPC_9gnz_0qKKjtjqglCP-1AlfOdu7r5kOpkOACs5mWn4tm1K9R1EPjk2T_MMO7FkteZd8woh1fwUUuvbhPyDxBzx9EUsnGWbpTndOYc7W-EUk1jMtWBk3buLeaypVaOLWranK_XFrX-xx03BohrfinOqmftYgc0z94sxix7X1G36JZeh8-jpUhwyBPinBxOZOE_5kQn4CYM66Ygxwiws0ZJ-klG2qTi239w\",\n" + + " \"alg\": \"RS256\",\n" + + " \"kty\": \"RSA\",\n" + + " \"kid\": \"674dbba8faee69acae1bc1be190453678f472803\"\n" + + " }\n" + + " ]\n" + + "}"; + googlev2 = "{\n" + + " \"keys\": [\n" + + " {\n" + + " \"kty\": \"RSA\",\n" + + " \"n\": \"oAP5OnSzKfkEV2QMm2XCuu4G8VGRBOyhKg-4H04WzYzPqM_Tmqi60Vod96JTo7SfM0OoGeNnlkWNjjBWkSS66alNLrvTNLi0A-KGeBsZiIFmrbsP6HHJfFzPd0Mci7-e11fNKecZgbC1me9PtRXFZb9JprZGFOvBiMwU0rRvh0GWYmTFj1HFjOIMAwTGOKOVGNuPjv0b3V0YaAkUNklzi4MM6qgzUb0tE0so1Ii7kBe7roMScS2USPeeJkeoPjLEbQcrT8MxOSxH-JgPLfq-zOnEJ6ERW3mtXdZCNzqmVLn5yjX5lKr5E2vgkPAHx9NLZ09fo_L9woeX_5epl6cIkQ==\",\n" + + " \"use\": \"sig\",\n" + + " \"e\": \"AQAB\",\n" + + " \"kid\": \"6719678351a5faedc2e70274bbea62da2a8c4a12\",\n" + + " \"alg\": \"RS256\"\n" + + " },\n" + + " {\n" + + " \"alg\": \"RS256\",\n" + + " \"e\": \"AQAB\",\n" + + " \"use\": \"sig\",\n" + + " \"kty\": \"RSA\",\n" + + " \"n\": \"w-l_VE4KNa22n4nsMwcabujowm924YoQQnwOz_dPYHmDI1O-r2bqw6mHmByXwii7aaeIMHJZWpmT5SkR3OYIu5RbSgiU-8JrQoplW_vZY2IqG1y5-frPC_9gnz_0qKKjtjqglCP-1AlfOdu7r5kOpkOACs5mWn4tm1K9R1EPjk2T_MMO7FkteZd8woh1fwUUuvbhPyDxBzx9EUsnGWbpTndOYc7W-EUk1jMtWBk3buLeaypVaOLWranK_XFrX-xx03BohrfinOqmftYgc0z94sxix7X1G36JZeh8-jpUhwyBPinBxOZOE_5kQn4CYM66Ygxwiws0ZJ-klG2qTi239w==\",\n" + + " \"kid\": \"674dbba8faee69acae1bc1be190453678f472803\"\n" + + " }\n" + + " ]\n" + + "}"; + facebook = "{\n" + + " \"keys\": [\n" + + " {\n" + + " \"kid\": \"d458ab5237807dc6718901e522cebcd8e8157791\",\n" + + " \"kty\": \"RSA\",\n" + + " \"alg\": \"RS256\",\n" + + " \"use\": \"sig\",\n" + + " \"n\": \"uPyWMhNfNsO9EtiraYI0tr78vnkiJmzsmAAUd8hLHF5vPXDn683aQKZQ2Ny5lObigNmbHI5tt5y0o5m0RuZjJTj081uWm7Z901boO-p4VLwEONzjh4vTp2ZQ7aMjo17kMBzInHqz9iruWeB94dEu_LKYdQnDI6rweD_-chWWTR4mc7xbeaNozLHYzjEisSrIM3xIry2lZv5Mh334ZoahcTXGouFtU2XV_HvStXthwhoAtizQK7s2yJlBz8qlQK2lFNojRzd95f2bkynRnIvcpoF-qHZbOBTCIf-6TLp23qShs-XvbCkwHMhzvCPxcuZx3GNfCQkyTxeM5IGIMlWZ8w\",\n" + + " \"e\": \"AQAB\"\n" + + " },\n" + + " {\n" + + " \"kid\": \"ec11d50341c08e82899650e6afcc6668f2a0a420\",\n" + + " \"kty\": \"RSA\",\n" + + " \"alg\": \"RS256\",\n" + + " \"use\": \"sig\",\n" + + " \"n\": \"-rJ0HvlxiqOcwfpP6LsAYo0aaGNmohEBFr1JuWCGVvnPb3Z5Akd5w_bxQMRlOMot15IyrhWFonWCFr9H02f9E9GOEaroAj0zxQnCXcuGWb1BFN6RfoGNFpee1MqSDV3ikSIsSI3JL-z_1uBtDsQ1AtbYMKsB572v64bapW4WjDjekz0pQ-ePizVWm9mNNQxkA_fh3p1hW3KssXgnasWbKJODT5I6hnzd4whxj22oLE8xJCYTFeouk86teKI-nvK-LmaxoetBhnDn3QS5pN_oiIfDqjKPXGazeG2qwGAE8VPeISPvzYIstGbEh3NCzFEoB7a7APF1nLEo7Lco9aWjYQ\",\n" + + " \"e\": \"AQAB\"\n" + + " }\n" + + " ]\n" + + "}"; + akid = "L1KfKFI_jnXbwWc22xZxw1sUHH0"; + gv3kid = "6719678351a5faedc2e70274bbea62da2a8c4a12"; + gv2kid = "6719678351a5faedc2e70274bbea62da2a8c4a12"; + fkid = "ec11d50341c08e82899650e6afcc6668f2a0a420"; + } + + [Test] + public void testAzure() + { + PublicKey key = new PublicKey(); + bool loaded = key.FromJwks(azure, akid); + Assert.AreEqual(true, loaded); + Assert.IsTrue(loaded); + Assert.IsFalse(key.HasError()); + } + + [Test] + public void testGooglev2() + { + PublicKey key = new PublicKey(); + bool loaded = key.FromJwks(googlev2, gv2kid); + Assert.IsTrue(loaded); + Assert.IsFalse(key.HasError()); + } + + [Test] + public void testGooglev3() + { + PublicKey key = new PublicKey(); + bool loaded = key.FromJwks(googlev3, gv3kid); + Assert.IsTrue(loaded); + Assert.IsFalse(key.HasError()); + } + + [Test] + public void testFacebook() + { + PublicKey key = new PublicKey(); + bool loaded = key.FromJwks(facebook, fkid); + Assert.IsTrue(loaded); + Assert.IsFalse(key.HasError()); + } + } +} diff --git a/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/SecurityAPITest.csproj b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/SecurityAPITest.csproj index c9262da04..d456a37c0 100644 --- a/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/SecurityAPITest.csproj +++ b/dotnet/src/extensions/SecurityAPI/test/dotnetframework/SecurityAPITest/SecurityAPITest.csproj @@ -13,6 +13,8 @@ + + From 2698d699db8c233ea0934c3115b6ed18e5778db6 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 18 Jun 2024 11:18:26 -0300 Subject: [PATCH 156/164] Improve error logging for trace when loading data types via reflections. (#1041) Some messages were logged as errors but should be warnings due to multiple attempts to load from assemblies. --- .../GxClasses/Helpers/GXMetadata.cs | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXMetadata.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXMetadata.cs index 9c83d6a8f..b3b76cb43 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXMetadata.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXMetadata.cs @@ -88,11 +88,11 @@ static public Type FindType(string defaultAssemblyName, string ns, string clssWi { try { - objType = ignoreCase? defaultAssembly.GetType(clss, false, ignoreCase): defaultAssembly.GetType(clss); + objType = ignoreCase? defaultAssembly.GetType(clss, false, ignoreCase): defaultAssembly.GetType(clss, false); } catch { - GXLogging.Error(log, "Failed to load type: " + clss + ", assembly: " + defaultAssembly.FullName); + GXLogging.Warn(log, "Failed to load type: " + clss + ", assembly: " + defaultAssembly.FullName); } } @@ -103,36 +103,40 @@ static public Type FindType(string defaultAssemblyName, string ns, string clssWi { #if NETCORE Assembly assem = AssemblyLoader.LoadAssembly(defaultAssemblyNameObj); - objType = ignoreCase ? assem.GetType(clss): assem.GetType(clss, false, ignoreCase); + objType = ignoreCase ? assem.GetType(clss, false): assem.GetType(clss, false, ignoreCase); #else - objType = Assembly.Load(defaultAssemblyNameObj).GetType(clss); + objType = Assembly.Load(defaultAssemblyNameObj).GetType(clss, false); #endif } } + catch(FileNotFoundException) + { + GXLogging.Warn(log, "Assembly: ", defaultAssemblyName, "not found"); + } catch(Exception ex) { - GXLogging.Error(log, "Failed to load type: " + clss + ", assembly: " + defaultAssemblyName, ex); + GXLogging.Warn(log, "Failed to load type: " + clss + ", assembly: " + defaultAssemblyName, ex); } try { if (objType == null) if (Assembly.GetEntryAssembly() != null) - objType = ignoreCase ? Assembly.GetEntryAssembly().GetType(clss, false, ignoreCase) : Assembly.GetEntryAssembly().GetType(clss); + objType = ignoreCase ? Assembly.GetEntryAssembly().GetType(clss, false, ignoreCase) : Assembly.GetEntryAssembly().GetType(clss, false); } catch { - GXLogging.Error(log, "Failed to load type: " + clss + " from entryAssembly"); + GXLogging.Warn(log, "Failed to load type: " + clss + " from entryAssembly"); } try { if (objType == null) - objType = ignoreCase ? Assembly.GetCallingAssembly().GetType(clss, false, ignoreCase) : Assembly.GetCallingAssembly().GetType(clss); + objType = ignoreCase ? Assembly.GetCallingAssembly().GetType(clss, false, ignoreCase) : Assembly.GetCallingAssembly().GetType(clss, false); } catch { - GXLogging.Error(log, "Failed to load type: " + clss + " from callingAssembly"); + GXLogging.Warn(log, "Failed to load type: " + clss + " from callingAssembly"); } if (objType == null && !string.IsNullOrEmpty(ns) && Config.GetValueOf("AppMainNamespace", out appNS)) @@ -148,7 +152,7 @@ static public Type FindType(string defaultAssemblyName, string ns, string clssWi foreach (Assembly asby in AppDomain.CurrentDomain.GetAssemblies()) { - objType = ignoreCase ? asby.GetType(clss, false, ignoreCase) : asby.GetType(clss); + objType = ignoreCase ? asby.GetType(clss, false, ignoreCase) : asby.GetType(clss, false); if (objType != null) break; } @@ -183,10 +187,10 @@ static public Type FindType(string defaultAssemblyName, string ns, string clssWi try { #if !NETCORE - objType = Assembly.LoadFrom(file).GetType(clss); + objType = Assembly.LoadFrom(file).GetType(clss, false); #else Assembly assem = AssemblyLoader.LoadAssembly(new AssemblyName(Path.GetFileNameWithoutExtension(file))); - objType = ignoreCase ? assem.GetType(clss, false, ignoreCase) : assem.GetType(clss); + objType = ignoreCase ? assem.GetType(clss, false, ignoreCase) : assem.GetType(clss, false); #endif if (objType != null) break; From 3495b86a83bbcfbed1eb46b89be355a70a0ab99f Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 18 Jun 2024 12:25:33 -0300 Subject: [PATCH 157/164] Fixed internal server error for REST services with string collection output parameters. (#1032) * Fixed internal server error for REST services with string collection output parameters. * Fix a broken case and add it to unit tests. * Remove Debugger. * Fix broken case with rest services returning SDT collection. * Simple Collections do not need to convert. * Add test for rest service returning SDT collection. --- .../GxClasses/Services/GxRestWrapper.cs | 31 +- .../DotNetCoreWebUnitTest.csproj | 9 + .../Middleware/RestServiceTest.cs | 42 + .../apps/getbccollection.cs | 114 ++ .../apps/getbccollection.svc | 1 + .../apps/getcollection.cs | 81 ++ .../apps/getcollection.svc | 1 + .../apps/getsdtcollection.cs | 360 +++++++ .../apps/getsdtcollection.svc | 1 + .../apps/type_SdtCustomerSdtSimple.cs | 329 ++++++ .../apps/type_SdtInvoice.cs | 983 ++++++++++++++++++ .../apps/type_SdtInvoice_Level.cs | 667 ++++++++++++ 12 files changed, 2608 insertions(+), 11 deletions(-) create mode 100644 dotnet/test/DotNetCoreWebUnitTest/apps/getbccollection.cs create mode 100644 dotnet/test/DotNetCoreWebUnitTest/apps/getbccollection.svc create mode 100644 dotnet/test/DotNetCoreWebUnitTest/apps/getcollection.cs create mode 100644 dotnet/test/DotNetCoreWebUnitTest/apps/getcollection.svc create mode 100644 dotnet/test/DotNetCoreWebUnitTest/apps/getsdtcollection.cs create mode 100644 dotnet/test/DotNetCoreWebUnitTest/apps/getsdtcollection.svc create mode 100644 dotnet/test/DotNetCoreWebUnitTest/apps/type_SdtCustomerSdtSimple.cs create mode 100644 dotnet/test/DotNetCoreWebUnitTest/apps/type_SdtInvoice.cs create mode 100644 dotnet/test/DotNetCoreWebUnitTest/apps/type_SdtInvoice_Level.cs diff --git a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs index 4f8f98eed..2baba5a70 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs @@ -898,21 +898,30 @@ protected static object MakeRestType( object collectionValue, bool isApiObject) { restItemType = ClassLoader.FindType(Config.CommonAssemblyName, itemType.FullName + "_RESTLInterface", null); } - if (restItemType == null)//Collection convert to GxGenericCollection + else //Collection convert to GxGenericCollection { - restItemType = ClassLoader.FindType(Config.CommonAssemblyName, itemType.FullName + "_RESTInterface", null); + if (typeof(GxUserType).IsAssignableFrom(itemType)){ + restItemType = ClassLoader.FindType(Config.CommonAssemblyName, itemType.FullName + "_RESTInterface", null); + } + else + { + collectionObject = collectionValue; + } } - object[] attributes = restItemType.GetCustomAttributes(typeof(GxJsonSerialization), false); - IEnumerable serializationAttributes = attributes.Where(a => a.GetType() == typeof(GxJsonSerialization)); - if (serializationAttributes != null && serializationAttributes.Any()) + if (restItemType != null) { - GxJsonSerialization attFmt = (GxJsonSerialization)serializationAttributes.FirstOrDefault(); - wrappedStatus = attFmt.JsonUnwrapped; - isWrapped = (isApiObject)? ((wrappedStatus == "wrapped")? true: false): ((wrappedStatus == "unwrapped") ? false : true); + object[] attributes = restItemType.GetCustomAttributes(typeof(GxJsonSerialization), false); + IEnumerable serializationAttributes = attributes.Where(a => a.GetType() == typeof(GxJsonSerialization)); + if (serializationAttributes != null && serializationAttributes.Any()) + { + GxJsonSerialization attFmt = (GxJsonSerialization)serializationAttributes.FirstOrDefault(); + wrappedStatus = attFmt.JsonUnwrapped; + isWrapped = (isApiObject) ? ((wrappedStatus == "wrapped") ? true : false) : ((wrappedStatus == "unwrapped") ? false : true); + } + isEmpty = !restItemType.IsDefined(typeof(GxOmitEmptyCollection), false); + Type genericListItemType = typeof(GxGenericCollection<>).MakeGenericType(restItemType); + collectionObject = Activator.CreateInstance(genericListItemType, new object[] { collectionValue, isWrapped, wrappedStatus }); } - isEmpty = !restItemType.IsDefined(typeof(GxOmitEmptyCollection), false); - Type genericListItemType = typeof(GxGenericCollection<>).MakeGenericType(restItemType); - collectionObject = Activator.CreateInstance(genericListItemType, new object[] { collectionValue, isWrapped , wrappedStatus}); } // Empty collection serialized w/ noproperty if (collectionObject is IList restList) diff --git a/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj b/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj index 5da562bb5..5d252c63c 100644 --- a/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj +++ b/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj @@ -57,6 +57,15 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest diff --git a/dotnet/test/DotNetCoreWebUnitTest/Middleware/RestServiceTest.cs b/dotnet/test/DotNetCoreWebUnitTest/Middleware/RestServiceTest.cs index 49dbbfe4f..ada29501a 100644 --- a/dotnet/test/DotNetCoreWebUnitTest/Middleware/RestServiceTest.cs +++ b/dotnet/test/DotNetCoreWebUnitTest/Middleware/RestServiceTest.cs @@ -23,6 +23,9 @@ public RestServiceTest() : base() { ClassLoader.FindType("apps.append", "GeneXus.Programs.apps", "append", Assembly.GetExecutingAssembly(), true);//Force loading assembly for append procedure ClassLoader.FindType("apps.saveimage", "GeneXus.Programs.apps", "saveimage", Assembly.GetExecutingAssembly(), true);//Force loading assembly for saveimage procedure + ClassLoader.FindType("apps.getcollection", "GeneXus.Programs.apps", "getcollection", Assembly.GetExecutingAssembly(), true); + ClassLoader.FindType("apps.getsdtcollection", "GeneXus.Programs.apps", "getsdtcollection", Assembly.GetExecutingAssembly(), true); + ClassLoader.FindType("apps.getbccollection", "GeneXus.Programs.apps", "getbccollection", Assembly.GetExecutingAssembly(), true); server.AllowSynchronousIO = true; } const string serviceBodyResponse = "OK"; @@ -129,6 +132,7 @@ private async Task RunController(HttpClient client) return response; } string ACCESS_CONTROL_MAX_AGE_HEADER = "86400"; + [Fact] public async Task TestHttpResponseOnRestService() { @@ -140,6 +144,44 @@ public async Task TestHttpResponseOnRestService() Assert.Equal(ACCESS_CONTROL_MAX_AGE_HEADER, values.FirstOrDefault()); } + [Fact] + public async Task TestRestServiceWithSimpleCollectionOutput() + { + server.AllowSynchronousIO = true; + HttpClient client = server.CreateClient(); + HttpResponseMessage response = await client.PostAsync("rest/apps/getcollection", null); + response.EnsureSuccessStatusCode(); + Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); + string responseBody = await response.Content.ReadAsStringAsync(); + Assert.Equal("{\"CliType\":1,\"CliCode\":[1,2]}", responseBody); + } + [Fact] + public async Task TestRestServiceWithBCCollectionOutput() + { + server.AllowSynchronousIO = true; + HttpClient client = server.CreateClient(); + HttpResponseMessage response = await client.PostAsync("rest/apps/getbccollection", null); + response.EnsureSuccessStatusCode(); + Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); + string responseBody = await response.Content.ReadAsStringAsync(); + + string expected = "{\"InvoiceDate\":\"2024-02-02\",\"uri\":\"\"}"; + Assert.Contains(expected, responseBody, StringComparison.OrdinalIgnoreCase); + } + [Fact] + public async Task TestRestServiceWithSdtCollectionOutput() + { + server.AllowSynchronousIO = true; + HttpClient client = server.CreateClient(); + HttpResponseMessage response = await client.PostAsync("rest/apps/getsdtcollection", null); + response.EnsureSuccessStatusCode(); + Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); + string responseBody = await response.Content.ReadAsStringAsync(); + + string expected = "{\"CustomerId\":1,"; + Assert.Contains(expected, responseBody, StringComparison.OrdinalIgnoreCase); + } + } } diff --git a/dotnet/test/DotNetCoreWebUnitTest/apps/getbccollection.cs b/dotnet/test/DotNetCoreWebUnitTest/apps/getbccollection.cs new file mode 100644 index 000000000..600b1cfc8 --- /dev/null +++ b/dotnet/test/DotNetCoreWebUnitTest/apps/getbccollection.cs @@ -0,0 +1,114 @@ +using System; +using GeneXus.Application; +using GeneXus.Data.NTier; +using GeneXus.Procedure; +using GeneXus.Utils; +namespace GeneXus.Programs.apps +{ + public class getbccollection : GXProcedure + { + public getbccollection() + { + context = new GxContext(); + DataStoreUtil.LoadDataStores(context); + IsMain = true; + context.SetDefaultTheme("GeneXusXEv2", false); + } + + public getbccollection(IGxContext context) + { + this.context = context; + IsMain = false; + } + + public void execute(DateTime aP0_invoicedate, + short aP1_CustomerId, + string aP2_Customername, + out GXBCCollection aP3_Gxm2rootcol) + { + this.AV6invoicedate = aP0_invoicedate; + this.AV5CustomerId = aP1_CustomerId; + this.AV7Customername = aP2_Customername; + this.Gxm2rootcol = new GXBCCollection(context, "Invoice", "TestRestProcs"); + initialize(); + ExecuteImpl(); + aP3_Gxm2rootcol = this.Gxm2rootcol; + } + + public GXBCCollection executeUdp(DateTime aP0_invoicedate, + short aP1_CustomerId, + string aP2_Customername) + { + execute(aP0_invoicedate, aP1_CustomerId, aP2_Customername, out aP3_Gxm2rootcol); + return Gxm2rootcol; + } + + public void executeSubmit(DateTime aP0_invoicedate, + short aP1_CustomerId, + string aP2_Customername, + out GXBCCollection aP3_Gxm2rootcol) + { + this.AV6invoicedate = aP0_invoicedate; + this.AV5CustomerId = aP1_CustomerId; + this.AV7Customername = aP2_Customername; + this.Gxm2rootcol = new GXBCCollection(context, "Invoice", "TestRestProcs"); + SubmitImpl(); + aP3_Gxm2rootcol = this.Gxm2rootcol; + } + + protected override void ExecutePrivate() + { + /* GeneXus formulas */ + /* Output device settings */ + Gxm1invoice = new SdtInvoice(context); + Gxm2rootcol.Add(Gxm1invoice, 0); + Gxm1invoice.gxTpr_Invoiceid = 1; + Gxm1invoice.gxTpr_Invoicedate = context.localUtil.YMDToD(2024, 1, 1); + Gxm1invoice.gxTpr_Customerid = 1; + Gxm3invoice_level = new SdtInvoice_Level(context); + Gxm1invoice.gxTpr_Level.Add(Gxm3invoice_level, 0); + Gxm3invoice_level.gxTpr_Invoicelevelid = 1; + Gxm3invoice_level.gxTpr_Productid = 1; + Gxm3invoice_level.gxTpr_Invoicelevelqty = 10; + + + Gxm1invoice = new SdtInvoice(context); + Gxm2rootcol.Add(Gxm1invoice, 0); + Gxm1invoice.gxTpr_Invoiceid = 2; + Gxm1invoice.gxTpr_Invoicedate = context.localUtil.YMDToD(2024, 2, 2); + Gxm1invoice.gxTpr_Customerid = 2; + Gxm3invoice_level = new SdtInvoice_Level(context); + Gxm1invoice.gxTpr_Level.Add(Gxm3invoice_level, 0); + Gxm3invoice_level.gxTpr_Invoicelevelid = 2; + Gxm3invoice_level.gxTpr_Productid = 2; + Gxm3invoice_level.gxTpr_Invoicelevelqty = 20; + cleanup(); + } + + public override void cleanup() + { + CloseCursors(); + if (IsMain) + { + context.CloseConnections(); + } + ExitApp(); + } + + public override void initialize() + { + Gxm1invoice = new SdtInvoice(context); + Gxm3invoice_level = new SdtInvoice_Level(context); + /* GeneXus formulas. */ + } + + private short AV5CustomerId; + private string AV7Customername; + private DateTime AV6invoicedate; + private GXBCCollection Gxm2rootcol; + private SdtInvoice Gxm1invoice; + private SdtInvoice_Level Gxm3invoice_level; + private GXBCCollection aP3_Gxm2rootcol; + } + +} diff --git a/dotnet/test/DotNetCoreWebUnitTest/apps/getbccollection.svc b/dotnet/test/DotNetCoreWebUnitTest/apps/getbccollection.svc new file mode 100644 index 000000000..e829f0c25 --- /dev/null +++ b/dotnet/test/DotNetCoreWebUnitTest/apps/getbccollection.svc @@ -0,0 +1 @@ +<%@ServiceHost Service= "GeneXus.Programs.apps.getbccollection,getbccollection" %> diff --git a/dotnet/test/DotNetCoreWebUnitTest/apps/getcollection.cs b/dotnet/test/DotNetCoreWebUnitTest/apps/getcollection.cs new file mode 100644 index 000000000..9c3c8903c --- /dev/null +++ b/dotnet/test/DotNetCoreWebUnitTest/apps/getcollection.cs @@ -0,0 +1,81 @@ +using GeneXus.Application; +using GeneXus.Data.NTier; +using GeneXus.Procedure; +using GeneXus.Utils; +namespace GeneXus.Programs.apps +{ + public class getcollection : GXProcedure + { + public getcollection( ) + { + context = new GxContext( ); + DataStoreUtil.LoadDataStores( context); + IsMain = true; + context.SetDefaultTheme("FromString", true); + } + + public getcollection( IGxContext context ) + { + this.context = context; + IsMain = false; + } + + public void execute( out short aP0_CliType , + out GxSimpleCollection aP1_CliCode ) + { + this.clitype = 0 ; + this.cliCod = new GxSimpleCollection() ; + initialize(); + ExecuteImpl(); + aP0_CliType=this.clitype; + aP1_CliCode=this.cliCod; + } + + public GxSimpleCollection executeUdp( out short aP0_CliType ) + { + execute(out aP0_CliType, out aP1_CliCode); + return cliCod ; + } + + public void executeSubmit( out short aP0_CliType , + out GxSimpleCollection aP1_CliCode ) + { + this.clitype = 0 ; + this.cliCod = new GxSimpleCollection() ; + SubmitImpl(); + aP0_CliType=this.clitype; + aP1_CliCode=this.cliCod; + } + + protected override void ExecutePrivate( ) + { + /* GeneXus formulas */ + /* Output device settings */ + clitype = 1; + cliCod.Add(1, 0); + cliCod.Add(2, 0); + this.cleanup(); + } + + public override void cleanup( ) + { + CloseCursors(); + if ( IsMain ) + { + context.CloseConnections(); + } + ExitApp(); + } + + public override void initialize( ) + { + cliCod = new GxSimpleCollection(); + + } + + private short clitype ; + private GxSimpleCollection cliCod ; + private GxSimpleCollection aP1_CliCode ; + } + +} diff --git a/dotnet/test/DotNetCoreWebUnitTest/apps/getcollection.svc b/dotnet/test/DotNetCoreWebUnitTest/apps/getcollection.svc new file mode 100644 index 000000000..b2a811c66 --- /dev/null +++ b/dotnet/test/DotNetCoreWebUnitTest/apps/getcollection.svc @@ -0,0 +1 @@ +<%@ServiceHost Service= "GeneXus.Programs.apps.getcollection,apps.getcollection" %> diff --git a/dotnet/test/DotNetCoreWebUnitTest/apps/getsdtcollection.cs b/dotnet/test/DotNetCoreWebUnitTest/apps/getsdtcollection.cs new file mode 100644 index 000000000..565ae02b3 --- /dev/null +++ b/dotnet/test/DotNetCoreWebUnitTest/apps/getsdtcollection.cs @@ -0,0 +1,360 @@ +using System; +using GeneXus.Application; +using GeneXus.Data.NTier; +using GeneXus.Http.Server; +using GeneXus.Procedure; +using GeneXus.Utils; +using GeneXus.XML; +namespace GeneXus.Programs.apps +{ + public class getsdtcollection : GXWebProcedure + { + public override void webExecute( ) + { + context.SetDefaultTheme("GeneXusXEv2", false); + initialize(); + AV10CustomerSdtList = new GXBaseCollection( context, "CustomerSdtSimple", "TestRestProcs") ; + if ( ! context.isAjaxRequest( ) ) + { + GXSoapHTTPResponse.AppendHeader("Content-type", "text/xml;charset=utf-8"); + } + if ( StringUtil.StrCmp(StringUtil.Lower( GXSoapHTTPRequest.Method), "get") == 0 ) + { + if ( StringUtil.StrCmp(StringUtil.Lower( GXSoapHTTPRequest.QueryString), "wsdl") == 0 ) + { + GXSoapXMLWriter.OpenResponse(GXSoapHTTPResponse); + GXSoapXMLWriter.WriteStartDocument("utf-8", 0); + GXSoapXMLWriter.WriteStartElement("definitions"); + GXSoapXMLWriter.WriteAttribute("name", "GetCustomersTest"); + GXSoapXMLWriter.WriteAttribute("targetNamespace", "TestRestProcs"); + GXSoapXMLWriter.WriteAttribute("xmlns:wsdlns", "TestRestProcs"); + GXSoapXMLWriter.WriteAttribute("xmlns:soap", "http://schemas.xmlsoap.org/wsdl/soap/"); + GXSoapXMLWriter.WriteAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema"); + GXSoapXMLWriter.WriteAttribute("xmlns", "http://schemas.xmlsoap.org/wsdl/"); + GXSoapXMLWriter.WriteAttribute("xmlns:tns", "TestRestProcs"); + GXSoapXMLWriter.WriteStartElement("types"); + GXSoapXMLWriter.WriteStartElement("schema"); + GXSoapXMLWriter.WriteAttribute("targetNamespace", "TestRestProcs"); + GXSoapXMLWriter.WriteAttribute("xmlns", "http://www.w3.org/2001/XMLSchema"); + GXSoapXMLWriter.WriteAttribute("xmlns:SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"); + GXSoapXMLWriter.WriteAttribute("elementFormDefault", "qualified"); + GXSoapXMLWriter.WriteStartElement("complexType"); + GXSoapXMLWriter.WriteAttribute("name", "ArrayOfCustomerSdtSimple"); + GXSoapXMLWriter.WriteStartElement("sequence"); + GXSoapXMLWriter.WriteStartElement("element"); + GXSoapXMLWriter.WriteAttribute("minOccurs", "0"); + GXSoapXMLWriter.WriteAttribute("maxOccurs", "unbounded"); + GXSoapXMLWriter.WriteAttribute("name", "CustomerSdtSimple"); + GXSoapXMLWriter.WriteAttribute("type", "tns:CustomerSdtSimple"); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteStartElement("complexType"); + GXSoapXMLWriter.WriteAttribute("name", "CustomerSdtSimple"); + GXSoapXMLWriter.WriteStartElement("sequence"); + GXSoapXMLWriter.WriteStartElement("element"); + GXSoapXMLWriter.WriteAttribute("name", "CustomerId"); + GXSoapXMLWriter.WriteAttribute("type", "xsd:short"); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteStartElement("element"); + GXSoapXMLWriter.WriteAttribute("name", "CustomerName"); + GXSoapXMLWriter.WriteAttribute("type", "xsd:string"); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteStartElement("element"); + GXSoapXMLWriter.WriteAttribute("name", "CustomerBirthDate"); + GXSoapXMLWriter.WriteAttribute("type", "xsd:date"); + GXSoapXMLWriter.WriteAttribute("nillable", "true"); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteStartElement("element"); + GXSoapXMLWriter.WriteAttribute("name", "CustomerPayDate"); + GXSoapXMLWriter.WriteAttribute("type", "xsd:dateTime"); + GXSoapXMLWriter.WriteAttribute("nillable", "true"); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteStartElement("element"); + GXSoapXMLWriter.WriteAttribute("name", "GetCustomersTest.Execute"); + GXSoapXMLWriter.WriteStartElement("complexType"); + GXSoapXMLWriter.WriteStartElement("sequence"); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteStartElement("element"); + GXSoapXMLWriter.WriteAttribute("name", "GetCustomersTest.ExecuteResponse"); + GXSoapXMLWriter.WriteStartElement("complexType"); + GXSoapXMLWriter.WriteStartElement("sequence"); + GXSoapXMLWriter.WriteElement("element", ""); + GXSoapXMLWriter.WriteAttribute("minOccurs", "1"); + GXSoapXMLWriter.WriteAttribute("maxOccurs", "1"); + GXSoapXMLWriter.WriteAttribute("name", "Customersdtlist"); + GXSoapXMLWriter.WriteAttribute("type", "tns:ArrayOfCustomerSdtSimple"); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteStartElement("message"); + GXSoapXMLWriter.WriteAttribute("name", "GetCustomersTest.ExecuteSoapIn"); + GXSoapXMLWriter.WriteElement("part", ""); + GXSoapXMLWriter.WriteAttribute("name", "parameters"); + GXSoapXMLWriter.WriteAttribute("element", "tns:GetCustomersTest.Execute"); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteStartElement("message"); + GXSoapXMLWriter.WriteAttribute("name", "GetCustomersTest.ExecuteSoapOut"); + GXSoapXMLWriter.WriteElement("part", ""); + GXSoapXMLWriter.WriteAttribute("name", "parameters"); + GXSoapXMLWriter.WriteAttribute("element", "tns:GetCustomersTest.ExecuteResponse"); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteStartElement("portType"); + GXSoapXMLWriter.WriteAttribute("name", "GetCustomersTestSoapPort"); + GXSoapXMLWriter.WriteStartElement("operation"); + GXSoapXMLWriter.WriteAttribute("name", "Execute"); + GXSoapXMLWriter.WriteElement("input", ""); + GXSoapXMLWriter.WriteAttribute("message", "wsdlns:"+"GetCustomersTest.ExecuteSoapIn"); + GXSoapXMLWriter.WriteElement("output", ""); + GXSoapXMLWriter.WriteAttribute("message", "wsdlns:"+"GetCustomersTest.ExecuteSoapOut"); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteStartElement("binding"); + GXSoapXMLWriter.WriteAttribute("name", "GetCustomersTestSoapBinding"); + GXSoapXMLWriter.WriteAttribute("type", "wsdlns:"+"GetCustomersTestSoapPort"); + GXSoapXMLWriter.WriteElement("soap:binding", ""); + GXSoapXMLWriter.WriteAttribute("style", "document"); + GXSoapXMLWriter.WriteAttribute("transport", "http://schemas.xmlsoap.org/soap/http"); + GXSoapXMLWriter.WriteStartElement("operation"); + GXSoapXMLWriter.WriteAttribute("name", "Execute"); + GXSoapXMLWriter.WriteElement("soap:operation", ""); + GXSoapXMLWriter.WriteAttribute("soapAction", "TestRestProcsaction/"+"AGETCUSTOMERSTEST.Execute"); + GXSoapXMLWriter.WriteStartElement("input"); + GXSoapXMLWriter.WriteElement("soap:body", ""); + GXSoapXMLWriter.WriteAttribute("use", "literal"); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteStartElement("output"); + GXSoapXMLWriter.WriteElement("soap:body", ""); + GXSoapXMLWriter.WriteAttribute("use", "literal"); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteStartElement("service"); + GXSoapXMLWriter.WriteAttribute("name", "GetCustomersTest"); + GXSoapXMLWriter.WriteStartElement("port"); + GXSoapXMLWriter.WriteAttribute("name", "GetCustomersTestSoapPort"); + GXSoapXMLWriter.WriteAttribute("binding", "wsdlns:"+"GetCustomersTestSoapBinding"); + GXSoapXMLWriter.WriteElement("soap:address", ""); + GXSoapXMLWriter.WriteAttribute("location", "http://"+context.GetServerName( )+((context.GetServerPort( )>0)&&(context.GetServerPort( )!=80)&&(context.GetServerPort( )!=443) ? ":"+StringUtil.LTrim( StringUtil.Str( (decimal)(context.GetServerPort( )), 6, 0)) : "")+context.GetScriptPath( )+"getcustomerstest.aspx"); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.Close(); + return ; + } + else + { + currSoapErr = (short)(-20000); + currSoapErrmsg = "No SOAP request found. Call " + "http://" + context.GetServerName( ) + ((context.GetServerPort( )>0)&&(context.GetServerPort( )!=80)&&(context.GetServerPort( )!=443) ? ":"+StringUtil.LTrim( StringUtil.Str( (decimal)(context.GetServerPort( )), 6, 0)) : "") + context.GetScriptPath( ) + "getcustomerstest.aspx" + "?wsdl to get the WSDL."; + } + } + if ( currSoapErr == 0 ) + { + GXSoapXMLReader.OpenRequest(GXSoapHTTPRequest); + GXSoapXMLReader.ReadExternalEntities = 0; + GXSoapXMLReader.IgnoreComments = 1; + GXSoapError = GXSoapXMLReader.Read(); + while ( GXSoapError > 0 ) + { + if ( StringUtil.StringSearch( GXSoapXMLReader.Name, "Envelope", 1) > 0 ) + { + this.SetPrefixesFromReader( GXSoapXMLReader); + } + if ( StringUtil.StringSearch( GXSoapXMLReader.Name, "Body", 1) > 0 ) + { + this.SetPrefixesFromReader( GXSoapXMLReader); + if (true) break; + } + GXSoapError = GXSoapXMLReader.Read(); + } + if ( GXSoapError > 0 ) + { + GXSoapError = GXSoapXMLReader.Read(); + if ( GXSoapError > 0 ) + { + this.SetPrefixesFromReader( GXSoapXMLReader); + currMethod = GXSoapXMLReader.Name; + if ( ( StringUtil.StringSearch( currMethod+"&", "Execute&", 1) > 0 ) || ( currSoapErr != 0 ) ) + { + if ( currSoapErr == 0 ) + { + AV10CustomerSdtList = new GXBaseCollection( context, "CustomerSdtSimple", "TestRestProcs"); + } + } + else + { + currSoapErr = (short)(-20002); + currSoapErrmsg = "Wrong method called. Expected method: " + "Execute"; + } + } + } + GXSoapXMLReader.Close(); + } + if ( currSoapErr == 0 ) + { + if ( GXSoapError < 0 ) + { + currSoapErr = (short)(GXSoapError*-1); + currSoapErrmsg = context.sSOAPErrMsg; + } + else + { + if ( GXSoapXMLReader.ErrCode > 0 ) + { + currSoapErr = (short)(GXSoapXMLReader.ErrCode*-1); + currSoapErrmsg = GXSoapXMLReader.ErrDescription; + } + else + { + if ( GXSoapError == 0 ) + { + currSoapErr = (short)(-20001); + currSoapErrmsg = "Malformed SOAP message."; + } + else + { + currSoapErr = 0; + currSoapErrmsg = "No error."; + } + } + } + } + if ( currSoapErr == 0 ) + { + ExecutePrivate(); + } + context.CloseConnections(); + GXSoapXMLWriter.OpenResponse(GXSoapHTTPResponse); + GXSoapXMLWriter.WriteStartDocument("utf-8", 0); + GXSoapXMLWriter.WriteStartElement("SOAP-ENV:Envelope"); + GXSoapXMLWriter.WriteAttribute("xmlns:SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"); + GXSoapXMLWriter.WriteAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema"); + GXSoapXMLWriter.WriteAttribute("xmlns:SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"); + GXSoapXMLWriter.WriteAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); + if ( ( StringUtil.StringSearch( currMethod+"&", "Execute&", 1) > 0 ) || ( currSoapErr != 0 ) ) + { + GXSoapXMLWriter.WriteStartElement("SOAP-ENV:Body"); + GXSoapXMLWriter.WriteStartElement("GetCustomersTest.ExecuteResponse"); + GXSoapXMLWriter.WriteAttribute("xmlns", "TestRestProcs"); + if ( currSoapErr == 0 ) + { + if ( AV10CustomerSdtList != null ) + { + AV10CustomerSdtList.writexmlcollection(GXSoapXMLWriter, "Customersdtlist", "TestRestProcs", "CustomerSdtSimple", "TestRestProcs"); + } + } + else + { + GXSoapXMLWriter.WriteStartElement("SOAP-ENV:Fault"); + GXSoapXMLWriter.WriteElement("faultcode", "SOAP-ENV:Client"); + GXSoapXMLWriter.WriteElement("faultstring", currSoapErrmsg); + GXSoapXMLWriter.WriteElement("detail", StringUtil.Trim( StringUtil.Str( (decimal)(currSoapErr), 10, 0))); + GXSoapXMLWriter.WriteEndElement(); + } + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.WriteEndElement(); + } + GXSoapXMLWriter.WriteEndElement(); + GXSoapXMLWriter.Close(); + cleanup(); + } + + public getsdtcollection( ) + { + context = new GxContext( ); + DataStoreUtil.LoadDataStores( context); + IsMain = true; + context.SetDefaultTheme("GeneXusXEv2", false); + } + + public getsdtcollection( IGxContext context ) + { + this.context = context; + IsMain = false; + } + + public void execute( out GXBaseCollection aP0_CustomerSdtList ) + { + this.AV10CustomerSdtList = new GXBaseCollection( context, "CustomerSdtSimple", "TestRestProcs") ; + initialize(); + ExecuteImpl(); + aP0_CustomerSdtList=this.AV10CustomerSdtList; + } + + public GXBaseCollection executeUdp( ) + { + execute(out aP0_CustomerSdtList); + return AV10CustomerSdtList ; + } + + public void executeSubmit( out GXBaseCollection aP0_CustomerSdtList ) + { + this.AV10CustomerSdtList = new GXBaseCollection( context, "CustomerSdtSimple", "TestRestProcs") ; + SubmitImpl(); + aP0_CustomerSdtList=this.AV10CustomerSdtList; + } + + protected override void ExecutePrivate( ) + { + /* GeneXus formulas */ + /* Output device settings */ + AV9CustomerSdt.gxTpr_Customerid = 1; + AV9CustomerSdt.gxTpr_Customername = "CustomerName"; + AV9CustomerSdt.gxTpr_Customerbirthdate = DateTimeUtil.Today( context); + GXt_dtime1 = DateTimeUtil.ResetTime( DateTimeUtil.Today( context) ) ; + AV9CustomerSdt.gxTpr_Customerpaydate = GXt_dtime1; + AV10CustomerSdtList.Add(AV9CustomerSdt, 0); + AV9CustomerSdt = new SdtCustomerSdtSimple(context); + if ( context.WillRedirect( ) ) + { + context.Redirect( context.wjLoc ); + context.wjLoc = ""; + } + cleanup(); + } + + public override void cleanup( ) + { + CloseCursors(); + base.cleanup(); + if ( IsMain ) + { + context.CloseConnections(); + } + ExitApp(); + } + + public override void initialize( ) + { + GXSoapHTTPRequest = new GxSoapRequest(context) ; + GXSoapXMLReader = new GXXMLReader(context.GetPhysicalPath()); + GXSoapHTTPResponse = new GxHttpResponse(context) ; + GXSoapXMLWriter = new GXXMLWriter(context.GetPhysicalPath()); + currSoapErrmsg = ""; + currMethod = ""; + AV9CustomerSdt = new SdtCustomerSdtSimple(context); + GXt_dtime1 = (DateTime)(DateTime.MinValue); + /* GeneXus formulas. */ + } + + private short GXSoapError ; + private short currSoapErr ; + private string currSoapErrmsg ; + private string currMethod ; + private DateTime GXt_dtime1 ; + private GXXMLReader GXSoapXMLReader ; + private GXXMLWriter GXSoapXMLWriter ; + private GxSoapRequest GXSoapHTTPRequest ; + private GxHttpResponse GXSoapHTTPResponse ; + private GXBaseCollection AV10CustomerSdtList ; + private SdtCustomerSdtSimple AV9CustomerSdt ; + private GXBaseCollection aP0_CustomerSdtList ; + } + +} diff --git a/dotnet/test/DotNetCoreWebUnitTest/apps/getsdtcollection.svc b/dotnet/test/DotNetCoreWebUnitTest/apps/getsdtcollection.svc new file mode 100644 index 000000000..ff43c2880 --- /dev/null +++ b/dotnet/test/DotNetCoreWebUnitTest/apps/getsdtcollection.svc @@ -0,0 +1 @@ +<%@ServiceHost Service= "GeneXus.Programs.apps.getsdtcollection,apps.getsdtcollection" %> diff --git a/dotnet/test/DotNetCoreWebUnitTest/apps/type_SdtCustomerSdtSimple.cs b/dotnet/test/DotNetCoreWebUnitTest/apps/type_SdtCustomerSdtSimple.cs new file mode 100644 index 000000000..f9c821f73 --- /dev/null +++ b/dotnet/test/DotNetCoreWebUnitTest/apps/type_SdtCustomerSdtSimple.cs @@ -0,0 +1,329 @@ +/* + File: type_SdtCustomerSdtSimple + Description: CustomerSdtSimple + Author: Nemo 🐠 for C# (.NET) version 18.0.10.183411 + Program type: Callable routine + Main DBMS: +*/ +using System; +using System.Collections; +using System.Runtime.Serialization; +using System.Xml.Serialization; +using GeneXus.Application; +using GeneXus.Utils; + + +namespace GeneXus.Programs.apps +{ + [XmlRoot(ElementName="CustomerSdtSimple")] + [XmlType(TypeName="CustomerSdtSimple" , Namespace="TestRestProcs" )] + [Serializable] + public class SdtCustomerSdtSimple : GxUserType + { + public SdtCustomerSdtSimple( ) + { + /* Constructor for serialization */ + gxTv_SdtCustomerSdtSimple_Customername = ""; + + gxTv_SdtCustomerSdtSimple_Customerpaydate = (DateTime)(DateTime.MinValue); + + } + + public SdtCustomerSdtSimple(IGxContext context) + { + this.context = context; + initialize(); + } + + #region Json + private static Hashtable mapper; + public override string JsonMap(string value) + { + if (mapper == null) + { + mapper = new Hashtable(); + } + return (string)mapper[value]; ; + } + + public override void ToJSON() + { + ToJSON(true) ; + return; + } + + public override void ToJSON(bool includeState) + { + AddObjectProperty("CustomerId", gxTpr_Customerid, false); + + + AddObjectProperty("CustomerName", gxTpr_Customername, false); + + + sDateCnv = ""; + sNumToPad = StringUtil.Trim(StringUtil.Str((decimal)(DateTimeUtil.Year(gxTpr_Customerbirthdate)), 10, 0)); + sDateCnv = sDateCnv + StringUtil.Substring("0000", 1, 4-StringUtil.Len(sNumToPad)) + sNumToPad; + sDateCnv = sDateCnv + "-"; + sNumToPad = StringUtil.Trim(StringUtil.Str((decimal)(DateTimeUtil.Month(gxTpr_Customerbirthdate)), 10, 0)); + sDateCnv = sDateCnv + StringUtil.Substring("00", 1, 2-StringUtil.Len(sNumToPad)) + sNumToPad; + sDateCnv = sDateCnv + "-"; + sNumToPad = StringUtil.Trim(StringUtil.Str((decimal)(DateTimeUtil.Day(gxTpr_Customerbirthdate)), 10, 0)); + sDateCnv = sDateCnv + StringUtil.Substring("00", 1, 2-StringUtil.Len(sNumToPad)) + sNumToPad; + AddObjectProperty("CustomerBirthDate", sDateCnv, false); + + + + datetime_STZ = gxTpr_Customerpaydate; + sDateCnv = ""; + sNumToPad = StringUtil.Trim(StringUtil.Str((decimal)(DateTimeUtil.Year(datetime_STZ)), 10, 0)); + sDateCnv = sDateCnv + StringUtil.Substring("0000", 1, 4-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv = sDateCnv + "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str((decimal)(DateTimeUtil.Month(datetime_STZ)), 10, 0)); + sDateCnv = sDateCnv + StringUtil.Substring("00", 1, 2-StringUtil.Len(sNumToPad)) + sNumToPad; + sDateCnv = sDateCnv + "-"; + sNumToPad = StringUtil.Trim(StringUtil.Str((decimal)(DateTimeUtil.Day(datetime_STZ)), 10, 0)); + sDateCnv = sDateCnv + StringUtil.Substring("00", 1, 2-StringUtil.Len(sNumToPad)) + sNumToPad; + sDateCnv = sDateCnv + "T"; + sNumToPad = StringUtil.Trim(StringUtil.Str((decimal)(DateTimeUtil.Hour(datetime_STZ)), 10, 0)); + sDateCnv = sDateCnv + StringUtil.Substring("00", 1, 2-StringUtil.Len(sNumToPad)) + sNumToPad; + sDateCnv = sDateCnv + ":"; + sNumToPad = StringUtil.Trim(StringUtil.Str((decimal)(DateTimeUtil.Minute(datetime_STZ)), 10, 0)); + sDateCnv = sDateCnv + StringUtil.Substring("00", 1, 2-StringUtil.Len(sNumToPad)) + sNumToPad; + sDateCnv = sDateCnv + ":"; + sNumToPad = StringUtil.Trim(StringUtil.Str((decimal)(DateTimeUtil.Second(datetime_STZ)), 10, 0)); + sDateCnv = sDateCnv + StringUtil.Substring("00", 1, 2-StringUtil.Len(sNumToPad)) + sNumToPad; + AddObjectProperty("CustomerPayDate", sDateCnv, false); + + + return; + } + #endregion + + #region Properties + + [SoapElement(ElementName="CustomerId")] + [XmlElement(ElementName="CustomerId")] + public short gxTpr_Customerid + { + get { + return gxTv_SdtCustomerSdtSimple_Customerid; + } + set { + gxTv_SdtCustomerSdtSimple_Customerid = value; + SetDirty("Customerid"); + } + } + + + + + [SoapElement(ElementName="CustomerName")] + [XmlElement(ElementName="CustomerName")] + public string gxTpr_Customername + { + get { + return gxTv_SdtCustomerSdtSimple_Customername; + } + set { + gxTv_SdtCustomerSdtSimple_Customername = value; + SetDirty("Customername"); + } + } + + + + [SoapElement(ElementName="CustomerBirthDate")] + [XmlElement(ElementName="CustomerBirthDate" , IsNullable=true)] + public string gxTpr_Customerbirthdate_Nullable + { + get { + if ( gxTv_SdtCustomerSdtSimple_Customerbirthdate == DateTime.MinValue) + return null; + return new GxDateString(gxTv_SdtCustomerSdtSimple_Customerbirthdate).value ; + } + set { + gxTv_SdtCustomerSdtSimple_Customerbirthdate = DateTimeUtil.CToD2(value); + } + } + + [XmlIgnore] + public DateTime gxTpr_Customerbirthdate + { + get { + return gxTv_SdtCustomerSdtSimple_Customerbirthdate; + } + set { + gxTv_SdtCustomerSdtSimple_Customerbirthdate = value; + SetDirty("Customerbirthdate"); + } + } + + + [SoapElement(ElementName="CustomerPayDate")] + [XmlElement(ElementName="CustomerPayDate" , IsNullable=true)] + public string gxTpr_Customerpaydate_Nullable + { + get { + if ( gxTv_SdtCustomerSdtSimple_Customerpaydate == DateTime.MinValue) + return null; + return new GxDatetimeString(gxTv_SdtCustomerSdtSimple_Customerpaydate).value ; + } + set { + gxTv_SdtCustomerSdtSimple_Customerpaydate = DateTimeUtil.CToD2(value); + } + } + + [XmlIgnore] + public DateTime gxTpr_Customerpaydate + { + get { + return gxTv_SdtCustomerSdtSimple_Customerpaydate; + } + set { + gxTv_SdtCustomerSdtSimple_Customerpaydate = value; + SetDirty("Customerpaydate"); + } + } + + + public override bool ShouldSerializeSdtJson() + { + return true; + } + + + + #endregion + + #region Static Type Properties + + [XmlIgnore] + private static GXTypeInfo _typeProps; + protected override GXTypeInfo TypeInfo { get { return _typeProps; } set { _typeProps = value; } } + + #endregion + + #region Initialization + + public void initialize( ) + { + gxTv_SdtCustomerSdtSimple_Customername = ""; + + gxTv_SdtCustomerSdtSimple_Customerpaydate = (DateTime)(DateTime.MinValue); + datetime_STZ = (DateTime)(DateTime.MinValue); + sDateCnv = ""; + sNumToPad = ""; + return ; + } + + + + #endregion + + #region Declaration + + protected string sDateCnv ; + protected string sNumToPad ; + protected DateTime datetime_STZ ; + + protected short gxTv_SdtCustomerSdtSimple_Customerid; + + + protected string gxTv_SdtCustomerSdtSimple_Customername; + + + protected DateTime gxTv_SdtCustomerSdtSimple_Customerbirthdate; + + + protected DateTime gxTv_SdtCustomerSdtSimple_Customerpaydate; + + + + #endregion + } + #region Rest interface + [GxJsonSerialization("default")] + [DataContract(Name=@"CustomerSdtSimple", Namespace="TestRestProcs")] + public class SdtCustomerSdtSimple_RESTInterface : GxGenericCollectionItem, System.Web.SessionState.IRequiresSessionState + { + public SdtCustomerSdtSimple_RESTInterface( ) : base() + { + } + + public SdtCustomerSdtSimple_RESTInterface( SdtCustomerSdtSimple psdt ) : base(psdt) + { + } + + #region Rest Properties + [DataMember(Name="CustomerId", Order=0)] + public short gxTpr_Customerid + { + get { + return sdt.gxTpr_Customerid; + + } + set { + sdt.gxTpr_Customerid = value; + } + } + + [DataMember(Name="CustomerName", Order=1)] + public string gxTpr_Customername + { + get { + return StringUtil.RTrim( sdt.gxTpr_Customername); + + } + set { + sdt.gxTpr_Customername = value; + } + } + + [DataMember(Name="CustomerBirthDate", Order=2)] + public string gxTpr_Customerbirthdate + { + get { + return DateTimeUtil.DToC2( sdt.gxTpr_Customerbirthdate); + + } + set { + sdt.gxTpr_Customerbirthdate = DateTimeUtil.CToD2(value); + } + } + + [DataMember(Name="CustomerPayDate", Order=3)] + public string gxTpr_Customerpaydate + { + get { + return DateTimeUtil.TToC2( sdt.gxTpr_Customerpaydate,context); + + } + set { + sdt.gxTpr_Customerpaydate = DateTimeUtil.CToT2(value,context); + } + } + + + #endregion + + public SdtCustomerSdtSimple sdt + { + get { + return (SdtCustomerSdtSimple)Sdt; + } + set { + Sdt = value; + } + } + + [OnDeserializing] + void checkSdt( StreamingContext ctx ) + { + if ( sdt == null ) + { + sdt = new SdtCustomerSdtSimple() ; + } + } + } + #endregion +} \ No newline at end of file diff --git a/dotnet/test/DotNetCoreWebUnitTest/apps/type_SdtInvoice.cs b/dotnet/test/DotNetCoreWebUnitTest/apps/type_SdtInvoice.cs new file mode 100644 index 000000000..cc96aa01d --- /dev/null +++ b/dotnet/test/DotNetCoreWebUnitTest/apps/type_SdtInvoice.cs @@ -0,0 +1,983 @@ +using System; +using System.Collections; +using GeneXus.Utils; +using GeneXus.Resources; +using GeneXus.Application; +using GeneXus.Metadata; +using GeneXus.Cryptography; +using GeneXus.Encryption; +using GeneXus.Http.Client; +using System.Reflection; +using System.Xml.Serialization; +using System.Runtime.Serialization; +namespace GeneXus.Programs.apps +{ + [XmlRoot(ElementName = "Invoice" )] + [XmlType(TypeName = "Invoice" , Namespace = "TestRestProcs" )] + [Serializable] + public class SdtInvoice : GxSilentTrnSdt + { + public SdtInvoice( ) + { + } + + public SdtInvoice( IGxContext context ) + { + this.context = context; + constructorCallingAssembly = Assembly.GetEntryAssembly(); + initialize(); + } + + private static Hashtable mapper; + public override string JsonMap( string value ) + { + if ( mapper == null ) + { + mapper = new Hashtable(); + } + return (string)mapper[value]; ; + } + + public void Load( short AV5InvoiceId ) + { + IGxSilentTrn obj; + obj = getTransaction(); + obj.LoadKey(new Object[] {(short)AV5InvoiceId}); + return ; + } + + public void LoadStrParms( string sAV5InvoiceId ) + { + short AV5InvoiceId; + AV5InvoiceId = (short)(Math.Round(NumberUtil.Val( sAV5InvoiceId, "."), 18, MidpointRounding.ToEven)); + Load( AV5InvoiceId) ; + return ; + } + + public override Object[][] GetBCKey( ) + { + return (Object[][])(new Object[][]{new Object[]{"InvoiceId", typeof(short)}}) ; + } + + public override GXProperties GetMetadata( ) + { + GXProperties metadata = new GXProperties(); + metadata.Set("Name", "Invoice"); + metadata.Set("BT", "Invoice"); + metadata.Set("PK", "[ \"InvoiceId\" ]"); + metadata.Set("Levels", "[ \"Level\" ]"); + metadata.Set("Serial", "[ [ \"Same\",\"Invoice\",\"InvoiceLast\",\"InvoiceLevelId\",\"InvoiceId\",\"InvoiceId\" ] ]"); + metadata.Set("FKList", "[ { \"FK\":[ \"CustomerId\" ],\"FKMap\":[ ] } ]"); + metadata.Set("AllowInsert", "True"); + metadata.Set("AllowUpdate", "True"); + metadata.Set("AllowDelete", "True"); + return metadata ; + } + + public override GeneXus.Utils.GxStringCollection StateAttributes( ) + { + GeneXus.Utils.GxStringCollection state = new GeneXus.Utils.GxStringCollection(); + state.Add("gxTpr_Mode"); + state.Add("gxTpr_Initialized"); + state.Add("gxTpr_Invoiceid_Z"); + state.Add("gxTpr_Invoicedate_Z_Nullable"); + state.Add("gxTpr_Customerid_Z"); + state.Add("gxTpr_Customername_Z"); + state.Add("gxTpr_Invoicetotal_Z"); + state.Add("gxTpr_Invoicelast_Z"); + state.Add("gxTpr_Invoicetotal_N"); + return state ; + } + + public override void Copy( GxUserType source ) + { + SdtInvoice sdt; + sdt = (SdtInvoice)(source); + gxTv_SdtInvoice_Invoiceid = sdt.gxTv_SdtInvoice_Invoiceid ; + gxTv_SdtInvoice_Invoicedate = sdt.gxTv_SdtInvoice_Invoicedate ; + gxTv_SdtInvoice_Customerid = sdt.gxTv_SdtInvoice_Customerid ; + gxTv_SdtInvoice_Customername = sdt.gxTv_SdtInvoice_Customername ; + gxTv_SdtInvoice_Invoicetotal = sdt.gxTv_SdtInvoice_Invoicetotal ; + gxTv_SdtInvoice_Invoicelast = sdt.gxTv_SdtInvoice_Invoicelast ; + gxTv_SdtInvoice_Level = sdt.gxTv_SdtInvoice_Level ; + gxTv_SdtInvoice_Mode = sdt.gxTv_SdtInvoice_Mode ; + gxTv_SdtInvoice_Initialized = sdt.gxTv_SdtInvoice_Initialized ; + gxTv_SdtInvoice_Invoiceid_Z = sdt.gxTv_SdtInvoice_Invoiceid_Z ; + gxTv_SdtInvoice_Invoicedate_Z = sdt.gxTv_SdtInvoice_Invoicedate_Z ; + gxTv_SdtInvoice_Customerid_Z = sdt.gxTv_SdtInvoice_Customerid_Z ; + gxTv_SdtInvoice_Customername_Z = sdt.gxTv_SdtInvoice_Customername_Z ; + gxTv_SdtInvoice_Invoicetotal_Z = sdt.gxTv_SdtInvoice_Invoicetotal_Z ; + gxTv_SdtInvoice_Invoicelast_Z = sdt.gxTv_SdtInvoice_Invoicelast_Z ; + gxTv_SdtInvoice_Invoicetotal_N = sdt.gxTv_SdtInvoice_Invoicetotal_N ; + return ; + } + + public override void ToJSON( ) + { + ToJSON( true) ; + return ; + } + + public override void ToJSON( bool includeState ) + { + ToJSON( includeState, true) ; + return ; + } + + public override void ToJSON( bool includeState , + bool includeNonInitialized ) + { + AddObjectProperty("InvoiceId", gxTv_SdtInvoice_Invoiceid, false, includeNonInitialized); + sDateCnv = ""; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Year( gxTv_SdtInvoice_Invoicedate)), 10, 0)); + sDateCnv += StringUtil.Substring( "0000", 1, 4-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Month( gxTv_SdtInvoice_Invoicedate)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Day( gxTv_SdtInvoice_Invoicedate)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + AddObjectProperty("InvoiceDate", sDateCnv, false, includeNonInitialized); + AddObjectProperty("CustomerId", gxTv_SdtInvoice_Customerid, false, includeNonInitialized); + AddObjectProperty("CustomerName", gxTv_SdtInvoice_Customername, false, includeNonInitialized); + AddObjectProperty("InvoiceTotal", gxTv_SdtInvoice_Invoicetotal, false, includeNonInitialized); + AddObjectProperty("InvoiceTotal_N", gxTv_SdtInvoice_Invoicetotal_N, false, includeNonInitialized); + AddObjectProperty("InvoiceLast", gxTv_SdtInvoice_Invoicelast, false, includeNonInitialized); + if ( gxTv_SdtInvoice_Level != null ) + { + AddObjectProperty("Level", gxTv_SdtInvoice_Level, includeState, includeNonInitialized); + } + if ( includeState ) + { + AddObjectProperty("Mode", gxTv_SdtInvoice_Mode, false, includeNonInitialized); + AddObjectProperty("Initialized", gxTv_SdtInvoice_Initialized, false, includeNonInitialized); + AddObjectProperty("InvoiceId_Z", gxTv_SdtInvoice_Invoiceid_Z, false, includeNonInitialized); + sDateCnv = ""; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Year( gxTv_SdtInvoice_Invoicedate_Z)), 10, 0)); + sDateCnv += StringUtil.Substring( "0000", 1, 4-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Month( gxTv_SdtInvoice_Invoicedate_Z)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + sDateCnv += "-"; + sNumToPad = StringUtil.Trim( StringUtil.Str( (decimal)(DateTimeUtil.Day( gxTv_SdtInvoice_Invoicedate_Z)), 10, 0)); + sDateCnv += StringUtil.Substring( "00", 1, 2-StringUtil.Len( sNumToPad)) + sNumToPad; + AddObjectProperty("InvoiceDate_Z", sDateCnv, false, includeNonInitialized); + AddObjectProperty("CustomerId_Z", gxTv_SdtInvoice_Customerid_Z, false, includeNonInitialized); + AddObjectProperty("CustomerName_Z", gxTv_SdtInvoice_Customername_Z, false, includeNonInitialized); + AddObjectProperty("InvoiceTotal_Z", gxTv_SdtInvoice_Invoicetotal_Z, false, includeNonInitialized); + AddObjectProperty("InvoiceLast_Z", gxTv_SdtInvoice_Invoicelast_Z, false, includeNonInitialized); + AddObjectProperty("InvoiceTotal_N", gxTv_SdtInvoice_Invoicetotal_N, false, includeNonInitialized); + } + return ; + } + + public void UpdateDirties( SdtInvoice sdt ) + { + if ( sdt.IsDirty("InvoiceId") ) + { + sdtIsNull = 0; + gxTv_SdtInvoice_Invoiceid = sdt.gxTv_SdtInvoice_Invoiceid ; + } + if ( sdt.IsDirty("InvoiceDate") ) + { + sdtIsNull = 0; + gxTv_SdtInvoice_Invoicedate = sdt.gxTv_SdtInvoice_Invoicedate ; + } + if ( sdt.IsDirty("CustomerId") ) + { + sdtIsNull = 0; + gxTv_SdtInvoice_Customerid = sdt.gxTv_SdtInvoice_Customerid ; + } + if ( sdt.IsDirty("CustomerName") ) + { + sdtIsNull = 0; + gxTv_SdtInvoice_Customername = sdt.gxTv_SdtInvoice_Customername ; + } + if ( sdt.IsDirty("InvoiceTotal") ) + { + gxTv_SdtInvoice_Invoicetotal_N = (short)(sdt.gxTv_SdtInvoice_Invoicetotal_N); + sdtIsNull = 0; + gxTv_SdtInvoice_Invoicetotal = sdt.gxTv_SdtInvoice_Invoicetotal ; + } + if ( sdt.IsDirty("InvoiceLast") ) + { + sdtIsNull = 0; + gxTv_SdtInvoice_Invoicelast = sdt.gxTv_SdtInvoice_Invoicelast ; + } + if ( gxTv_SdtInvoice_Level != null ) + { + GXBCLevelCollection newCollectionLevel = sdt.gxTpr_Level; + SdtInvoice_Level currItemLevel; + SdtInvoice_Level newItemLevel; + short idx = 1; + while ( idx <= newCollectionLevel.Count ) + { + newItemLevel = ((SdtInvoice_Level)newCollectionLevel.Item(idx)); + currItemLevel = gxTv_SdtInvoice_Level.GetByKey(newItemLevel.gxTpr_Invoicelevelid); + if ( StringUtil.StrCmp(currItemLevel.gxTpr_Mode, "UPD") == 0 ) + { + currItemLevel.UpdateDirties(newItemLevel); + if ( StringUtil.StrCmp(newItemLevel.gxTpr_Mode, "DLT") == 0 ) + { + currItemLevel.gxTpr_Mode = "DLT"; + } + currItemLevel.gxTpr_Modified = 1; + } + else + { + gxTv_SdtInvoice_Level.Add(newItemLevel, 0); + } + idx = (short)(idx+1); + } + } + return ; + } + + [ SoapElement( ElementName = "InvoiceId" )] + [ XmlElement( ElementName = "InvoiceId" )] + public short gxTpr_Invoiceid + { + get { + return gxTv_SdtInvoice_Invoiceid ; + } + + set { + sdtIsNull = 0; + if ( gxTv_SdtInvoice_Invoiceid != value ) + { + gxTv_SdtInvoice_Mode = "INS"; + this.gxTv_SdtInvoice_Invoiceid_Z_SetNull( ); + this.gxTv_SdtInvoice_Invoicedate_Z_SetNull( ); + this.gxTv_SdtInvoice_Customerid_Z_SetNull( ); + this.gxTv_SdtInvoice_Customername_Z_SetNull( ); + this.gxTv_SdtInvoice_Invoicetotal_Z_SetNull( ); + this.gxTv_SdtInvoice_Invoicelast_Z_SetNull( ); + if ( gxTv_SdtInvoice_Level != null ) + { + GXBCLevelCollection collectionLevel = gxTv_SdtInvoice_Level; + SdtInvoice_Level currItemLevel; + short idx = 1; + while ( idx <= collectionLevel.Count ) + { + currItemLevel = ((SdtInvoice_Level)collectionLevel.Item(idx)); + currItemLevel.gxTpr_Mode = "INS"; + currItemLevel.gxTpr_Modified = 1; + idx = (short)(idx+1); + } + } + } + gxTv_SdtInvoice_Invoiceid = value; + SetDirty("Invoiceid"); + } + + } + + [ SoapElement( ElementName = "InvoiceDate" )] + [ XmlElement( ElementName = "InvoiceDate" , IsNullable=true )] + public string gxTpr_Invoicedate_Nullable + { + get { + if ( gxTv_SdtInvoice_Invoicedate == DateTime.MinValue) + return null; + return new GxDateString(gxTv_SdtInvoice_Invoicedate).value ; + } + + set { + sdtIsNull = 0; + if (String.IsNullOrEmpty(value) || value == GxDateString.NullValue ) + gxTv_SdtInvoice_Invoicedate = DateTime.MinValue; + else + gxTv_SdtInvoice_Invoicedate = DateTime.Parse( value); + } + + } + + [XmlIgnore] + public DateTime gxTpr_Invoicedate + { + get { + return gxTv_SdtInvoice_Invoicedate ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Invoicedate = value; + SetDirty("Invoicedate"); + } + + } + + [ SoapElement( ElementName = "CustomerId" )] + [ XmlElement( ElementName = "CustomerId" )] + public short gxTpr_Customerid + { + get { + return gxTv_SdtInvoice_Customerid ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Customerid = value; + SetDirty("Customerid"); + } + + } + + [ SoapElement( ElementName = "CustomerName" )] + [ XmlElement( ElementName = "CustomerName" )] + public string gxTpr_Customername + { + get { + return gxTv_SdtInvoice_Customername ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Customername = value; + SetDirty("Customername"); + } + + } + + [ SoapElement( ElementName = "InvoiceTotal" )] + [ XmlElement( ElementName = "InvoiceTotal" )] + public short gxTpr_Invoicetotal + { + get { + return gxTv_SdtInvoice_Invoicetotal ; + } + + set { + gxTv_SdtInvoice_Invoicetotal_N = 0; + sdtIsNull = 0; + gxTv_SdtInvoice_Invoicetotal = value; + SetDirty("Invoicetotal"); + } + + } + + public void gxTv_SdtInvoice_Invoicetotal_SetNull( ) + { + gxTv_SdtInvoice_Invoicetotal_N = 1; + gxTv_SdtInvoice_Invoicetotal = 0; + SetDirty("Invoicetotal"); + return ; + } + + public bool gxTv_SdtInvoice_Invoicetotal_IsNull( ) + { + return (gxTv_SdtInvoice_Invoicetotal_N==1) ; + } + + [ SoapElement( ElementName = "InvoiceLast" )] + [ XmlElement( ElementName = "InvoiceLast" )] + public short gxTpr_Invoicelast + { + get { + return gxTv_SdtInvoice_Invoicelast ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Invoicelast = value; + SetDirty("Invoicelast"); + } + + } + + [ SoapElement( ElementName = "Level" )] + [ XmlArray( ElementName = "Level" )] + [ XmlArrayItemAttribute( ElementName= "Invoice.Level" , IsNullable=false)] + public GXBCLevelCollection gxTpr_Level_GXBCLevelCollection + { + get { + if ( gxTv_SdtInvoice_Level == null ) + { + gxTv_SdtInvoice_Level = new GXBCLevelCollection( context, "Invoice.Level", "TestRestProcs"); + } + return gxTv_SdtInvoice_Level ; + } + + set { + if ( gxTv_SdtInvoice_Level == null ) + { + gxTv_SdtInvoice_Level = new GXBCLevelCollection( context, "Invoice.Level", "TestRestProcs"); + } + sdtIsNull = 0; + gxTv_SdtInvoice_Level = value; + } + + } + + [XmlIgnore] + public GXBCLevelCollection gxTpr_Level + { + get { + if ( gxTv_SdtInvoice_Level == null ) + { + gxTv_SdtInvoice_Level = new GXBCLevelCollection( context, "Invoice.Level", "TestRestProcs"); + } + sdtIsNull = 0; + return gxTv_SdtInvoice_Level ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Level = value; + SetDirty("Level"); + } + + } + + public void gxTv_SdtInvoice_Level_SetNull( ) + { + gxTv_SdtInvoice_Level = null; + SetDirty("Level"); + return ; + } + + public bool gxTv_SdtInvoice_Level_IsNull( ) + { + if ( gxTv_SdtInvoice_Level == null ) + { + return true ; + } + return false ; + } + + [ SoapElement( ElementName = "Mode" )] + [ XmlElement( ElementName = "Mode" )] + public string gxTpr_Mode + { + get { + return gxTv_SdtInvoice_Mode ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Mode = value; + SetDirty("Mode"); + } + + } + + public void gxTv_SdtInvoice_Mode_SetNull( ) + { + gxTv_SdtInvoice_Mode = ""; + SetDirty("Mode"); + return ; + } + + public bool gxTv_SdtInvoice_Mode_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "Initialized" )] + [ XmlElement( ElementName = "Initialized" )] + public short gxTpr_Initialized + { + get { + return gxTv_SdtInvoice_Initialized ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Initialized = value; + SetDirty("Initialized"); + } + + } + + public void gxTv_SdtInvoice_Initialized_SetNull( ) + { + gxTv_SdtInvoice_Initialized = 0; + SetDirty("Initialized"); + return ; + } + + public bool gxTv_SdtInvoice_Initialized_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "InvoiceId_Z" )] + [ XmlElement( ElementName = "InvoiceId_Z" )] + public short gxTpr_Invoiceid_Z + { + get { + return gxTv_SdtInvoice_Invoiceid_Z ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Invoiceid_Z = value; + SetDirty("Invoiceid_Z"); + } + + } + + public void gxTv_SdtInvoice_Invoiceid_Z_SetNull( ) + { + gxTv_SdtInvoice_Invoiceid_Z = 0; + SetDirty("Invoiceid_Z"); + return ; + } + + public bool gxTv_SdtInvoice_Invoiceid_Z_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "InvoiceDate_Z" )] + [ XmlElement( ElementName = "InvoiceDate_Z" , IsNullable=true )] + public string gxTpr_Invoicedate_Z_Nullable + { + get { + if ( gxTv_SdtInvoice_Invoicedate_Z == DateTime.MinValue) + return null; + return new GxDateString(gxTv_SdtInvoice_Invoicedate_Z).value ; + } + + set { + sdtIsNull = 0; + if (String.IsNullOrEmpty(value) || value == GxDateString.NullValue ) + gxTv_SdtInvoice_Invoicedate_Z = DateTime.MinValue; + else + gxTv_SdtInvoice_Invoicedate_Z = DateTime.Parse( value); + } + + } + + [XmlIgnore] + public DateTime gxTpr_Invoicedate_Z + { + get { + return gxTv_SdtInvoice_Invoicedate_Z ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Invoicedate_Z = value; + SetDirty("Invoicedate_Z"); + } + + } + + public void gxTv_SdtInvoice_Invoicedate_Z_SetNull( ) + { + gxTv_SdtInvoice_Invoicedate_Z = (DateTime)(DateTime.MinValue); + SetDirty("Invoicedate_Z"); + return ; + } + + public bool gxTv_SdtInvoice_Invoicedate_Z_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "CustomerId_Z" )] + [ XmlElement( ElementName = "CustomerId_Z" )] + public short gxTpr_Customerid_Z + { + get { + return gxTv_SdtInvoice_Customerid_Z ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Customerid_Z = value; + SetDirty("Customerid_Z"); + } + + } + + public void gxTv_SdtInvoice_Customerid_Z_SetNull( ) + { + gxTv_SdtInvoice_Customerid_Z = 0; + SetDirty("Customerid_Z"); + return ; + } + + public bool gxTv_SdtInvoice_Customerid_Z_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "CustomerName_Z" )] + [ XmlElement( ElementName = "CustomerName_Z" )] + public string gxTpr_Customername_Z + { + get { + return gxTv_SdtInvoice_Customername_Z ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Customername_Z = value; + SetDirty("Customername_Z"); + } + + } + + public void gxTv_SdtInvoice_Customername_Z_SetNull( ) + { + gxTv_SdtInvoice_Customername_Z = ""; + SetDirty("Customername_Z"); + return ; + } + + public bool gxTv_SdtInvoice_Customername_Z_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "InvoiceTotal_Z" )] + [ XmlElement( ElementName = "InvoiceTotal_Z" )] + public short gxTpr_Invoicetotal_Z + { + get { + return gxTv_SdtInvoice_Invoicetotal_Z ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Invoicetotal_Z = value; + SetDirty("Invoicetotal_Z"); + } + + } + + public void gxTv_SdtInvoice_Invoicetotal_Z_SetNull( ) + { + gxTv_SdtInvoice_Invoicetotal_Z = 0; + SetDirty("Invoicetotal_Z"); + return ; + } + + public bool gxTv_SdtInvoice_Invoicetotal_Z_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "InvoiceLast_Z" )] + [ XmlElement( ElementName = "InvoiceLast_Z" )] + public short gxTpr_Invoicelast_Z + { + get { + return gxTv_SdtInvoice_Invoicelast_Z ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Invoicelast_Z = value; + SetDirty("Invoicelast_Z"); + } + + } + + public void gxTv_SdtInvoice_Invoicelast_Z_SetNull( ) + { + gxTv_SdtInvoice_Invoicelast_Z = 0; + SetDirty("Invoicelast_Z"); + return ; + } + + public bool gxTv_SdtInvoice_Invoicelast_Z_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "InvoiceTotal_N" )] + [ XmlElement( ElementName = "InvoiceTotal_N" )] + public short gxTpr_Invoicetotal_N + { + get { + return gxTv_SdtInvoice_Invoicetotal_N ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Invoicetotal_N = value; + SetDirty("Invoicetotal_N"); + } + + } + + public void gxTv_SdtInvoice_Invoicetotal_N_SetNull( ) + { + gxTv_SdtInvoice_Invoicetotal_N = 0; + SetDirty("Invoicetotal_N"); + return ; + } + + public bool gxTv_SdtInvoice_Invoicetotal_N_IsNull( ) + { + return false ; + } + + [XmlIgnore] + private static GXTypeInfo _typeProps; + protected override GXTypeInfo TypeInfo + { + get { + return _typeProps ; + } + + set { + _typeProps = value ; + } + + } + + public void initialize( ) + { + sdtIsNull = 1; + gxTv_SdtInvoice_Invoicedate = DateTime.MinValue; + gxTv_SdtInvoice_Customername = ""; + gxTv_SdtInvoice_Mode = ""; + gxTv_SdtInvoice_Invoicedate_Z = DateTime.MinValue; + gxTv_SdtInvoice_Customername_Z = ""; + sDateCnv = ""; + sNumToPad = ""; + return ; + } + + public short isNull( ) + { + return sdtIsNull ; + } + + private short gxTv_SdtInvoice_Invoiceid ; + private short sdtIsNull ; + private short gxTv_SdtInvoice_Customerid ; + private short gxTv_SdtInvoice_Invoicetotal ; + private short gxTv_SdtInvoice_Invoicelast ; + private short gxTv_SdtInvoice_Initialized ; + private short gxTv_SdtInvoice_Invoiceid_Z ; + private short gxTv_SdtInvoice_Customerid_Z ; + private short gxTv_SdtInvoice_Invoicetotal_Z ; + private short gxTv_SdtInvoice_Invoicelast_Z ; + private short gxTv_SdtInvoice_Invoicetotal_N ; + private string gxTv_SdtInvoice_Customername ; + private string gxTv_SdtInvoice_Mode ; + private string gxTv_SdtInvoice_Customername_Z ; + private string sDateCnv ; + private string sNumToPad ; + private DateTime gxTv_SdtInvoice_Invoicedate ; + private DateTime gxTv_SdtInvoice_Invoicedate_Z ; + private GXBCLevelCollection gxTv_SdtInvoice_Level=null ; + } + + [DataContract(Name = @"Invoice", Namespace = "TestRestProcs")] + [GxJsonSerialization("default")] + public class SdtInvoice_RESTInterface : GxGenericCollectionItem + { + public SdtInvoice_RESTInterface( ) : base() + { + } + + public SdtInvoice_RESTInterface( SdtInvoice psdt ) : base(psdt) + { + } + + [DataMember( Name = "InvoiceId" , Order = 0 )] + [GxSeudo()] + public Nullable gxTpr_Invoiceid + { + get { + return sdt.gxTpr_Invoiceid ; + } + + set { + sdt.gxTpr_Invoiceid = (short)(value.HasValue ? value.Value : 0); + } + + } + + [DataMember( Name = "InvoiceDate" , Order = 1 )] + [GxSeudo()] + public string gxTpr_Invoicedate + { + get { + return DateTimeUtil.DToC2( sdt.gxTpr_Invoicedate) ; + } + + set { + sdt.gxTpr_Invoicedate = DateTimeUtil.CToD2( value); + } + + } + + [DataMember( Name = "CustomerId" , Order = 2 )] + [GxSeudo()] + public Nullable gxTpr_Customerid + { + get { + return sdt.gxTpr_Customerid ; + } + + set { + sdt.gxTpr_Customerid = (short)(value.HasValue ? value.Value : 0); + } + + } + + [DataMember( Name = "CustomerName" , Order = 3 )] + [GxSeudo()] + public string gxTpr_Customername + { + get { + return StringUtil.RTrim( sdt.gxTpr_Customername) ; + } + + set { + sdt.gxTpr_Customername = value; + } + + } + + [DataMember( Name = "InvoiceTotal" , Order = 4 )] + [GxSeudo()] + public Nullable gxTpr_Invoicetotal + { + get { + return sdt.gxTpr_Invoicetotal ; + } + + set { + sdt.gxTpr_Invoicetotal = (short)(value.HasValue ? value.Value : 0); + } + + } + + [DataMember( Name = "InvoiceLast" , Order = 5 )] + [GxSeudo()] + public Nullable gxTpr_Invoicelast + { + get { + return sdt.gxTpr_Invoicelast ; + } + + set { + sdt.gxTpr_Invoicelast = (short)(value.HasValue ? value.Value : 0); + } + + } + + [DataMember( Name = "Level" , Order = 6 )] + public GxGenericCollection gxTpr_Level + { + get { + return new GxGenericCollection(sdt.gxTpr_Level) ; + } + + set { + value.LoadCollection(sdt.gxTpr_Level); + } + + } + + public SdtInvoice sdt + { + get { + return (SdtInvoice)Sdt ; + } + + set { + Sdt = value ; + } + + } + + [OnDeserializing] + void checkSdt( StreamingContext ctx ) + { + if ( sdt == null ) + { + sdt = new SdtInvoice() ; + } + } + + [DataMember( Name = "gx_md5_hash", Order = 7 )] + public string Hash + { + get { + if ( StringUtil.StrCmp(md5Hash, null) == 0 ) + { + md5Hash = (string)(getHash()); + } + return md5Hash ; + } + + set { + md5Hash = value ; + } + + } + + private string md5Hash ; + } + + [DataContract(Name = @"Invoice", Namespace = "TestRestProcs")] + [GxJsonSerialization("default")] + public class SdtInvoice_RESTLInterface : GxGenericCollectionItem + { + public SdtInvoice_RESTLInterface( ) : base() + { + } + + public SdtInvoice_RESTLInterface( SdtInvoice psdt ) : base(psdt) + { + } + + [DataMember( Name = "InvoiceDate" , Order = 0 )] + [GxSeudo()] + public string gxTpr_Invoicedate + { + get { + return DateTimeUtil.DToC2( sdt.gxTpr_Invoicedate) ; + } + + set { + sdt.gxTpr_Invoicedate = DateTimeUtil.CToD2( value); + } + + } + + [DataMember( Name = "uri", Order = 1 )] + public string Uri + { + get { + return "" ; + } + + set { + } + + } + + public SdtInvoice sdt + { + get { + return (SdtInvoice)Sdt ; + } + + set { + Sdt = value ; + } + + } + + [OnDeserializing] + void checkSdt( StreamingContext ctx ) + { + if ( sdt == null ) + { + sdt = new SdtInvoice() ; + } + } + + } + +} diff --git a/dotnet/test/DotNetCoreWebUnitTest/apps/type_SdtInvoice_Level.cs b/dotnet/test/DotNetCoreWebUnitTest/apps/type_SdtInvoice_Level.cs new file mode 100644 index 000000000..ed48ff3ab --- /dev/null +++ b/dotnet/test/DotNetCoreWebUnitTest/apps/type_SdtInvoice_Level.cs @@ -0,0 +1,667 @@ +using System; +using System.Collections; +using GeneXus.Utils; +using GeneXus.Resources; +using GeneXus.Application; +using GeneXus.Metadata; +using GeneXus.Cryptography; +using GeneXus.Encryption; +using GeneXus.Http.Client; +using System.Reflection; +using System.Xml.Serialization; +using System.Runtime.Serialization; +namespace GeneXus.Programs.apps +{ + [XmlRoot(ElementName = "Invoice.Level" )] + [XmlType(TypeName = "Invoice.Level" , Namespace = "TestRestProcs" )] + [Serializable] + public class SdtInvoice_Level : GxSilentTrnSdt, IGxSilentTrnGridItem + { + public SdtInvoice_Level( ) + { + } + + public SdtInvoice_Level( IGxContext context ) + { + this.context = context; + constructorCallingAssembly = Assembly.GetEntryAssembly(); + initialize(); + } + + private static Hashtable mapper; + public override string JsonMap( string value ) + { + if ( mapper == null ) + { + mapper = new Hashtable(); + } + return (string)mapper[value]; ; + } + + public override Object[][] GetBCKey( ) + { + return (Object[][])(new Object[][]{new Object[]{"InvoiceLevelId", typeof(short)}}) ; + } + + public override GXProperties GetMetadata( ) + { + GXProperties metadata = new GXProperties(); + metadata.Set("Name", "Level"); + metadata.Set("BT", "InvoiceLevel"); + metadata.Set("PK", "[ \"InvoiceLevelId\" ]"); + metadata.Set("PKAssigned", "[ \"InvoiceLevelId\" ]"); + metadata.Set("FKList", "[ { \"FK\":[ \"InvoiceId\" ],\"FKMap\":[ ] },{ \"FK\":[ \"ProductId\" ],\"FKMap\":[ ] } ]"); + metadata.Set("AllowInsert", "True"); + metadata.Set("AllowUpdate", "True"); + metadata.Set("AllowDelete", "True"); + return metadata ; + } + + public override GeneXus.Utils.GxStringCollection StateAttributes( ) + { + GeneXus.Utils.GxStringCollection state = new GeneXus.Utils.GxStringCollection(); + state.Add("gxTpr_Mode"); + state.Add("gxTpr_Modified"); + state.Add("gxTpr_Initialized"); + state.Add("gxTpr_Invoicelevelid_Z"); + state.Add("gxTpr_Productid_Z"); + state.Add("gxTpr_Invoicelevelqty_Z"); + state.Add("gxTpr_Productprice_Z"); + state.Add("gxTpr_Invoicelevelsubtot_Z"); + return state ; + } + + public override void Copy( GxUserType source ) + { + SdtInvoice_Level sdt; + sdt = (SdtInvoice_Level)(source); + gxTv_SdtInvoice_Level_Invoicelevelid = sdt.gxTv_SdtInvoice_Level_Invoicelevelid ; + gxTv_SdtInvoice_Level_Productid = sdt.gxTv_SdtInvoice_Level_Productid ; + gxTv_SdtInvoice_Level_Invoicelevelqty = sdt.gxTv_SdtInvoice_Level_Invoicelevelqty ; + gxTv_SdtInvoice_Level_Productprice = sdt.gxTv_SdtInvoice_Level_Productprice ; + gxTv_SdtInvoice_Level_Invoicelevelsubtot = sdt.gxTv_SdtInvoice_Level_Invoicelevelsubtot ; + gxTv_SdtInvoice_Level_Mode = sdt.gxTv_SdtInvoice_Level_Mode ; + gxTv_SdtInvoice_Level_Modified = sdt.gxTv_SdtInvoice_Level_Modified ; + gxTv_SdtInvoice_Level_Initialized = sdt.gxTv_SdtInvoice_Level_Initialized ; + gxTv_SdtInvoice_Level_Invoicelevelid_Z = sdt.gxTv_SdtInvoice_Level_Invoicelevelid_Z ; + gxTv_SdtInvoice_Level_Productid_Z = sdt.gxTv_SdtInvoice_Level_Productid_Z ; + gxTv_SdtInvoice_Level_Invoicelevelqty_Z = sdt.gxTv_SdtInvoice_Level_Invoicelevelqty_Z ; + gxTv_SdtInvoice_Level_Productprice_Z = sdt.gxTv_SdtInvoice_Level_Productprice_Z ; + gxTv_SdtInvoice_Level_Invoicelevelsubtot_Z = sdt.gxTv_SdtInvoice_Level_Invoicelevelsubtot_Z ; + return ; + } + + public override void ToJSON( ) + { + ToJSON( true) ; + return ; + } + + public override void ToJSON( bool includeState ) + { + ToJSON( includeState, true) ; + return ; + } + + public override void ToJSON( bool includeState , + bool includeNonInitialized ) + { + AddObjectProperty("InvoiceLevelId", gxTv_SdtInvoice_Level_Invoicelevelid, false, includeNonInitialized); + AddObjectProperty("ProductId", gxTv_SdtInvoice_Level_Productid, false, includeNonInitialized); + AddObjectProperty("InvoiceLevelQty", gxTv_SdtInvoice_Level_Invoicelevelqty, false, includeNonInitialized); + AddObjectProperty("ProductPrice", gxTv_SdtInvoice_Level_Productprice, false, includeNonInitialized); + AddObjectProperty("InvoiceLevelSubTot", gxTv_SdtInvoice_Level_Invoicelevelsubtot, false, includeNonInitialized); + if ( includeState ) + { + AddObjectProperty("Mode", gxTv_SdtInvoice_Level_Mode, false, includeNonInitialized); + AddObjectProperty("Modified", gxTv_SdtInvoice_Level_Modified, false, includeNonInitialized); + AddObjectProperty("Initialized", gxTv_SdtInvoice_Level_Initialized, false, includeNonInitialized); + AddObjectProperty("InvoiceLevelId_Z", gxTv_SdtInvoice_Level_Invoicelevelid_Z, false, includeNonInitialized); + AddObjectProperty("ProductId_Z", gxTv_SdtInvoice_Level_Productid_Z, false, includeNonInitialized); + AddObjectProperty("InvoiceLevelQty_Z", gxTv_SdtInvoice_Level_Invoicelevelqty_Z, false, includeNonInitialized); + AddObjectProperty("ProductPrice_Z", gxTv_SdtInvoice_Level_Productprice_Z, false, includeNonInitialized); + AddObjectProperty("InvoiceLevelSubTot_Z", gxTv_SdtInvoice_Level_Invoicelevelsubtot_Z, false, includeNonInitialized); + } + return ; + } + + public void UpdateDirties( SdtInvoice_Level sdt ) + { + if ( sdt.IsDirty("InvoiceLevelId") ) + { + sdtIsNull = 0; + gxTv_SdtInvoice_Level_Invoicelevelid = sdt.gxTv_SdtInvoice_Level_Invoicelevelid ; + } + if ( sdt.IsDirty("ProductId") ) + { + sdtIsNull = 0; + gxTv_SdtInvoice_Level_Productid = sdt.gxTv_SdtInvoice_Level_Productid ; + } + if ( sdt.IsDirty("InvoiceLevelQty") ) + { + sdtIsNull = 0; + gxTv_SdtInvoice_Level_Invoicelevelqty = sdt.gxTv_SdtInvoice_Level_Invoicelevelqty ; + } + if ( sdt.IsDirty("ProductPrice") ) + { + sdtIsNull = 0; + gxTv_SdtInvoice_Level_Productprice = sdt.gxTv_SdtInvoice_Level_Productprice ; + } + if ( sdt.IsDirty("InvoiceLevelSubTot") ) + { + sdtIsNull = 0; + gxTv_SdtInvoice_Level_Invoicelevelsubtot = sdt.gxTv_SdtInvoice_Level_Invoicelevelsubtot ; + } + return ; + } + + [ SoapElement( ElementName = "InvoiceLevelId" )] + [ XmlElement( ElementName = "InvoiceLevelId" )] + public short gxTpr_Invoicelevelid + { + get { + return gxTv_SdtInvoice_Level_Invoicelevelid ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Level_Invoicelevelid = value; + gxTv_SdtInvoice_Level_Modified = 1; + SetDirty("Invoicelevelid"); + } + + } + + [ SoapElement( ElementName = "ProductId" )] + [ XmlElement( ElementName = "ProductId" )] + public short gxTpr_Productid + { + get { + return gxTv_SdtInvoice_Level_Productid ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Level_Productid = value; + gxTv_SdtInvoice_Level_Modified = 1; + SetDirty("Productid"); + } + + } + + [ SoapElement( ElementName = "InvoiceLevelQty" )] + [ XmlElement( ElementName = "InvoiceLevelQty" )] + public short gxTpr_Invoicelevelqty + { + get { + return gxTv_SdtInvoice_Level_Invoicelevelqty ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Level_Invoicelevelqty = value; + gxTv_SdtInvoice_Level_Modified = 1; + SetDirty("Invoicelevelqty"); + } + + } + + [ SoapElement( ElementName = "ProductPrice" )] + [ XmlElement( ElementName = "ProductPrice" )] + public decimal gxTpr_Productprice + { + get { + return gxTv_SdtInvoice_Level_Productprice ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Level_Productprice = value; + gxTv_SdtInvoice_Level_Modified = 1; + SetDirty("Productprice"); + } + + } + + [ SoapElement( ElementName = "InvoiceLevelSubTot" )] + [ XmlElement( ElementName = "InvoiceLevelSubTot" )] + public decimal gxTpr_Invoicelevelsubtot + { + get { + return gxTv_SdtInvoice_Level_Invoicelevelsubtot ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Level_Invoicelevelsubtot = value; + gxTv_SdtInvoice_Level_Modified = 1; + SetDirty("Invoicelevelsubtot"); + } + + } + + public void gxTv_SdtInvoice_Level_Invoicelevelsubtot_SetNull( ) + { + gxTv_SdtInvoice_Level_Invoicelevelsubtot = 0; + SetDirty("Invoicelevelsubtot"); + return ; + } + + public bool gxTv_SdtInvoice_Level_Invoicelevelsubtot_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "Mode" )] + [ XmlElement( ElementName = "Mode" )] + public string gxTpr_Mode + { + get { + return gxTv_SdtInvoice_Level_Mode ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Level_Mode = value; + SetDirty("Mode"); + } + + } + + public void gxTv_SdtInvoice_Level_Mode_SetNull( ) + { + gxTv_SdtInvoice_Level_Mode = ""; + SetDirty("Mode"); + return ; + } + + public bool gxTv_SdtInvoice_Level_Mode_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "Modified" )] + [ XmlElement( ElementName = "Modified" )] + public short gxTpr_Modified + { + get { + return gxTv_SdtInvoice_Level_Modified ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Level_Modified = value; + SetDirty("Modified"); + } + + } + + public void gxTv_SdtInvoice_Level_Modified_SetNull( ) + { + gxTv_SdtInvoice_Level_Modified = 0; + SetDirty("Modified"); + return ; + } + + public bool gxTv_SdtInvoice_Level_Modified_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "Initialized" )] + [ XmlElement( ElementName = "Initialized" )] + public short gxTpr_Initialized + { + get { + return gxTv_SdtInvoice_Level_Initialized ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Level_Initialized = value; + gxTv_SdtInvoice_Level_Modified = 1; + SetDirty("Initialized"); + } + + } + + public void gxTv_SdtInvoice_Level_Initialized_SetNull( ) + { + gxTv_SdtInvoice_Level_Initialized = 0; + SetDirty("Initialized"); + return ; + } + + public bool gxTv_SdtInvoice_Level_Initialized_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "InvoiceLevelId_Z" )] + [ XmlElement( ElementName = "InvoiceLevelId_Z" )] + public short gxTpr_Invoicelevelid_Z + { + get { + return gxTv_SdtInvoice_Level_Invoicelevelid_Z ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Level_Invoicelevelid_Z = value; + gxTv_SdtInvoice_Level_Modified = 1; + SetDirty("Invoicelevelid_Z"); + } + + } + + public void gxTv_SdtInvoice_Level_Invoicelevelid_Z_SetNull( ) + { + gxTv_SdtInvoice_Level_Invoicelevelid_Z = 0; + SetDirty("Invoicelevelid_Z"); + return ; + } + + public bool gxTv_SdtInvoice_Level_Invoicelevelid_Z_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "ProductId_Z" )] + [ XmlElement( ElementName = "ProductId_Z" )] + public short gxTpr_Productid_Z + { + get { + return gxTv_SdtInvoice_Level_Productid_Z ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Level_Productid_Z = value; + gxTv_SdtInvoice_Level_Modified = 1; + SetDirty("Productid_Z"); + } + + } + + public void gxTv_SdtInvoice_Level_Productid_Z_SetNull( ) + { + gxTv_SdtInvoice_Level_Productid_Z = 0; + SetDirty("Productid_Z"); + return ; + } + + public bool gxTv_SdtInvoice_Level_Productid_Z_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "InvoiceLevelQty_Z" )] + [ XmlElement( ElementName = "InvoiceLevelQty_Z" )] + public short gxTpr_Invoicelevelqty_Z + { + get { + return gxTv_SdtInvoice_Level_Invoicelevelqty_Z ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Level_Invoicelevelqty_Z = value; + gxTv_SdtInvoice_Level_Modified = 1; + SetDirty("Invoicelevelqty_Z"); + } + + } + + public void gxTv_SdtInvoice_Level_Invoicelevelqty_Z_SetNull( ) + { + gxTv_SdtInvoice_Level_Invoicelevelqty_Z = 0; + SetDirty("Invoicelevelqty_Z"); + return ; + } + + public bool gxTv_SdtInvoice_Level_Invoicelevelqty_Z_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "ProductPrice_Z" )] + [ XmlElement( ElementName = "ProductPrice_Z" )] + public decimal gxTpr_Productprice_Z + { + get { + return gxTv_SdtInvoice_Level_Productprice_Z ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Level_Productprice_Z = value; + gxTv_SdtInvoice_Level_Modified = 1; + SetDirty("Productprice_Z"); + } + + } + + public void gxTv_SdtInvoice_Level_Productprice_Z_SetNull( ) + { + gxTv_SdtInvoice_Level_Productprice_Z = 0; + SetDirty("Productprice_Z"); + return ; + } + + public bool gxTv_SdtInvoice_Level_Productprice_Z_IsNull( ) + { + return false ; + } + + [ SoapElement( ElementName = "InvoiceLevelSubTot_Z" )] + [ XmlElement( ElementName = "InvoiceLevelSubTot_Z" )] + public decimal gxTpr_Invoicelevelsubtot_Z + { + get { + return gxTv_SdtInvoice_Level_Invoicelevelsubtot_Z ; + } + + set { + sdtIsNull = 0; + gxTv_SdtInvoice_Level_Invoicelevelsubtot_Z = value; + gxTv_SdtInvoice_Level_Modified = 1; + SetDirty("Invoicelevelsubtot_Z"); + } + + } + + public void gxTv_SdtInvoice_Level_Invoicelevelsubtot_Z_SetNull( ) + { + gxTv_SdtInvoice_Level_Invoicelevelsubtot_Z = 0; + SetDirty("Invoicelevelsubtot_Z"); + return ; + } + + public bool gxTv_SdtInvoice_Level_Invoicelevelsubtot_Z_IsNull( ) + { + return false ; + } + + [XmlIgnore] + private static GXTypeInfo _typeProps; + protected override GXTypeInfo TypeInfo + { + get { + return _typeProps ; + } + + set { + _typeProps = value ; + } + + } + + public void initialize( ) + { + sdtIsNull = 1; + gxTv_SdtInvoice_Level_Mode = ""; + return ; + } + + public short isNull( ) + { + return sdtIsNull ; + } + + private short gxTv_SdtInvoice_Level_Invoicelevelid ; + private short sdtIsNull ; + private short gxTv_SdtInvoice_Level_Productid ; + private short gxTv_SdtInvoice_Level_Invoicelevelqty ; + private short gxTv_SdtInvoice_Level_Modified ; + private short gxTv_SdtInvoice_Level_Initialized ; + private short gxTv_SdtInvoice_Level_Invoicelevelid_Z ; + private short gxTv_SdtInvoice_Level_Productid_Z ; + private short gxTv_SdtInvoice_Level_Invoicelevelqty_Z ; + private decimal gxTv_SdtInvoice_Level_Productprice ; + private decimal gxTv_SdtInvoice_Level_Invoicelevelsubtot ; + private decimal gxTv_SdtInvoice_Level_Productprice_Z ; + private decimal gxTv_SdtInvoice_Level_Invoicelevelsubtot_Z ; + private string gxTv_SdtInvoice_Level_Mode ; + } + + [DataContract(Name = @"Invoice.Level", Namespace = "TestRestProcs")] + [GxJsonSerialization("default")] + public class SdtInvoice_Level_RESTInterface : GxGenericCollectionItem + { + public SdtInvoice_Level_RESTInterface( ) : base() + { + } + + public SdtInvoice_Level_RESTInterface( SdtInvoice_Level psdt ) : base(psdt) + { + } + + [DataMember( Name = "InvoiceLevelId" , Order = 0 )] + [GxSeudo()] + public Nullable gxTpr_Invoicelevelid + { + get { + return sdt.gxTpr_Invoicelevelid ; + } + + set { + sdt.gxTpr_Invoicelevelid = (short)(value.HasValue ? value.Value : 0); + } + + } + + [DataMember( Name = "ProductId" , Order = 1 )] + [GxSeudo()] + public Nullable gxTpr_Productid + { + get { + return sdt.gxTpr_Productid ; + } + + set { + sdt.gxTpr_Productid = (short)(value.HasValue ? value.Value : 0); + } + + } + + [DataMember( Name = "InvoiceLevelQty" , Order = 2 )] + [GxSeudo()] + public Nullable gxTpr_Invoicelevelqty + { + get { + return sdt.gxTpr_Invoicelevelqty ; + } + + set { + sdt.gxTpr_Invoicelevelqty = (short)(value.HasValue ? value.Value : 0); + } + + } + + [DataMember( Name = "ProductPrice" , Order = 3 )] + [GxSeudo()] + public Nullable gxTpr_Productprice + { + get { + return sdt.gxTpr_Productprice ; + } + + set { + sdt.gxTpr_Productprice = (decimal)(value.HasValue ? value.Value : 0); + } + + } + + [DataMember( Name = "InvoiceLevelSubTot" , Order = 4 )] + [GxSeudo()] + public Nullable gxTpr_Invoicelevelsubtot + { + get { + return sdt.gxTpr_Invoicelevelsubtot ; + } + + set { + sdt.gxTpr_Invoicelevelsubtot = (decimal)(value.HasValue ? value.Value : 0); + } + + } + + public SdtInvoice_Level sdt + { + get { + return (SdtInvoice_Level)Sdt ; + } + + set { + Sdt = value ; + } + + } + + [OnDeserializing] + void checkSdt( StreamingContext ctx ) + { + if ( sdt == null ) + { + sdt = new SdtInvoice_Level() ; + } + } + + } + + [DataContract(Name = @"Invoice.Level", Namespace = "TestRestProcs")] + [GxJsonSerialization("default")] + public class SdtInvoice_Level_RESTLInterface : GxGenericCollectionItem + { + public SdtInvoice_Level_RESTLInterface( ) : base() + { + } + + public SdtInvoice_Level_RESTLInterface( SdtInvoice_Level psdt ) : base(psdt) + { + } + + public SdtInvoice_Level sdt + { + get { + return (SdtInvoice_Level)Sdt ; + } + + set { + Sdt = value ; + } + + } + + [OnDeserializing] + void checkSdt( StreamingContext ctx ) + { + if ( sdt == null ) + { + sdt = new SdtInvoice_Level() ; + } + } + + } + +} From 2ee12bd7b7db85c9c874356e74d6df95556429f2 Mon Sep 17 00:00:00 2001 From: sjuarezgx Date: Wed, 19 Jun 2024 15:05:11 -0300 Subject: [PATCH 158/164] Support Azurite Blob Storage for devolpment (#982) --- .../GXAzureStorage/AzureStorageExternalProvider.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/dotnet/src/dotnetframework/Providers/Storage/GXAzureStorage/AzureStorageExternalProvider.cs b/dotnet/src/dotnetframework/Providers/Storage/GXAzureStorage/AzureStorageExternalProvider.cs index 738ad0c0d..678afac39 100644 --- a/dotnet/src/dotnetframework/Providers/Storage/GXAzureStorage/AzureStorageExternalProvider.cs +++ b/dotnet/src/dotnetframework/Providers/Storage/GXAzureStorage/AzureStorageExternalProvider.cs @@ -56,9 +56,15 @@ private void Initialize() string publicContainer = GetEncryptedPropertyValue(PUBLIC_CONTAINER); string privateContainer = GetEncryptedPropertyValue(PRIVATE_CONTAINER); - + string useDevelopmentStorage = Environment.GetEnvironmentVariable("AzuriteUseDevelopmentStorage"); + CloudStorageAccount storageAccount; + + if (string.Equals(useDevelopmentStorage, "true", StringComparison.OrdinalIgnoreCase)) + storageAccount = CloudStorageAccount.Parse("UseDevelopmentStorage=true"); + else { StorageCredentials credentials = new StorageCredentials(Account, Key); - CloudStorageAccount storageAccount = new CloudStorageAccount(credentials, true); + storageAccount = new CloudStorageAccount(credentials, true); + } Client = storageAccount.CreateCloudBlobClient(); From b8bec5b0fa251dd29fe63c3b91293c2ffc2b6265 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 25 Jun 2024 12:11:23 -0300 Subject: [PATCH 159/164] Support memcached and redis encrypted password. (#1033) * Support memcached and redis encrypted password. * Configure the Memcached client with the appropriate user and password for authentication * Set missing zone for Memcached. * Compatibility fix: Support encrypted and decrypted password at CloudServices.config for memcached and redis. --- .../Cache/GxMemcached/GxMemcached.cs | 31 +++++++++++++++++-- .../Providers/Cache/GxRedis/GxRedis.cs | 9 ++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/dotnet/src/dotnetframework/Providers/Cache/GxMemcached/GxMemcached.cs b/dotnet/src/dotnetframework/Providers/Cache/GxMemcached/GxMemcached.cs index 917758d7e..8ee0e92bd 100644 --- a/dotnet/src/dotnetframework/Providers/Cache/GxMemcached/GxMemcached.cs +++ b/dotnet/src/dotnetframework/Providers/Cache/GxMemcached/GxMemcached.cs @@ -3,10 +3,10 @@ using System.Linq; using System.Security; using System.Text.Json; -using System.Text.Json.Serialization; using Enyim.Caching; using Enyim.Caching.Configuration; using Enyim.Caching.Memcached; +using GeneXus.Encryption; using GeneXus.Services; using GeneXus.Utils; @@ -26,21 +26,46 @@ public Memcached() MemcachedClient InitCache() { GXServices services = ServiceFactory.GetGXServices(); - String address = string.Empty; + string address = string.Empty; + string password = string.Empty; + string username = string.Empty; if (services != null) { GXService providerService = ServiceFactory.GetGXServices()?.Get(GXServices.CACHE_SERVICE); if (providerService != null) { address = providerService.Properties.Get("CACHE_PROVIDER_ADDRESS"); + username = providerService.Properties.Get("CACHE_PROVIDER_USER"); + password = providerService.Properties.Get("CACHE_PROVIDER_PASSWORD"); + if (!string.IsNullOrEmpty(password)) + { + string ret = string.Empty; + if (CryptoImpl.Decrypt(ref ret, password)) + { + password = ret; + } + } } } #if NETCORE var loggerFactory = new Microsoft.Extensions.Logging.Abstractions.NullLoggerFactory(); - MemcachedClientConfiguration config = new MemcachedClientConfiguration(loggerFactory, new MemcachedClientOptions()); + MemcachedClientOptions options = new MemcachedClientOptions(); + if (!String.IsNullOrEmpty(username) || !String.IsNullOrEmpty(password)) + { + options.AddPlainTextAuthenticator(string.Empty, username, password); + } + MemcachedClientConfiguration config = new MemcachedClientConfiguration(loggerFactory, options); #else + MemcachedClientConfiguration config = new MemcachedClientConfiguration(); + if (!String.IsNullOrEmpty(username) || !String.IsNullOrEmpty(password)) + { + config.Authentication.Type = typeof(PlainTextAuthenticator); + config.Authentication.Parameters["userName"] = username; + config.Authentication.Parameters["password"] = password; + config.Authentication.Parameters["zone"] = string.Empty; + } #endif if (!String.IsNullOrEmpty(address)) { diff --git a/dotnet/src/dotnetframework/Providers/Cache/GxRedis/GxRedis.cs b/dotnet/src/dotnetframework/Providers/Cache/GxRedis/GxRedis.cs index 7007d736a..d8724d849 100644 --- a/dotnet/src/dotnetframework/Providers/Cache/GxRedis/GxRedis.cs +++ b/dotnet/src/dotnetframework/Providers/Cache/GxRedis/GxRedis.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Text.Json; using System.Threading.Tasks; +using GeneXus.Encryption; using GeneXus.Services; using GeneXus.Utils; using StackExchange.Redis; @@ -38,6 +39,14 @@ public Redis() string address, password; address = providerService.Properties.Get("CACHE_PROVIDER_ADDRESS"); password = providerService.Properties.Get("CACHE_PROVIDER_PASSWORD"); + if (!string.IsNullOrEmpty(password)) + { + string ret = string.Empty; + if (CryptoImpl.Decrypt(ref ret, password)) + { + password = ret; + } + } if (string.IsNullOrEmpty(address)) address = String.Format("localhost:{0}", REDIS_DEFAULT_PORT); From bc9f085db737fd93054f706ef695a7bc6db8a0b8 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 25 Jun 2024 14:55:36 -0300 Subject: [PATCH 160/164] Add support for HttpClient HTTP version 2.0 and 3.0 values (#1042) * Add support for HttpClient HTTP version 2.0 and 3.0 values * Fix build error. * Add trace message for custom HttpVersion. * SendAsync is required for httpVersion 2.0 in httpclient. --- .../GxClasses/Domain/GxHttpClient.cs | 28 ++++++++++++++----- .../test/DotNetCoreUnitTest/appsettings.json | 1 + 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs index 8cda5d449..7aa605b7b 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs @@ -814,15 +814,23 @@ void InferContentType(string contentType, HttpRequestMessage req) } } - void setHttpVersion(HttpRequestMessage req) + void SetHttpVersion(HttpRequestMessage req) { string httpVersion; if (Config.GetValueOf("HttpClientHttpVersion", out httpVersion)) { if (httpVersion == "1.0") req.Version = HttpVersion.Version10; +#if NETCORE + else if (httpVersion == "2.0") + req.Version = HttpVersion.Version20; + else if (httpVersion == "3.0") + req.Version = HttpVersion.Version30; +#endif else req.Version = HttpVersion.Version11; + + GXLogging.Debug(log, "Setting HTTPClient request version to ", req.Version.ToString()); } else req.Version = HttpVersion.Version11; @@ -845,7 +853,7 @@ HttpResponseMessage ExecuteRequest(string method, string requestUrl, bool contex Method = new HttpMethod(method), }; setHeaders(request, cookies, out string contentType); - setHttpVersion(request); + SetHttpVersion(request); bool disposableInstance = true; try { @@ -873,7 +881,7 @@ HttpResponseMessage ExecuteRequest(string method, string requestUrl, bool contex request.Content = new ByteArrayContent(reqStream.ToArray()); setContentHeaders(request, contentType); #if NETCORE - response = client.Send(request, HttpCompletionOption.ResponseHeadersRead); + response = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).GetAwaiter().GetResult(); response.ExtractCookies(cookies); #else response = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).GetAwaiter().GetResult(); @@ -907,7 +915,7 @@ async Task ExecuteRequestAsync(string method, string reques Method = new HttpMethod(method), }; setHeaders(request, cookies, out string contentType); - setHttpVersion(request); + SetHttpVersion(request); bool disposableInstance = true; try { @@ -1361,7 +1369,7 @@ static WebProxy getProxy(string proxyHost, int proxyPort, ArrayList authenticati return null; } - private void setHttpVersion(HttpWebRequest req) + private void SetHttpVersion(HttpWebRequest req) { string httpVersion; @@ -1369,6 +1377,12 @@ private void setHttpVersion(HttpWebRequest req) { if (httpVersion == "1.0") req.ProtocolVersion = HttpVersion.Version10; +#if NETCORE + else if (httpVersion == "2.0") + req.ProtocolVersion = HttpVersion.Version20; + else if (httpVersion == "3.0") + req.ProtocolVersion = HttpVersion.Version30; +#endif else req.ProtocolVersion = HttpVersion.Version11; } @@ -1430,7 +1444,7 @@ async Task buildRequestAsync(string method, string requestUrl, C req.ClientCertificates.Add(cert); req.Method = method.Trim(); req.Timeout = _timeout; - setHttpVersion(req); + SetHttpVersion(req); WebProxy proxy = getProxy(_proxyHost, _proxyPort, _authProxyCollection); if (proxy != null) req.Proxy = proxy; @@ -1482,7 +1496,7 @@ HttpWebRequest buildRequest(string method, string requestUrl, CookieContainer co req.ClientCertificates.Add(cert); req.Method = method.Trim(); req.Timeout = _timeout; - setHttpVersion(req); + SetHttpVersion(req); WebProxy proxy = getProxy(_proxyHost, _proxyPort, _authProxyCollection); if (proxy != null) req.Proxy = proxy; diff --git a/dotnet/test/DotNetCoreUnitTest/appsettings.json b/dotnet/test/DotNetCoreUnitTest/appsettings.json index d38ee5c57..660ee47e6 100644 --- a/dotnet/test/DotNetCoreUnitTest/appsettings.json +++ b/dotnet/test/DotNetCoreUnitTest/appsettings.json @@ -50,6 +50,7 @@ "CACHE_INVALIDATION_TOKEN": "20216211291931", "CORS_ALLOW_ORIGIN": "https://normal-website.com", "USE_JAYROCK": "0", + "HttpClientHttpVersion": "2.0", "MY_CUSTOM_PTY": "DEFAULT_VALUE" }, "languages": { From af20214451d5945bf0235f2614d332e1c744a07f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Sexenian?= <99925035+tomas-sexenian@users.noreply.github.com> Date: Tue, 2 Jul 2024 12:20:00 -0300 Subject: [PATCH 161/164] No ACL support for S3 (#1009) * STORAGE_PROVIDER_PRIVACY property rename Issue:108183 * Dynamically choose between sending canned ACL in the request or not * Presign every link to a resource in case the bucket is private * Treat ownerEnforcedBucketPrivacy as nullable * Cast nullable BucketPrivacy enum to null * Revert property name for compatibility reasons --- .../Services/Storage/ExternalProviderBase.cs | 4 +- .../Storage/GXAmazonS3/ExternalProviderS3.cs | 78 +++++++++++++++---- 2 files changed, 63 insertions(+), 19 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Services/Storage/ExternalProviderBase.cs b/dotnet/src/dotnetframework/GxClasses/Services/Storage/ExternalProviderBase.cs index df8816b04..e45905029 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/Storage/ExternalProviderBase.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/Storage/ExternalProviderBase.cs @@ -18,7 +18,7 @@ public abstract class ExternalProviderBase protected static String DEFAULT_ACL = "DEFAULT_ACL"; protected static String DEFAULT_EXPIRATION = "DEFAULT_EXPIRATION"; protected static String FOLDER = "FOLDER_NAME"; - protected static String DEFAULT_ACL_DEPRECATED = "STORAGE_PROVIDER_DEFAULT_ACL"; + protected static String DEFAULT_STORAGE_PRIVACY = "STORAGE_PROVIDER_DEFAULT_ACL"; protected static String DEFAULT_EXPIRATION_DEPRECATED = "STORAGE_PROVIDER_DEFAULT_EXPIRATION"; protected TimeSpan defaultExpiration = new TimeSpan(24, 0, 0); protected static string DEFAULT_TMP_CONTENT_TYPE = "image/jpeg"; @@ -52,7 +52,7 @@ public ExternalProviderBase(GXService s) private void Initialize() { - String aclS = GetPropertyValue(DEFAULT_ACL, DEFAULT_ACL_DEPRECATED, ""); + String aclS = GetPropertyValue(DEFAULT_ACL, DEFAULT_STORAGE_PRIVACY, ""); if (!String.IsNullOrEmpty(aclS)) { this.defaultAcl = aclS.Equals("Private") ? GxFileType.Private : GxFileType.PublicRead; diff --git a/dotnet/src/dotnetframework/Providers/Storage/GXAmazonS3/ExternalProviderS3.cs b/dotnet/src/dotnetframework/Providers/Storage/GXAmazonS3/ExternalProviderS3.cs index d31d262d9..dd015db2f 100644 --- a/dotnet/src/dotnetframework/Providers/Storage/GXAmazonS3/ExternalProviderS3.cs +++ b/dotnet/src/dotnetframework/Providers/Storage/GXAmazonS3/ExternalProviderS3.cs @@ -49,7 +49,11 @@ public class ExternalProviderS3 : ExternalProviderBase, ExternalProvider bool forcePathStyle = false; bool customEndpoint = false; - + + bool objectOwnershipEnabled; + private enum BucketPrivacy { PRIVATE, PUBLIC }; + private BucketPrivacy? ownerEnforcedBucketPrivacy; + public string StorageUri { get { @@ -104,6 +108,12 @@ private void Initialize() { } } + string default_storage_privacy = GetPropertyValue(DEFAULT_ACL, DEFAULT_STORAGE_PRIVACY, ""); + objectOwnershipEnabled = !default_storage_privacy.Contains("Bucket owner enforced"); + ownerEnforcedBucketPrivacy = (!objectOwnershipEnabled ? + (default_storage_privacy.Contains("private") ? BucketPrivacy.PRIVATE : BucketPrivacy.PUBLIC) + : (BucketPrivacy?)null); + #if NETCORE if (credentials != null) { @@ -227,16 +237,22 @@ public string Upload(string localFile, string objectName, GxFileType fileType) { BucketName = Bucket, Key = objectName, - FilePath = localFile, - CannedACL = GetCannedACL(fileType) + FilePath = localFile }; + if (objectOwnershipEnabled) + { + objectRequest.CannedACL = GetCannedACL(fileType); + } PutObject(objectRequest); return GetUrlImpl(objectName, fileType); } private bool IsPrivateUpload(GxFileType fileType) { - return GetCannedACL(fileType) != S3CannedACL.PublicRead; + if (objectOwnershipEnabled && GetCannedACL(fileType) != S3CannedACL.PublicRead) + return true; + else + return ownerEnforcedBucketPrivacy.HasValue && ownerEnforcedBucketPrivacy == BucketPrivacy.PRIVATE; } public string Get(string objectName, GxFileType fileType, int urlMinutes = 0) @@ -257,7 +273,7 @@ public string GetUrl(string objectName, GxFileType fileType, int urlMinutes = 0) private string GetUrlImpl(string objectName, GxFileType fileType, int urlMinutes = 0) { bool isPrivate = IsPrivateUpload(fileType); - return (isPrivate)? GetPreSignedUrl(objectName, ResolveExpiration(urlMinutes).TotalMinutes): StorageUri + StorageUtils.EncodeUrlPath(objectName); + return (isPrivate) ? GetPreSignedUrl(objectName, ResolveExpiration(urlMinutes).TotalMinutes): IsPrivateUpload(fileType) ? GetPreSignedUrl(objectName, ResolveExpiration(urlMinutes).TotalMinutes): StorageUri + StorageUtils.EncodeUrlPath(objectName); } @@ -316,7 +332,9 @@ public string Rename(string objectName, string newName, GxFileType fileType) { Copy(objectName, fileType, newName, fileType); Delete(objectName, fileType); - return StorageUri + StorageUtils.EncodeUrlPath(newName); + if (objectOwnershipEnabled) + return StorageUri + StorageUtils.EncodeUrlPath(newName); + return IsPrivateUpload(fileType) ? GetPreSignedUrl(objectName, defaultExpiration.Minutes) : StorageUri + StorageUtils.EncodeUrlPath(newName); } public string Copy(string objectName, GxFileType sourceFileType, string newName, GxFileType destFileType) @@ -327,17 +345,23 @@ public string Copy(string objectName, GxFileType sourceFileType, string newName, SourceKey = objectName, DestinationBucket = Bucket, DestinationKey = newName, - CannedACL = GetCannedACL(destFileType), MetadataDirective = S3MetadataDirective.REPLACE }; + if (objectOwnershipEnabled) + { + request.CannedACL = GetCannedACL(destFileType); + } + if (TryGetContentType(newName, out string mimeType, DEFAULT_CONTENT_TYPE)) { request.ContentType = mimeType; } CopyObject(request); - return StorageUri + StorageUtils.EncodeUrlPath(newName); + if (objectOwnershipEnabled) + return StorageUri + StorageUtils.EncodeUrlPath(newName); + return IsPrivateUpload(sourceFileType) ? GetPreSignedUrl(objectName, defaultExpiration.Minutes) : StorageUri + StorageUtils.EncodeUrlPath(newName); } private S3CannedACL GetCannedACL(GxFileType acl) @@ -384,10 +408,14 @@ private string UploadMultipart(string fileName, Stream stream, GxFileType destFi BucketName = Bucket, Key = fileName, PartSize = MULITIPART_POST_PART_SIZE, - InputStream = stream, - CannedACL = GetCannedACL(destFileType) + InputStream = stream }; + if (objectOwnershipEnabled) + { + uploadRequest.CannedACL = GetCannedACL(destFileType); + } + if (TryGetContentType(fileName, out string mimeType)) { uploadRequest.ContentType = mimeType; @@ -404,9 +432,14 @@ private string UploadSimple(string fileName, Stream stream, GxFileType destFileT { BucketName = Bucket, Key = fileName, - InputStream = stream, - CannedACL = GetCannedACL(destFileType) + InputStream = stream }; + + if (objectOwnershipEnabled) + { + objectRequest.CannedACL = GetCannedACL(destFileType); + } + if (TryGetContentType(fileName, out string mimeType)) { objectRequest.ContentType = mimeType; @@ -430,10 +463,14 @@ public string Copy(string url, string newName, string tableName, string fieldNam SourceKey = url, DestinationBucket = Bucket, DestinationKey = resourceKey, - CannedACL = GetCannedACL(destFileType), MetadataDirective = S3MetadataDirective.REPLACE }; + if (objectOwnershipEnabled) + { + request.CannedACL = GetCannedACL(destFileType); + } + if (TryGetContentType(newName, out string mimeType, DEFAULT_CONTENT_TYPE)) { request.ContentType = mimeType; @@ -442,7 +479,9 @@ public string Copy(string url, string newName, string tableName, string fieldNam AddObjectMetadata(request.Metadata, tableName, fieldName, resourceKey); CopyObject(request); - return StorageUri + StorageUtils.EncodeUrlPath(resourceKey); + if (objectOwnershipEnabled) + return StorageUri + StorageUtils.EncodeUrlPath(resourceKey); + return IsPrivateUpload(destFileType) ? GetPreSignedUrl(resourceKey, defaultExpiration.Minutes) : StorageUri + StorageUtils.EncodeUrlPath(resourceKey); } public string Save(Stream fileStream, string fileName, string tableName, string fieldName, GxFileType destFileType) @@ -455,9 +494,12 @@ public string Save(Stream fileStream, string fileName, string tableName, string { BucketName = Bucket, Key = resourceKey, - InputStream = fileStream, - CannedACL = GetCannedACL(destFileType) + InputStream = fileStream }; + if (objectOwnershipEnabled) + { + objectRequest.CannedACL = GetCannedACL(destFileType); + } if (TryGetContentType(fileName, out string mimeType)) { objectRequest.ContentType = mimeType; @@ -466,7 +508,9 @@ public string Save(Stream fileStream, string fileName, string tableName, string AddObjectMetadata(objectRequest.Metadata, tableName, fieldName, resourceKey); PutObjectResponse result = PutObject(objectRequest); - return StorageUri + resourceKey; + if (objectOwnershipEnabled) + return StorageUri + resourceKey; + return IsPrivateUpload(destFileType) ? GetPreSignedUrl(resourceKey, defaultExpiration.Minutes) : StorageUri + StorageUtils.EncodeUrlPath(resourceKey); } catch (Exception ex) { From 14f87e05e6678329857aaa520986e613a4cdf6d3 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 30 Jul 2024 14:18:46 -0300 Subject: [PATCH 162/164] Fix incorrect image path in Linux environment (#1052) --- dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs index 8ec7b8ee8..56f5da655 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs @@ -3781,7 +3781,7 @@ Hashtable Images { GXLogging.Debug(Logger, "Searching for txt files .."); int srchIx = 0; - string[] paths = new string[] { ".\\", "..\\" }; + string[] paths = { Directory.GetCurrentDirectory(), Directory.GetParent(Directory.GetCurrentDirectory()).FullName}; bool found = false; while (!found && srchIx < paths.Length) { From 98aca032c3233618ce46fbcd049063ff8cf377a4 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 31 Jul 2024 14:01:45 -0300 Subject: [PATCH 163/164] Fix NullReferenceException when adding certificates to HttpClient due to uninitialized handler.SslOptions.ClientCertificates (#1053) --- .../GxClasses/Domain/GxHttpClient.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs index 7aa605b7b..35b3136dc 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs @@ -238,8 +238,20 @@ private static SocketsHttpHandler GetHandler(Uri URI, ArrayList authCollection, { handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; } - foreach (X509Certificate2 cert in certificateCollection) - handler.SslOptions.ClientCertificates.Add(cert); + if (certificateCollection.Count > 0) + { + if (handler.SslOptions.ClientCertificates == null) + { + handler.SslOptions.ClientCertificates = new X509CertificateCollection(certificateCollection); + } + else + { + foreach (X509Certificate2 cert in certificateCollection) + { + handler.SslOptions.ClientCertificates.Add(cert); + } + } + } WebProxy proxy = getProxy(proxyHost, proxyPort, authProxyCollection); if (proxy != null) From e77b2e827668abb2fdc4391f7af37aaa69ba4a82 Mon Sep 17 00:00:00 2001 From: Ana Berta <31777352+anaiberta@users.noreply.github.com> Date: Mon, 9 Sep 2024 09:38:39 -0300 Subject: [PATCH 164/164] fix: Restore Beta Bot (#1060) --- .github/workflows/call-beta-bot.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/workflows/call-beta-bot.yml diff --git a/.github/workflows/call-beta-bot.yml b/.github/workflows/call-beta-bot.yml new file mode 100644 index 000000000..d7cb4406e --- /dev/null +++ b/.github/workflows/call-beta-bot.yml @@ -0,0 +1,18 @@ +name: Call Beta Bot + +on: + # Triggers the workflow on push to beta branch or changes in a pull request to main branch + push: + branches: [ "beta" ] + pull_request: + types: [ opened, synchronize, reopened, ready_for_review, closed, labeled, unlabeled ] + branches: [ "master" ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +jobs: + call-workflow: + if: github.repository_owner == 'genexuslabs' + uses: genexuslabs/build-genexus-reusable-workflow/.github/workflows/run-beta-bot.yml@main + secrets: inherit