From 3ef81b2c8e3a27881e52257b4515b3fd55541c2c Mon Sep 17 00:00:00 2001 From: PoChangSu Date: Thu, 25 Jun 2020 13:42:54 +0900 Subject: [PATCH 1/2] check invalid file name --- .../Scripts/Extensions/StringExtensions.cs | 3 + .../UniVRM/Editor/Format/VRMExportSettings.cs | 66 ++++++++++++++++++- 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/Assets/VRM/UniGLTF/Scripts/Extensions/StringExtensions.cs b/Assets/VRM/UniGLTF/Scripts/Extensions/StringExtensions.cs index d181c7d40..92dbdbb7e 100644 --- a/Assets/VRM/UniGLTF/Scripts/Extensions/StringExtensions.cs +++ b/Assets/VRM/UniGLTF/Scripts/Extensions/StringExtensions.cs @@ -1,4 +1,5 @@ using System.IO; +using System.Text.RegularExpressions; using UnityEngine; namespace UniGLTF @@ -63,6 +64,8 @@ namespace UniGLTF }; public static string EscapeFilePath(this string path) { + path = Regex.Replace(path, @"[\u0000-\u001F\u007F]", "+"); + foreach(var x in EscapeChars) { path = path.Replace(x, '+'); diff --git a/Assets/VRM/UniVRM/Editor/Format/VRMExportSettings.cs b/Assets/VRM/UniVRM/Editor/Format/VRMExportSettings.cs index 3a5838a1e..7ae1ff610 100644 --- a/Assets/VRM/UniVRM/Editor/Format/VRMExportSettings.cs +++ b/Assets/VRM/UniVRM/Editor/Format/VRMExportSettings.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using UniGLTF; +using UnityEditor; using UnityEngine; @@ -92,6 +93,8 @@ namespace VRM public bool RemoveVertexColor = false; #endregion + private const int MAX_LENGTH = 64; + public struct Validation { /// @@ -190,7 +193,7 @@ namespace VRM if (ReduceBlendshape && Source.GetComponent() == null) { - yield return Validation.Error("ReduceBlendshapeSize is need VRMBlendShapeProxy, you need to convert to VRM once."); + yield return Validation.Error("ReduceBlendshapeSize needs VRMBlendShapeProxy. You need to convert to VRM once."); } var vertexColor = Source.GetComponentsInChildren().Any(x => x.sharedMesh.colors.Length > 0); @@ -228,6 +231,67 @@ namespace VRM yield return Validation.Warning(string.Format("unknown material '{0}' is used. this will export as `Standard` fallback", material.shader.name)); } + + foreach (var material in materials) + { + if (material.name.Length > MAX_LENGTH) + yield return Validation.Error(string.Format("FileName '{0}' is too long. ", material.name)); + } + + var textureNameList = new List(); + foreach (var material in materials) + { + var shader = material.shader; + int propertyCount = ShaderUtil.GetPropertyCount(shader); + for (int i = 0; i < propertyCount; i++) + { + if (ShaderUtil.GetPropertyType(shader, i) == ShaderUtil.ShaderPropertyType.TexEnv) + { + if ((material.GetTexture(ShaderUtil.GetPropertyName(shader, i)) != null)) + { + var textureName = material.GetTexture(ShaderUtil.GetPropertyName(shader, i)).name; + if (!textureNameList.Contains(textureName)) + textureNameList.Add(textureName); + } + } + } + } + + foreach (var textureName in textureNameList) + { + if (textureName.Length > MAX_LENGTH) + yield return Validation.Error(string.Format("FileName '{0}' is too long. ", textureName)); + } + + var vrmMeta = Source.GetComponent(); + if (vrmMeta != null) + { + if (vrmMeta.Meta != null) + { + if (vrmMeta.Meta.Thumbnail != null) + { + var thumbnailName = vrmMeta.Meta.Thumbnail.name; + if (thumbnailName.Length > MAX_LENGTH) + yield return Validation.Error(string.Format("FileName '{0}' is too long. ", thumbnailName)); + } + } + } + + var meshFilters = Source.GetComponentsInChildren(); + var meshesName = meshFilters.Select(x => x.sharedMesh.name).Distinct(); + foreach (var meshName in meshesName) + { + if (meshName.Length > MAX_LENGTH) + yield return Validation.Error(string.Format("FileName '{0}' is too long. ", meshName)); + } + + var skinnedmeshRenderers = Source.GetComponentsInChildren(); + var skinnedmeshesName = skinnedmeshRenderers.Select(x => x.sharedMesh.name).Distinct(); + foreach (var skinnedmeshName in skinnedmeshesName) + { + if (skinnedmeshName.Length > MAX_LENGTH) + yield return Validation.Error(string.Format("FileName '{0}' is too long. ", skinnedmeshName)); + } } /// From 73309bff07bb95fd849383b4a07dcf7ad8245f6c Mon Sep 17 00:00:00 2001 From: PoChangSu Date: Thu, 25 Jun 2020 19:27:09 +0900 Subject: [PATCH 2/2] add unit tests --- .../UniVRM/Editor/Format/VRMExportSettings.cs | 27 +++++------ .../Editor/Tests/InvalidFileNameTest.cs | 48 +++++++++++++++++++ .../Editor/Tests/InvalidFileNameTest.cs.meta | 11 +++++ .../Editor/Tests/UniVRM.Editor.Tests.asmdef | 9 +++- 4 files changed, 78 insertions(+), 17 deletions(-) create mode 100644 Assets/VRM/UniVRM/Editor/Tests/InvalidFileNameTest.cs create mode 100644 Assets/VRM/UniVRM/Editor/Tests/InvalidFileNameTest.cs.meta diff --git a/Assets/VRM/UniVRM/Editor/Format/VRMExportSettings.cs b/Assets/VRM/UniVRM/Editor/Format/VRMExportSettings.cs index 7ae1ff610..7fcab98a8 100644 --- a/Assets/VRM/UniVRM/Editor/Format/VRMExportSettings.cs +++ b/Assets/VRM/UniVRM/Editor/Format/VRMExportSettings.cs @@ -93,7 +93,10 @@ namespace VRM public bool RemoveVertexColor = false; #endregion - private const int MAX_LENGTH = 64; + public static bool IsFileNameLengthTooLong(string fileName) + { + return fileName.Length > 64; + } public struct Validation { @@ -234,7 +237,7 @@ namespace VRM foreach (var material in materials) { - if (material.name.Length > MAX_LENGTH) + if (IsFileNameLengthTooLong(material.name)) yield return Validation.Error(string.Format("FileName '{0}' is too long. ", material.name)); } @@ -259,29 +262,23 @@ namespace VRM foreach (var textureName in textureNameList) { - if (textureName.Length > MAX_LENGTH) + if (IsFileNameLengthTooLong(textureName)) yield return Validation.Error(string.Format("FileName '{0}' is too long. ", textureName)); } var vrmMeta = Source.GetComponent(); - if (vrmMeta != null) + if (vrmMeta != null && vrmMeta.Meta != null && vrmMeta.Meta.Thumbnail != null) { - if (vrmMeta.Meta != null) - { - if (vrmMeta.Meta.Thumbnail != null) - { - var thumbnailName = vrmMeta.Meta.Thumbnail.name; - if (thumbnailName.Length > MAX_LENGTH) - yield return Validation.Error(string.Format("FileName '{0}' is too long. ", thumbnailName)); - } - } + var thumbnailName = vrmMeta.Meta.Thumbnail.name; + if (IsFileNameLengthTooLong(thumbnailName)) + yield return Validation.Error(string.Format("FileName '{0}' is too long. ", thumbnailName)); } var meshFilters = Source.GetComponentsInChildren(); var meshesName = meshFilters.Select(x => x.sharedMesh.name).Distinct(); foreach (var meshName in meshesName) { - if (meshName.Length > MAX_LENGTH) + if (IsFileNameLengthTooLong(meshName)) yield return Validation.Error(string.Format("FileName '{0}' is too long. ", meshName)); } @@ -289,7 +286,7 @@ namespace VRM var skinnedmeshesName = skinnedmeshRenderers.Select(x => x.sharedMesh.name).Distinct(); foreach (var skinnedmeshName in skinnedmeshesName) { - if (skinnedmeshName.Length > MAX_LENGTH) + if (IsFileNameLengthTooLong(skinnedmeshName)) yield return Validation.Error(string.Format("FileName '{0}' is too long. ", skinnedmeshName)); } } diff --git a/Assets/VRM/UniVRM/Editor/Tests/InvalidFileNameTest.cs b/Assets/VRM/UniVRM/Editor/Tests/InvalidFileNameTest.cs new file mode 100644 index 000000000..ef6d0831c --- /dev/null +++ b/Assets/VRM/UniVRM/Editor/Tests/InvalidFileNameTest.cs @@ -0,0 +1,48 @@ +using NUnit.Framework; +using System.Linq; +using System.IO; + +namespace VRM +{ + public class InvalidFileNameTest + { + [Test] + [TestCase("VRMVRMVRMVRMVRMVRMVRMVRMVRMVRMVRMVRMVRMVRMVRMVRMVRMVRMVRMVRMVRMVRMV", true)] + [TestCase("VRMFormatVRMFormatVRMFormatVRMFormatVRMFormatVRMFormatVRMFormat", false)] + [TestCase("UniVRMUniVRMUniVRMUniVRMUniVRMUniVRMUniVRMUniVRMUniVRMUniVRMUniVRM", true)] + [TestCase("UniVRMUniVRMUniVRMUniVRMUniVRMUniVRMUniVRMUniVRMUniVRMUniVRMUniV", false)] + [TestCase("AliciaAliciaAliciaAliciaAliciaAliciaAliciaAliciaAliciaAliciaAliciaAlicia", true)] + public void DetectFileNameLength(string fileName, bool isIllegal) + { + var result = VRMExportSettings.IsFileNameLengthTooLong(fileName); + Assert.AreEqual(result, isIllegal); + } + + [Test] + [TestCase("\u0000\u0042\u0062", true)] + [TestCase("\u0045\u0046\u0047\u0065\u0068\u0036", false)] + [TestCase("\u0043\u0045\u0047\u007F", true)] + [TestCase("\u0000\u0042\u0062", true)] + [TestCase("\u003A\u0039\u005C\u0060\u0074", false)] + [TestCase("\u005D\u006F\u001C\u007A\u0036\u0049", true)] + public void DetectControlCharacters(string fileName, bool isIllegal) + { + var result = fileName.Any(x => char.IsControl(x)); + Assert.AreEqual(result, isIllegal); + } + + [Test] + [TestCase("VRM|Alicia?VRM", true)] + [TestCase("UniVRMUniVRM:UniVRM", true)] + [TestCase("VRMIsVRFileFormat", false)] + [TestCase("AliciaAlicia", true)] + [TestCase("UniVRMIsVRMImplementationInUnityPlatform", false)] + [TestCase("Avator*Avator/Avator", true)] + public void DetectInvalidCharacters(string fileName, bool isIllegal) + { + char[] invalidPathChars = Path.GetInvalidFileNameChars(); + var result = fileName.Any(x => invalidPathChars.Contains(x)); + Assert.AreEqual(result, isIllegal); + } + } +} diff --git a/Assets/VRM/UniVRM/Editor/Tests/InvalidFileNameTest.cs.meta b/Assets/VRM/UniVRM/Editor/Tests/InvalidFileNameTest.cs.meta new file mode 100644 index 000000000..aa5f11465 --- /dev/null +++ b/Assets/VRM/UniVRM/Editor/Tests/InvalidFileNameTest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8511ed091b59bca4da4fd280693b7c82 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM/UniVRM/Editor/Tests/UniVRM.Editor.Tests.asmdef b/Assets/VRM/UniVRM/Editor/Tests/UniVRM.Editor.Tests.asmdef index 2b3357214..0aa9a540b 100644 --- a/Assets/VRM/UniVRM/Editor/Tests/UniVRM.Editor.Tests.asmdef +++ b/Assets/VRM/UniVRM/Editor/Tests/UniVRM.Editor.Tests.asmdef @@ -2,7 +2,8 @@ "name": "UniVRM.Editor.Tests", "references": [ "VRM", - "UniJSON" + "UniJSON", + "UniVRM.Editor" ], "optionalUnityReferences": [ "TestAssemblies" @@ -11,5 +12,9 @@ "Editor" ], "excludePlatforms": [], - "allowUnsafeCode": false + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [] } \ No newline at end of file