Skip to content

Commit afab8c6

Browse files
committed
Optimized the project code
1 parent c2cd10b commit afab8c6

File tree

4 files changed

+126
-5
lines changed

4 files changed

+126
-5
lines changed

OpenBioCardServer/Controllers/Classic/ClassicSettingsController.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using OpenBioCardServer.Models.Entities;
55
using OpenBioCardServer.Models.Enums;
66
using OpenBioCardServer.Services;
7+
using OpenBioCardServer.Utilities;
78
using OpenBioCardServer.Utilities.Mappers;
89

910
namespace OpenBioCardServer.Controllers.Classic;
@@ -174,11 +175,13 @@ public async Task<IActionResult> UpdateSettings([FromBody] ClassicUpdateSettings
174175
}
175176
}
176177

177-
private static string AssetToString(AssetType type, string? text, byte[]? data) => type switch
178+
public static string AssetToString(AssetType type, string? text, byte[]? data) => type switch
178179
{
179180
AssetType.Text => text ?? string.Empty,
180181
AssetType.Remote => text ?? string.Empty,
181-
AssetType.Image => data != null ? $"data:image/png;base64,{Convert.ToBase64String(data)}" : string.Empty,
182+
AssetType.Image => data != null
183+
? $"data:{ImageHelper.DetectMimeType(data)};base64,{Convert.ToBase64String(data)}"
184+
: string.Empty,
182185
_ => string.Empty
183186
};
184187
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
namespace OpenBioCardServer.Utilities;
2+
3+
public static class Base64Validator
4+
{
5+
/// <summary>
6+
/// Calculate the approximate size of decoded Base64 data
7+
/// </summary>
8+
public static long CalculateBase64Size(string base64String)
9+
{
10+
if (string.IsNullOrEmpty(base64String))
11+
return 0;
12+
13+
// Remove data URL prefix if present
14+
var base64Data = base64String;
15+
if (base64String.StartsWith("data:"))
16+
{
17+
var commaIndex = base64String.IndexOf(',');
18+
if (commaIndex >= 0)
19+
{
20+
base64Data = base64String[(commaIndex + 1)..];
21+
}
22+
}
23+
24+
// Remove padding and calculate size
25+
var paddingCount = base64Data.EndsWith("==") ? 2 : base64Data.EndsWith("=") ? 1 : 0;
26+
var base64Length = base64Data.Length;
27+
28+
// Decoded size = (base64Length * 3) / 4 - paddingCount
29+
return (base64Length * 3L / 4) - paddingCount;
30+
}
31+
32+
/// <summary>
33+
/// Validate if Base64 string size is within limit
34+
/// </summary>
35+
public static (bool isValid, string? errorMessage) ValidateSize(
36+
string base64String,
37+
long maxSizeBytes,
38+
string fieldName = "File")
39+
{
40+
if (string.IsNullOrEmpty(base64String))
41+
return (true, null);
42+
43+
var estimatedSize = CalculateBase64Size(base64String);
44+
45+
if (estimatedSize > maxSizeBytes)
46+
{
47+
var maxSizeMB = maxSizeBytes / 1024.0 / 1024.0;
48+
var actualSizeMB = estimatedSize / 1024.0 / 1024.0;
49+
50+
return (false,
51+
$"{fieldName} size ({actualSizeMB:F2}MB) exceeds maximum allowed size ({maxSizeMB:F2}MB)");
52+
}
53+
54+
return (true, null);
55+
}
56+
57+
/// <summary>
58+
/// Validate image type from Base64 data URL
59+
/// </summary>
60+
public static (bool isValid, string? errorMessage) ValidateImageType(
61+
string base64String,
62+
IEnumerable<string> allowedTypes,
63+
string fieldName = "File")
64+
{
65+
if (string.IsNullOrEmpty(base64String))
66+
return (true, null);
67+
68+
if (!base64String.StartsWith("data:"))
69+
return (true, null); // Not a data URL, skip type check
70+
71+
var semicolonIndex = base64String.IndexOf(';');
72+
if (semicolonIndex < 0)
73+
return (false, $"{fieldName} has invalid data URL format");
74+
75+
var mimeType = base64String[5..semicolonIndex]; // Skip "data:"
76+
77+
if (!allowedTypes.Contains(mimeType, StringComparer.OrdinalIgnoreCase))
78+
{
79+
return (false,
80+
$"{fieldName} type '{mimeType}' is not allowed. " +
81+
$"Allowed types: {string.Join(", ", allowedTypes)}");
82+
}
83+
84+
return (true, null);
85+
}
86+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
namespace OpenBioCardServer.Utilities;
2+
3+
public static class ImageHelper
4+
{
5+
public static string DetectMimeType(byte[] data)
6+
{
7+
if (data == null || data.Length < 4)
8+
return "application/octet-stream";
9+
10+
// PNG: 89 50 4E 47
11+
if (data[0] == 0x89 && data[1] == 0x50 && data[2] == 0x4E && data[3] == 0x47)
12+
return "image/png";
13+
14+
// JPEG: FF D8 FF
15+
if (data[0] == 0xFF && data[1] == 0xD8 && data[2] == 0xFF)
16+
return "image/jpeg";
17+
18+
// GIF: 47 49 46 38
19+
if (data[0] == 0x47 && data[1] == 0x49 && data[2] == 0x46 && data[3] == 0x38)
20+
return "image/gif";
21+
22+
// WebP: 52 49 46 46 ... 57 45 42 50
23+
if (data.Length >= 12 &&
24+
data[0] == 0x52 && data[1] == 0x49 && data[2] == 0x46 && data[3] == 0x46 &&
25+
data[8] == 0x57 && data[9] == 0x45 && data[10] == 0x42 && data[11] == 0x50)
26+
return "image/webp";
27+
28+
return "application/octet-stream";
29+
}
30+
}

OpenBioCardServer/Utilities/Mappers/ClassicMapper.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,14 @@ public static ClassicProfile ToClassicProfile(ProfileEntity profile)
3535
Gallery = profile.Gallery.Select(ToClassicGalleryItem).ToList()
3636
};
3737
}
38-
39-
private static string AssetToString(AssetType type, string? text, byte[]? data) => type switch
38+
39+
public static string AssetToString(AssetType type, string? text, byte[]? data) => type switch
4040
{
4141
AssetType.Text => text ?? string.Empty,
4242
AssetType.Remote => text ?? string.Empty,
43-
AssetType.Image => data != null ? $"data:image/png;base64,{Convert.ToBase64String(data)}" : string.Empty,
43+
AssetType.Image => data != null
44+
? $"data:{ImageHelper.DetectMimeType(data)};base64,{Convert.ToBase64String(data)}"
45+
: string.Empty,
4446
_ => string.Empty
4547
};
4648

0 commit comments

Comments
 (0)