mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-19 14:53:50 +02:00
fix: Wrong keyword encoding, bad buffer, update cache fix
Was using ASCII for keyword and was generating inconsistent CRC whoops
This commit is contained in:
@@ -7,7 +7,7 @@ using System.Text;
|
|||||||
|
|
||||||
namespace VRCX;
|
namespace VRCX;
|
||||||
|
|
||||||
public struct PNGChunk
|
public class PNGChunk
|
||||||
{
|
{
|
||||||
public int Index;
|
public int Index;
|
||||||
public int Length;
|
public int Length;
|
||||||
@@ -58,7 +58,7 @@ public struct PNGChunk
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Parse keyword as null-terminated string
|
// Parse keyword as null-terminated string
|
||||||
var keywordEncoding = Encoding.GetEncoding("ISO-8859-1");
|
var keywordEncoding = Encoding.UTF8;
|
||||||
int keywordLength = 0;
|
int keywordLength = 0;
|
||||||
for (int i = 0; i < chunkLength; i++)
|
for (int i = 0; i < chunkLength; i++)
|
||||||
{
|
{
|
||||||
@@ -126,8 +126,9 @@ public struct PNGChunk
|
|||||||
public bool ExistsInFile(FileStream fileStream)
|
public bool ExistsInFile(FileStream fileStream)
|
||||||
{
|
{
|
||||||
fileStream.Seek(Index, SeekOrigin.Begin);
|
fileStream.Seek(Index, SeekOrigin.Begin);
|
||||||
byte[] buffer = new byte[Length];
|
|
||||||
fileStream.ReadExactly(buffer, 0, Length);
|
byte[] buffer = new byte[4];
|
||||||
|
fileStream.ReadExactly(buffer, 0, 4);
|
||||||
|
|
||||||
if (BitConverter.IsLittleEndian)
|
if (BitConverter.IsLittleEndian)
|
||||||
Array.Reverse(buffer, 0, 4);
|
Array.Reverse(buffer, 0, 4);
|
||||||
@@ -137,14 +138,15 @@ public struct PNGChunk
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
fileStream.Seek(4 + chunkLength, SeekOrigin.Current);
|
fileStream.Seek(4 + chunkLength, SeekOrigin.Current);
|
||||||
fileStream.ReadExactly(buffer, 0, Length);
|
fileStream.ReadExactly(buffer, 0, 4);
|
||||||
|
|
||||||
if (BitConverter.IsLittleEndian)
|
if (BitConverter.IsLittleEndian)
|
||||||
Array.Reverse(buffer, 0, 4);
|
Array.Reverse(buffer, 0, 4);
|
||||||
|
|
||||||
uint crc = BitConverter.ToUInt32(buffer, 0);
|
uint crc = BitConverter.ToUInt32(buffer, 0);
|
||||||
|
uint calculatedCRC = CalculateCRC();
|
||||||
|
|
||||||
return crc == CalculateCRC();
|
return crc == calculatedCRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -186,7 +188,7 @@ public struct PNGChunk
|
|||||||
|
|
||||||
public uint CalculateCRC()
|
public uint CalculateCRC()
|
||||||
{
|
{
|
||||||
var chunkTypeBytes = Encoding.ASCII.GetBytes(ChunkType);
|
var chunkTypeBytes = Encoding.UTF8.GetBytes(ChunkType);
|
||||||
return Crc32(Data, 0, Data.Length, Crc32(chunkTypeBytes, 0, chunkTypeBytes.Length, 0));
|
return Crc32(Data, 0, Data.Length, Crc32(chunkTypeBytes, 0, chunkTypeBytes.Length, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ public class PNGFile : IDisposable
|
|||||||
public PNGChunk? GetChunkReverse(PNGChunkTypeFilter chunkTypeFilter)
|
public PNGChunk? GetChunkReverse(PNGChunkTypeFilter chunkTypeFilter)
|
||||||
{
|
{
|
||||||
var chunk = ReadChunkReverse(chunkTypeFilter);
|
var chunk = ReadChunkReverse(chunkTypeFilter);
|
||||||
if (chunk.HasValue &&chunk.Value.IsZero())
|
if (chunk != null && chunk.IsZero())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return chunk;
|
return chunk;
|
||||||
@@ -147,10 +147,10 @@ public class PNGFile : IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
fileStream.SetLength(fileStream.Length - deleteLength);
|
fileStream.SetLength(fileStream.Length - deleteLength);
|
||||||
|
|
||||||
metadataChunkCache.Remove(chunk);
|
metadataChunkCache.Remove(chunk);
|
||||||
|
|
||||||
// update the index of all cached chunks
|
// Update the index of cached chunks
|
||||||
for (int i = 0; i < metadataChunkCache.Count; i++)
|
for (int i = 0; i < metadataChunkCache.Count; i++)
|
||||||
{
|
{
|
||||||
var cachedChunk = metadataChunkCache[i];
|
var cachedChunk = metadataChunkCache[i];
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ namespace VRCX
|
|||||||
public static string ReadResolution(PNGFile pngFile)
|
public static string ReadResolution(PNGFile pngFile)
|
||||||
{
|
{
|
||||||
var ihdrChunk = pngFile.GetChunk(PNGChunkTypeFilter.IHDR);
|
var ihdrChunk = pngFile.GetChunk(PNGChunkTypeFilter.IHDR);
|
||||||
if (ihdrChunk.HasValue)
|
if (ihdrChunk != null)
|
||||||
{
|
{
|
||||||
var resolution = ihdrChunk.Value.ReadIHDRChunkResolution();
|
var resolution = ihdrChunk.ReadIHDRChunkResolution();
|
||||||
return resolution.Item1 + "x" + resolution.Item2;
|
return resolution.Item1 + "x" + resolution.Item2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,9 +42,9 @@ namespace VRCX
|
|||||||
if (legacySearch)
|
if (legacySearch)
|
||||||
{
|
{
|
||||||
var legacyTextChunk = pngFile.GetChunkReverse(PNGChunkTypeFilter.iTXt);
|
var legacyTextChunk = pngFile.GetChunkReverse(PNGChunkTypeFilter.iTXt);
|
||||||
if (legacyTextChunk.HasValue)
|
if (legacyTextChunk != null)
|
||||||
{
|
{
|
||||||
var data = legacyTextChunk.Value.ReadITXtChunk();
|
var data = legacyTextChunk.ReadITXtChunk();
|
||||||
if (data.Item1 == keyword)
|
if (data.Item1 == keyword)
|
||||||
return data.Item2;
|
return data.Item2;
|
||||||
}
|
}
|
||||||
@@ -91,7 +91,7 @@ namespace VRCX
|
|||||||
public static PNGChunk GenerateTextChunk(string keyword, string text)
|
public static PNGChunk GenerateTextChunk(string keyword, string text)
|
||||||
{
|
{
|
||||||
byte[] textBytes = Encoding.UTF8.GetBytes(text);
|
byte[] textBytes = Encoding.UTF8.GetBytes(text);
|
||||||
byte[] keywordBytes = Encoding.GetEncoding("ISO-8859-1").GetBytes(keyword);
|
byte[] keywordBytes = Encoding.UTF8.GetBytes(keyword);
|
||||||
|
|
||||||
List<byte> constructedTextChunk = new List<byte>();
|
List<byte> constructedTextChunk = new List<byte>();
|
||||||
constructedTextChunk.AddRange(keywordBytes);
|
constructedTextChunk.AddRange(keywordBytes);
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ namespace VRCX
|
|||||||
|
|
||||||
// Check for chunk only present in files created by older modded versions of vrchat. (LFS, screenshotmanager), which put their metadata at the end of the file (which is not in spec bro).
|
// Check for chunk only present in files created by older modded versions of vrchat. (LFS, screenshotmanager), which put their metadata at the end of the file (which is not in spec bro).
|
||||||
// Searching from the end of the file is a slower bruteforce operation so only do it if we have to.
|
// Searching from the end of the file is a slower bruteforce operation so only do it if we have to.
|
||||||
if (result.Count == 0 && pngFile.GetChunk(PNGChunkTypeFilter.sRGB).HasValue)
|
if (result.Count == 0 && pngFile.GetChunk(PNGChunkTypeFilter.sRGB) != null)
|
||||||
{
|
{
|
||||||
var lfsMetadata = PNGHelper.ReadTextChunk("Description", pngFile, true);
|
var lfsMetadata = PNGHelper.ReadTextChunk("Description", pngFile, true);
|
||||||
|
|
||||||
@@ -233,7 +233,11 @@ namespace VRCX
|
|||||||
{
|
{
|
||||||
using var pngFile = new PNGFile(path);
|
using var pngFile = new PNGFile(path);
|
||||||
var chunk = PNGHelper.GenerateTextChunk("Description", text);
|
var chunk = PNGHelper.GenerateTextChunk("Description", text);
|
||||||
return pngFile.WriteChunk(chunk);
|
pngFile.WriteChunk(chunk);
|
||||||
|
|
||||||
|
DeleteTextMetadata(path, true);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ScreenshotMetadata ParseVRCImage(string xmlString)
|
public static ScreenshotMetadata ParseVRCImage(string xmlString)
|
||||||
|
|||||||
Reference in New Issue
Block a user