diff --git a/Wabbajack.Common/DynamicIniData.cs b/Wabbajack.Common/DynamicIniData.cs index 7757f40f..594058b5 100644 --- a/Wabbajack.Common/DynamicIniData.cs +++ b/Wabbajack.Common/DynamicIniData.cs @@ -1,6 +1,11 @@ -using System.Dynamic; +using System; +using System.Collections.Generic; +using System.Dynamic; +using System.Numerics; +using System.Text; using System.Text.RegularExpressions; using IniParser; +using IniParser.Exceptions; using IniParser.Model; namespace Wabbajack.Common @@ -44,10 +49,58 @@ namespace Wabbajack.Common public override bool TryGetMember(GetMemberBinder binder, out object result) { result = _coll[binder.Name]; - if (result is string) result = Regex.Unescape(((string) result).Trim('"')); + if (result is string) result = Interpret((string)result); return true; } + private static string Interpret(string s) + { + if (s.StartsWith("@ByteArray(") && s.EndsWith(")")) + { + return UnescapeUTF8(s.Substring("@ByteArray(".Length, s.Length - "@ByteArray(".Length - ")".Length)); + } + + return UnescapeString(s); + } + + private static string UnescapeString(string s) + { + return Regex.Unescape(s.Trim('"')); + } + + private static string UnescapeUTF8(string s) + { + List acc = new List(); + for (var i = 0; i < s.Length; i++) + { + var c = s[i]; + switch (c) + { + case '\\': + i++; + var nc = s[i]; + switch (nc) + { + case '\\': + acc.Add((byte)'\\'); + break; + case 'x': + var chrs = s[i + 1] + s[i + 2].ToString(); + i += 2; + acc.Add(Convert.ToByte(chrs, 16)); + break; + default: + throw new ParsingException($"Not a valid escape characer {nc}"); + } + break; + default: + acc.Add((byte)c); + break; + } + } + return Encoding.UTF8.GetString(acc.ToArray()); + } + public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) { if (indexes.Length > 1) @@ -61,4 +114,4 @@ namespace Wabbajack.Common return true; } } -} \ No newline at end of file +} diff --git a/Wabbajack.Test/IniTests.cs b/Wabbajack.Test/IniTests.cs new file mode 100644 index 00000000..6ad26a1d --- /dev/null +++ b/Wabbajack.Test/IniTests.cs @@ -0,0 +1,27 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Wabbajack.Common; + +namespace Wabbajack.Test +{ + [TestClass] + public class IniTests + { + + [TestMethod] + public void TestByteArrayParsing() + { + Assert.AreEqual("bar", @"[General] + foo = bar".LoadIniString().General.foo); + + Assert.AreEqual("baz\\bar", @"[General] + foo = baz\\bar".LoadIniString().General.foo); + + Assert.AreEqual("bar", @"[General] + foo = @ByteArray(bar)".LoadIniString().General.foo); + + Assert.AreEqual("foo\\h̴̹͚̎é̶̘͙̐l̶͕̔͑p̴̯̋͂m̶̞̮͘͠e̸͉͙͆̄\\baz", @"[General] + foo = @ByteArray(foo\\\x68\xcc\xb4\xcc\x8e\xcc\xb9\xcd\x9a\x65\xcc\xb6\xcd\x81\xcc\x90\xcc\x98\xcd\x99\x6c\xcc\xb6\xcc\x94\xcd\x91\xcd\x95\x70\xcc\xb4\xcc\x8b\xcd\x82\xcc\xaf\x6d\xcc\xb6\xcd\x98\xcd\xa0\xcc\x9e\xcc\xae\x65\xcc\xb8\xcd\x86\xcc\x84\xcd\x89\xcd\x99\\baz)".LoadIniString().General.foo); + } + + } +} diff --git a/Wabbajack.Test/Wabbajack.Test.csproj b/Wabbajack.Test/Wabbajack.Test.csproj index 1b15cf8d..581ff503 100644 --- a/Wabbajack.Test/Wabbajack.Test.csproj +++ b/Wabbajack.Test/Wabbajack.Test.csproj @@ -127,6 +127,7 @@ +