Brought spec up to date, improvements to stability

This commit is contained in:
CloneTrooper1019
2020-07-12 20:19:30 -05:00
parent 7359b6efb7
commit 57fd3f8a25
29 changed files with 551 additions and 245 deletions

View File

@ -11,7 +11,7 @@ namespace RobloxFiles.XmlFormat
{
var errorHandler = new Func<string, Exception>((message) =>
{
string contents = $"XmlDataReader.{label}: {message}";
string contents = $"XmlRobloxFileReader.{label}: {message}";
return new Exception(contents);
});
@ -29,19 +29,25 @@ namespace RobloxFiles.XmlFormat
{
if (sharedString.Name == "SharedString")
{
XmlNode md5Node = sharedString.Attributes.GetNamedItem("md5");
XmlNode hashNode = sharedString.Attributes.GetNamedItem("md5");
if (md5Node == null)
if (hashNode == null)
throw error("Got a SharedString without an 'md5' attribute!");
string key = md5Node.InnerText;
string key = hashNode.InnerText;
string value = sharedString.InnerText.Replace("\n", "");
byte[] buffer = Convert.FromBase64String(value);
SharedString record = SharedString.FromBase64(value);
byte[] hash = Convert.FromBase64String(key);
var record = SharedString.FromBase64(value);
if (record.MD5_Key != key)
throw error("The provided md5 hash did not match with the md5 hash computed for the value!");
if (hash.Length != 16)
throw error($"SharedString base64 key '{key}' must decode to byte[16]!");
if (key != record.Key)
{
SharedString.Register(key, record.SharedValue);
record.Key = key;
}
file.SharedStrings.Add(key);
}

View File

@ -1,4 +1,5 @@
using System;
using System.Linq;
using System.Text;
using System.Xml;
@ -47,6 +48,9 @@ namespace RobloxFiles.XmlFormat
public static XmlNode WriteProperty(Property prop, XmlDocument doc, XmlRobloxFile file)
{
if (prop.Name == "Archivable")
return null;
string propType = prop.XmlToken;
if (propType == null)
@ -78,6 +82,7 @@ namespace RobloxFiles.XmlFormat
case PropertyType.String:
propType = (prop.HasRawBuffer ? "BinaryString" : "string");
break;
default: break;
}
}
@ -89,6 +94,19 @@ namespace RobloxFiles.XmlFormat
return null;
}
if (prop.Type == PropertyType.SharedString)
{
SharedString value = prop.CastValue<SharedString>();
if (value.ComputedKey == null)
{
var newShared = SharedString.FromBuffer(value.SharedValue);
value.Key = newShared.ComputedKey;
}
file.SharedStrings.Add(value.Key);
}
XmlElement propElement = doc.CreateElement(propType);
propElement.SetAttribute("name", prop.Name);
@ -102,12 +120,6 @@ namespace RobloxFiles.XmlFormat
propNode = newNode;
}
if (prop.Type == PropertyType.SharedString)
{
SharedString value = prop.CastValue<SharedString>();
file.SharedStrings.Add(value.MD5_Key);
}
return propNode;
}
@ -124,11 +136,19 @@ namespace RobloxFiles.XmlFormat
instNode.AppendChild(propsNode);
var props = instance.RefreshProperties();
var orderedKeys = props
.OrderBy(pair => pair.Key)
.Select(pair => pair.Key);
foreach (string propName in props.Keys)
foreach (string propName in orderedKeys)
{
Property prop = props[propName];
XmlNode propNode = WriteProperty(prop, doc, file);
if (propNode == null)
continue;
propsNode.AppendChild(propNode);
}
@ -151,12 +171,12 @@ namespace RobloxFiles.XmlFormat
var binaryWriter = XmlPropertyTokens.GetHandler<BinaryStringToken>();
var binaryBuffer = new Property("SharedString", PropertyType.String);
foreach (string md5 in file.SharedStrings)
foreach (string key in file.SharedStrings)
{
XmlElement sharedString = doc.CreateElement("SharedString");
sharedString.SetAttribute("md5", md5);
sharedString.SetAttribute("md5", key);
binaryBuffer.RawBuffer = SharedString.FindRecord(md5);
binaryBuffer.RawBuffer = SharedString.Find(key);
binaryWriter.WriteProperty(binaryBuffer, doc, sharedString);
sharedStrings.AppendChild(sharedString);