From c84c15fa2cfea504a48069bc3fa341d306843f22 Mon Sep 17 00:00:00 2001 From: jvyden Date: Sun, 17 Oct 2021 20:34:44 -0400 Subject: [PATCH] Add method to determine a file type --- .../ExampleFiles/TestFarc.farc | 1 + .../ExampleFiles/TestLevel.lvl | Bin 0 -> 3952 bytes .../ExampleFiles/TestScript.ff | 3 + .../ExampleFiles/TestTexture.tex | Bin 0 -> 208 bytes .../ProjectLighthouse.Tests.csproj | 6 +- .../Tests/FileTypeTests.cs | 53 ++++++++++++++++++ .../Controllers/PublishController.cs | 1 + ProjectLighthouse/Helpers/BinaryHelper.cs | 13 +++++ ProjectLighthouse/Helpers/FileHelper.cs | 38 +++++++++++++ ProjectLighthouse/Types/Files/LbpFile.cs | 22 ++++++++ ProjectLighthouse/Types/Files/LbpFileType.cs | 9 +++ 11 files changed, 144 insertions(+), 2 deletions(-) create mode 100644 ProjectLighthouse.Tests/ExampleFiles/TestFarc.farc create mode 100644 ProjectLighthouse.Tests/ExampleFiles/TestLevel.lvl create mode 100644 ProjectLighthouse.Tests/ExampleFiles/TestScript.ff create mode 100644 ProjectLighthouse.Tests/ExampleFiles/TestTexture.tex create mode 100644 ProjectLighthouse.Tests/Tests/FileTypeTests.cs create mode 100644 ProjectLighthouse/Helpers/FileHelper.cs create mode 100644 ProjectLighthouse/Types/Files/LbpFile.cs create mode 100644 ProjectLighthouse/Types/Files/LbpFileType.cs diff --git a/ProjectLighthouse.Tests/ExampleFiles/TestFarc.farc b/ProjectLighthouse.Tests/ExampleFiles/TestFarc.farc new file mode 100644 index 00000000..3a0eae8e --- /dev/null +++ b/ProjectLighthouse.Tests/ExampleFiles/TestFarc.farc @@ -0,0 +1 @@ +FSHbFARC \ No newline at end of file diff --git a/ProjectLighthouse.Tests/ExampleFiles/TestLevel.lvl b/ProjectLighthouse.Tests/ExampleFiles/TestLevel.lvl new file mode 100644 index 0000000000000000000000000000000000000000..9491cbb59afebcd4a1db8091e6707d28f16f04c1 GIT binary patch literal 3952 zcmai1X-}M06dndBOC_~*pu;kS(hfUPpzO?0D9~Xm%s>a2vUC`r(6Y_6)6!vSS~WJY zu~y>}jdhDk)VM}XH%-*Ef{3+EYZsR<#t(k+FZet?*B7EOw$C}|Ip^N@eeXTz+&iJk z+0?Jo1^@ZQWt}d3rw;$Zf^_&Fo?+-8Mig+)wzk8>R35F`Q3DbUiLc~9XaxD4`k`d*jNdR9)$V*@@K0<;3ZAXLolulwk8wohzuLId540l_C>*SLh8%g%3=65 zPAGu@orTdJVVdr=HVNnY_G@7fi#UhAKX)`J^vg%!1?!-KB&_M)(6;a@gSgBJkUA+g zOib5}6M4F>3^?X#iL_MOufKfvyg1b`@d;6>Y2s$bRaK@I2;U%P;dJYEVbFSJOAkp3 zGfHrL$|?lv^;tS3HVTsuIkI!YEfLY%XUyYje*+S+-F_4#w=O-q*EDsI&rJJ{ znPe;zrlZXzPL>#Gqp_PS{pKu`hg%YKSXjdbaen@!Pso@U=#G`d=5^gvK5c_S+lpvS+jIpQxM^RegQWR5PL(duL?USSRc9U$A*) zB)2yagq`Pa=HsE|L6LVp0%5-N>|6%~2wZ)qQ5f|7T*H>L>~~)~4qXNTiuk$&h(-Ju z=fV@hmft)iMD(4PW5&`!btxuKcHI^*)0o<`Ixn?;n<{Th4~7@MkOz%jVxf-~x(~wm zA&Ezz_Iaba_Q0yOw1NVm5Z(|PRLxWd5Khlgn9Ts>;L>~w%&m{1cx1~V0KY6a#4f$ZZv%68K7}qh?A`{$Hx&g@vuQQB zc%5&BjHFv6c;no(nYR{T8p-1D1Bd(8IRlviRj?X_>L=M;0xJwly+4e@1DR*}y*?%%KU_?}vb2KF7dQg;2E*SLmNieO{!g#fjjAHICvFYewd*e>A}qsEe9 z(9znfCnZw6zCm~M6}H^u3^S%SG$y0}t9itVwOL%O240P-U3gr>dS%3-P1x)x0`G8} znplg)lf3r15JAWsXR?++yH0G;Pwa^s4~sX#Y6~J@hRvHaA7t{tW*xgn_2NC%fn2SD zYh%wXJ`1J6)6c{L9O7{RcpS!=L0}_m%tx)_L*Kj*t?_@5qfB&YW92%D2RXIz#CFhL zR%w)Tfa~*On_=Q1<+`{Li7>$)Pn&97|6D#VkfuSXjS${zK=Z^dAKN>)HFRf+p-V>@Y>7}YAk`xhGepW)~yodVdk^E z)R@oss7dH>h}T99sM`T7^SDHyr`Oncxv>G+&np9PfDyh6VD?rcuHN3@O-JOH(~cdP zt4CPD2qreETf)t4%+~GqpllnU5{k#w0Zfw#f4p@8#1~QxJ*W0BBhY-ezLYZuB$lzZ z{pySB11VeJ{`8o{p!u;i*`wm`@dSa`#ewd(JH6wuE>?xBsp*FTxaD07Z`y`dN`gov zWD4SHN!sn@-H`(k=$!-XeWpK(9Wlo5vIpwR{Lt*!vAq>MXaZMY)Zqi=l!2_F>_87l zN^i*oGr{~F;h6!#a_tNOrD8Uu-}4IsBg`};OWZ4Gc*> z;r;<`g%=OdZHhG{#MOWZS;Oh=W`JxATyL|h2Ow}(>f#lQ`9J%+wHqL1% zUVJsfS_=m7AgCWc_9?)R2jT|V7uTLI^>*705+6|8DKuwwBC`CjIa~eYmbfR6A+mCU z;iwJ8_ORcJc*6nJg;9?7Xa^WisD@}TPP@mGmDIxA@caN4AL|O_tHpuxq%oI#N|gW% z7}_CLox2M0p!sfpzPM91{)hpijp-}7LLtp?pq%~@k{ZWp|i)eg8VM&qQ@3a&>?IAyWu02zO0roJ$OGK=Dk3K=!CKux}i! z_3;Rvu9D)kGMJ^6{lH6r0KV*-m-fIi)7&>{-?a~gL5JS_ywT3C;#OEnbt+m{et}#* z)jSyOh76maTG&|r8K@s#fciJo?S=uaUNC+8eGqQYU0k6>LHMy*2tVF1zW>)Z__Q06 zl+QbbfA&V|bwNK|0@3SrIz9{<3YwY2KZ!w_lR?&k$QYTyfY5^=-2J~PD}bmGZw3=5 F^)H^5>2Lr5 literal 0 HcmV?d00001 diff --git a/ProjectLighthouse.Tests/ExampleFiles/TestScript.ff b/ProjectLighthouse.Tests/ExampleFiles/TestScript.ff new file mode 100644 index 00000000..ba1ce0e4 --- /dev/null +++ b/ProjectLighthouse.Tests/ExampleFiles/TestScript.ff @@ -0,0 +1,3 @@ +FSH + +this is not my stuff to upload so its just gonna be a file like this for now :/ \ No newline at end of file diff --git a/ProjectLighthouse.Tests/ExampleFiles/TestTexture.tex b/ProjectLighthouse.Tests/ExampleFiles/TestTexture.tex new file mode 100644 index 0000000000000000000000000000000000000000..340b4e89360df3d52e0533b1728e68c05e0bc5e8 GIT binary patch literal 208 zcmWG>jZk1<1j4dHhK%?7_X5$WjhsNzK!gQI>T^V;K}3Nhn;4LA;06)}41z$ikdfU4 zNQH%g#DS=yAVxD7NGk!ccWunojX>H0h#@EjNL`zjDi_BOWLQGP>VTArC#3{Xe| - + + + PreserveNewest + - diff --git a/ProjectLighthouse.Tests/Tests/FileTypeTests.cs b/ProjectLighthouse.Tests/Tests/FileTypeTests.cs new file mode 100644 index 00000000..f3484871 --- /dev/null +++ b/ProjectLighthouse.Tests/Tests/FileTypeTests.cs @@ -0,0 +1,53 @@ +using System; +using System.IO; +using System.Net; +using System.Text; +using ProjectLighthouse.Types.Files; +using Xunit; + +namespace ProjectLighthouse.Tests { + public class FileTypeTests { + [Fact] + public void ShouldRecognizeLevel() { + LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestLevel.lvl")); + Assert.True(file.FileType == LbpFileType.Level); + } + + [Fact] + public void ShouldRecognizeScript() { + LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestScript.ff")); + Assert.True(file.FileType == LbpFileType.Script); + } + + [Fact] + public void ShouldRecognizeTexture() { + LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestTexture.tex")); + Assert.True(file.FileType == LbpFileType.Texture); + } + + [Fact] + public void ShouldRecognizeFileArchive() { + LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestFarc.farc")); + Assert.True(file.FileType == LbpFileType.FileArchive); + } + + [Fact] + public void ShouldNotRecognizeFileArchiveAsScript() { + LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestFarc.farc")); + Assert.False(file.FileType == LbpFileType.Script); + Assert.True(file.FileType == LbpFileType.FileArchive); + } + + [Fact] + public void ShouldRecognizeNothingAsUnknown() { + LbpFile file = new(Array.Empty()); + Assert.True(file.FileType == LbpFileType.Unknown); + } + + [Fact] + public void ShouldRecognizeGarbageAsUnknown() { + LbpFile file = new(Encoding.ASCII.GetBytes("free pc only $900")); + Assert.True(file.FileType == LbpFileType.Unknown); + } + } +} \ No newline at end of file diff --git a/ProjectLighthouse/Controllers/PublishController.cs b/ProjectLighthouse/Controllers/PublishController.cs index f94e4292..d0839e30 100644 --- a/ProjectLighthouse/Controllers/PublishController.cs +++ b/ProjectLighthouse/Controllers/PublishController.cs @@ -49,6 +49,7 @@ namespace ProjectLighthouse.Controllers { await database.SaveChangesAsync(); slot.LocationId = l.Id; slot.CreatorId = user.UserId; + if(slot.BackgroundHash == null) slot.BackgroundHash = ""; database.Slots.Add(slot); await database.SaveChangesAsync(); diff --git a/ProjectLighthouse/Helpers/BinaryHelper.cs b/ProjectLighthouse/Helpers/BinaryHelper.cs index 6b66ff1c..9d2e18e3 100644 --- a/ProjectLighthouse/Helpers/BinaryHelper.cs +++ b/ProjectLighthouse/Helpers/BinaryHelper.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.IO; using System.Text; @@ -21,5 +22,17 @@ namespace ProjectLighthouse.Helpers { readByte = reader.ReadByte(); } while(readByte != byteToReadTo); } + + public static byte[] ReadLastBytes(BinaryReader reader, int count, bool restoreOldPosition = true) { + long oldPosition = reader.BaseStream.Position; + + if(reader.BaseStream.Length < count) return Array.Empty(); + + reader.BaseStream.Position = reader.BaseStream.Length - count; + byte[] data = reader.ReadBytes(count); + + if(restoreOldPosition) reader.BaseStream.Position = oldPosition; + return data; + } } } \ No newline at end of file diff --git a/ProjectLighthouse/Helpers/FileHelper.cs b/ProjectLighthouse/Helpers/FileHelper.cs new file mode 100644 index 00000000..31fff6eb --- /dev/null +++ b/ProjectLighthouse/Helpers/FileHelper.cs @@ -0,0 +1,38 @@ +using System; +using System.IO; +using System.Text; +using ProjectLighthouse.Types.Files; + +namespace ProjectLighthouse.Helpers { + public static class FileHelper { + public static bool IsFileSafe(LbpFile file) { + if(file.FileType == LbpFileType.Unknown) file.FileType = DetermineFileType(file.Data); + + return file.FileType switch { + LbpFileType.Texture => true, + LbpFileType.Script => false, + LbpFileType.Level => true, + LbpFileType.FileArchive => false, + LbpFileType.Unknown => false, + _ => throw new ArgumentOutOfRangeException(nameof(file), "Unknown file type."), + }; + } + + public static LbpFileType DetermineFileType(byte[] data) { + using MemoryStream ms = new(data); + using BinaryReader reader = new(ms); + + string footer = Encoding.ASCII.GetString(BinaryHelper.ReadLastBytes(reader, 4)); + if(footer == "FARC") return LbpFileType.FileArchive; + + byte[] header = reader.ReadBytes(3); + + return Encoding.ASCII.GetString(header) switch { + "TEX" => LbpFileType.Texture, + "FSH" => LbpFileType.Script, + "LVL" => LbpFileType.Level, + _ => LbpFileType.Unknown, + }; + } + } +} \ No newline at end of file diff --git a/ProjectLighthouse/Types/Files/LbpFile.cs b/ProjectLighthouse/Types/Files/LbpFile.cs new file mode 100644 index 00000000..710f9647 --- /dev/null +++ b/ProjectLighthouse/Types/Files/LbpFile.cs @@ -0,0 +1,22 @@ +using System.IO; +using ProjectLighthouse.Helpers; + +namespace ProjectLighthouse.Types.Files { + public class LbpFile { + public LbpFile(byte[] data) { + this.Data = data; + this.FileType = FileHelper.DetermineFileType(data); + } + + /// + /// The type of file. + /// + public LbpFileType FileType; + + /// + /// A buffer of the file's data. + /// + public readonly byte[] Data; + + } +} \ No newline at end of file diff --git a/ProjectLighthouse/Types/Files/LbpFileType.cs b/ProjectLighthouse/Types/Files/LbpFileType.cs new file mode 100644 index 00000000..418cb97f --- /dev/null +++ b/ProjectLighthouse/Types/Files/LbpFileType.cs @@ -0,0 +1,9 @@ +namespace ProjectLighthouse.Types.Files { + public enum LbpFileType { + Script, // .ff, FSH + Texture, // TEX + Level, // LVL + FileArchive, // .farc, (ends with FARC) + Unknown, + } +} \ No newline at end of file