18using System.Collections.Generic;
29 public class Base64Helper
31 private byte[] _decodedBytes;
32 private string _suggestedExtension =
".bin";
34 internal Base64Helper()
45 string cleaned = base64String.Trim();
49 _decodedBytes = Convert.FromBase64String(cleaned);
51 catch (FormatException ex)
53 GPAL.
PublishSimpleEvent(Enums.GPALEventType.EXCEPTION,
"Invalid base64 string.", base64String, Enums.GPALObjectType.Other, ex);
56 if (_decodedBytes ==
null || _decodedBytes.Length == 0)
58 GPAL.
PublishSimpleEvent(Enums.GPALEventType.WARNING,
"Decoded base64 resulted in empty data.", base64String, Enums.GPALObjectType.Other);
62 _suggestedExtension = FileTypeGuesser.GuessExtensionFromBytes(_decodedBytes);
77 string finalPath = ApplySuggestedExtension(filename.
Filename, _suggestedExtension);
79 File.WriteAllBytes(finalPath, _decodedBytes);
97 if (
string.IsNullOrEmpty(text))
return string.Empty;
98 byte[] bytes = Encoding.UTF8.GetBytes(text);
99 return Convert.ToBase64String(bytes);
110 if (
string.IsNullOrWhiteSpace(base64String))
113 bytes = Convert.FromBase64String(base64String.Trim());
115 return Encoding.UTF8.GetString(bytes);
118 private static string ApplySuggestedExtension(
string filename,
string suggestedExt)
120 string ext = Path.GetExtension(filename).ToLowerInvariant();
122 if (
string.IsNullOrEmpty(ext) || ext ==
".txt" || ext ==
".dat" || ext ==
".bin")
124 string dir = Path.GetDirectoryName(filename) ??
"";
125 string nameWithoutExt = Path.GetFileNameWithoutExtension(filename);
126 return Path.Combine(dir, nameWithoutExt + suggestedExt);
132 public static string GuessExtensionFromBytes(
byte[] bytes)
134 return FileTypeGuesser.GuessExtensionFromBytes(bytes);
139 internal static class FileTypeGuesser
142 private class FileSignature
144 public string Extension;
145 public byte[] Pattern;
150 private static readonly List<FileSignature> Signatures =
new List<FileSignature>
153 new FileSignature { Extension =
".pdf", Pattern =
new byte[] { 0x25, 0x50, 0x44, 0x46 }, Offset = 0 },
159 Pattern =
new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A },
164 new FileSignature { Extension =
".jpg", Pattern =
new byte[] { 0xFF, 0xD8 }, Offset = 0 },
167 new FileSignature { Extension =
".gif", Pattern = Encoding.ASCII.GetBytes(
"GIF87a"), Offset = 0 },
168 new FileSignature { Extension =
".gif", Pattern = Encoding.ASCII.GetBytes(
"GIF89a"), Offset = 0 },
171 new FileSignature { Extension =
".bmp", Pattern = Encoding.ASCII.GetBytes(
"BM"), Offset = 0 },
174 new FileSignature { Extension =
".zip", Pattern =
new byte[] { 0x50, 0x4B, 0x03, 0x04 }, Offset = 0 },
177 new FileSignature { Extension =
".rar", Pattern = Encoding.ASCII.GetBytes(
"Rar!"), Offset = 0 },
183 Pattern =
new byte[] { 0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C },
188 new FileSignature { Extension =
".mp3", Pattern = Encoding.ASCII.GetBytes(
"ID3"), Offset = 0 },
191 new FileSignature { Extension =
".mp4", Pattern = Encoding.ASCII.GetBytes(
"ftyp"), Offset = 4 },
194 new FileSignature { Extension =
".wav", Pattern = Encoding.ASCII.GetBytes(
"RIFF"), Offset = 0 }
198 internal static string GuessExtensionFromBytes(
byte[] bytes)
200 if (bytes ==
null || bytes.Length < 4)
203 foreach (var sig
in Signatures)
205 if (IsMatch(bytes, sig))
208 if (sig.Extension ==
".zip")
209 return DetectZipSubtype(bytes);
211 return sig.Extension;
219 private static bool IsMatch(
byte[] bytes, FileSignature sig)
221 if (bytes.Length < sig.Offset + sig.Pattern.Length)
224 for (
int i = 0; i < sig.Pattern.Length; i++)
226 if (bytes[sig.Offset + i] != sig.Pattern[i])
234 private static string DetectZipSubtype(
byte[] bytes)
236 int scanLength = Math.Min(bytes.Length, 3000);
237 string headerText = Encoding.ASCII.GetString(bytes, 0, scanLength);
239 if (headerText.Contains(
"word/"))
242 if (headerText.Contains(
"xl/"))
245 if (headerText.Contains(
"ppt/"))
string SuggestedExtension
Returns the detected/suggested file extension for the decoded content. Useful for logging,...
void SaveTo(GPALFile filename)
Saves the decoded bytes to the specified file path. Uses the suggested extension if the filename lack...
static string DecodeFromBase64(string base64String)
Decodes a base64 string to UTF-8 text. Throws if the result is not valid UTF-8 or input is invalid ba...
Base64Helper WithInput(string base64String)
Sets the base64 input string to work with. Returns this instance for simple chaining: WithInput(....
static string EncodeToBase64(string text)
Encodes a plain string to base64 using UTF-8 encoding.
GPAL File object instantied with GPAL.File Used to load tokens into a GPALGrid [rows/columns].
string Filename
We have only one file, accessing it.
Everything starts here, all the GPAL controls and global settings using fluent syntax are here....
static void PublishSimpleEvent(GPALEventType gPALEventType, string msg, dynamic gPALObject=null, Enums.GPALObjectType gPALObjectType=GPALObjectType.None, Exception ex=null)
Publish a message to either the information channel or exception channel (if exception passed in) Pub...