Skip to content

Commit a6d56da

Browse files
committed
MD5 hashing for localization strings
1 parent 2247844 commit a6d56da

File tree

4 files changed

+157
-1
lines changed

4 files changed

+157
-1
lines changed

src/Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project>
22
<PropertyGroup>
3-
<Version>4.0.11</Version>
3+
<Version>4.0.12</Version>
44
<Authors>Martin Danielsson</Authors>
55
<Company>Haufe-Lexware GmbH &amp; Co. KG</Company>
66
<Description>Extensible, simple and fast ETL Tool</Description>
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// Implements an IOperator which takes one single string,
2+
// supposedly a date string such as "2022-06-02T09:25:36.0830000", and strips
3+
// off the zeroes at then end of the string. It also replaces the "T" with a space.
4+
// If there are more than three decimals which are non zero, truncate to three.
5+
6+
using System;
7+
using System.Composition;
8+
using System.Text;
9+
using System.Text.RegularExpressions;
10+
using NoFrillsTransformation.Interfaces;
11+
12+
namespace NoFrillsTransformation.Plugins.Acumatica.Operators
13+
{
14+
[Export(typeof(IOperator))]
15+
public class AcumaticaLocalizationMd5HashOperator : IOperator
16+
{
17+
public string Name => "aculocalizationmd5hash";
18+
19+
public string Description => "Creates an MD5 hash string from the input string, according to Localization.";
20+
21+
public ExpressionType Type => ExpressionType.Custom;
22+
23+
public int ParamCount => 1;
24+
25+
public ParamType[]? ParamTypes => new ParamType[] { ParamType.String };
26+
27+
public ParamType ReturnType => ParamType.String;
28+
29+
public void Configure(string? config)
30+
{
31+
}
32+
33+
public string Evaluate(IEvaluator eval, IExpression expression, IContext context)
34+
{
35+
string parameter = eval.Evaluate(eval, expression.Arguments[0], context);
36+
return CalculateMD5LocalizationString(parameter);
37+
}
38+
39+
private static string GetMD5Hash(string input)
40+
{
41+
// step 1, calculate MD5 hash from input
42+
var md5 = System.Security.Cryptography.MD5.Create();
43+
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
44+
byte[] hash = md5.ComputeHash(inputBytes);
45+
46+
// step 2, convert byte array to hex string
47+
StringBuilder sb = new StringBuilder();
48+
for (int i = 0; i < hash.Length; i++)
49+
{
50+
sb.Append(hash[i].ToString("X2"));
51+
}
52+
53+
return sb.ToString();
54+
}
55+
56+
internal static Byte[] CalculateMD5(String str)
57+
{
58+
if (str == null) return new Byte[0];
59+
60+
using var prov = System.Security.Cryptography.MD5.Create();
61+
byte[] bs = prov.ComputeHash(System.Text.Encoding.Unicode.GetBytes(str));
62+
63+
return bs;
64+
}
65+
internal static String CalculateMD5String(String str)
66+
{
67+
return ConvertBytes(CalculateMD5(str));
68+
}
69+
internal static String CalculateMD5LocalizationString(String str)
70+
{
71+
return CalculateMD5String(str.ToLower());
72+
}
73+
74+
internal static String ConvertBytes(Byte[] bytes)
75+
{
76+
return ConvertBytes(bytes, 0);
77+
}
78+
/// <remarks>Will insert a separator (<c>-</c>) every <paramref name="chars"/> characters</remarks>
79+
internal static String ConvertBytes(Byte[] bytes, Int32 chars)
80+
{
81+
if (bytes == null) return "";
82+
83+
StringBuilder s = new StringBuilder();
84+
for (int i = 0; i < bytes.Length; i++)
85+
{
86+
if (i > 0 && chars > 0 && i % chars == 0) s.Append("-");
87+
88+
s.Append(bytes[i].ToString("X2"));
89+
}
90+
return s.ToString();
91+
}
92+
}
93+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Implements an IOperator which takes one single string,
2+
// supposedly a date string such as "2022-06-02T09:25:36.0830000", and strips
3+
// off the zeroes at then end of the string. It also replaces the "T" with a space.
4+
// If there are more than three decimals which are non zero, truncate to three.
5+
6+
using System;
7+
using System.Composition;
8+
using System.Text;
9+
using System.Text.RegularExpressions;
10+
using NoFrillsTransformation.Interfaces;
11+
12+
namespace NoFrillsTransformation.Plugins.Acumatica.Operators
13+
{
14+
[Export(typeof(IOperator))]
15+
public class AcumaticaMd5HashOperator : IOperator
16+
{
17+
public string Name => "acumd5hash";
18+
19+
public string Description => "Creates an MD5 hash string from the input string.";
20+
21+
public ExpressionType Type => ExpressionType.Custom;
22+
23+
public int ParamCount => 1;
24+
25+
public ParamType[]? ParamTypes => new ParamType[] { ParamType.String };
26+
27+
public ParamType ReturnType => ParamType.String;
28+
29+
public void Configure(string? config)
30+
{
31+
}
32+
33+
public string Evaluate(IEvaluator eval, IExpression expression, IContext context)
34+
{
35+
string parameter = eval.Evaluate(eval, expression.Arguments[0], context);
36+
return GetMD5Hash(parameter);
37+
}
38+
39+
private static string GetMD5Hash(string input)
40+
{
41+
// step 1, calculate MD5 hash from input
42+
var md5 = System.Security.Cryptography.MD5.Create();
43+
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
44+
byte[] hash = md5.ComputeHash(inputBytes);
45+
46+
// step 2, convert byte array to hex string
47+
StringBuilder sb = new StringBuilder();
48+
for (int i = 0; i < hash.Length; i++)
49+
{
50+
sb.Append(hash[i].ToString("X2"));
51+
}
52+
53+
return sb.ToString();
54+
}
55+
}
56+
}

src/NoFrillsTransformation.Plugins.Sql/SqlWriter.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ public SqlWriter(IContext context, string target, string[] fieldNames, int[] fie
4242
throw new ArgumentException("Table name not found in SQL entity configuration file: " + _config);
4343
}
4444
_tableName = _entityConfig.Table.Name;
45+
46+
// If there is a parameter sqltimestamp in the context, and it's set to true, write a timestamp comment
47+
if (context.Parameters.TryGetValue("sqltimestamp", out string? sqltimestamp) && sqltimestamp.ToLowerInvariant() == "true")
48+
{
49+
_textWriter.WriteLine("-- Generated by NoFrillsTransformation at " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
50+
}
51+
4552
_textWriter.WriteLine($"DROP TABLE IF EXISTS {_tableName};");
4653
_textWriter.WriteLine("CREATE TABLE " + _tableName + " (");
4754
// Copy the column names from the config file

0 commit comments

Comments
 (0)