Skip to content

Commit

Permalink
use helper
Browse files Browse the repository at this point in the history
  • Loading branch information
MikeAlhayek committed Nov 7, 2024
1 parent 3edaeaf commit 4c00119
Show file tree
Hide file tree
Showing 15 changed files with 144 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ protected override async Task HandleAsync(RecipeExecutionContext context)

if (!string.IsNullOrWhiteSpace(file.Base64))
{
stream = new MemoryStream(Convert.FromBase64String(file.Base64));
stream = MemoryStreamFactory.GetStream();
stream.Write(Str.FromBase64String(file.Base64));
}
else if (!string.IsNullOrWhiteSpace(file.SourcePath))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ public AdminController(
[Admin("Queries/Sql/Query", "QueriesRunSql")]
public Task<IActionResult> Query(string query)
{
query = string.IsNullOrWhiteSpace(query) ? "" : System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(query));
query = string.IsNullOrWhiteSpace(query)
? ""
: System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(query));

return Query(new AdminQueryViewModel
{
DecodedQuery = query,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Diagnostics;
using System.Globalization;
using System.Text;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Nodes;
Expand Down Expand Up @@ -466,7 +467,9 @@ public async Task<IActionResult> Query(string indexName, string query)
return await Query(new AdminQueryViewModel
{
IndexName = indexName,
DecodedQuery = string.IsNullOrWhiteSpace(query) ? string.Empty : System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(query))
DecodedQuery = string.IsNullOrWhiteSpace(query)
? string.Empty
: Encoding.UTF8.GetString(Str.FromBase64String(query))
});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Diagnostics;
using System.Globalization;
using System.Text;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Nodes;
Expand Down Expand Up @@ -355,7 +356,10 @@ public async Task<ActionResult> Delete(LuceneIndexSettingsViewModel model)

public Task<IActionResult> Query(string indexName, string query)
{
query = string.IsNullOrWhiteSpace(query) ? "" : System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(query));
query = string.IsNullOrWhiteSpace(query)
? ""
: Encoding.UTF8.GetString(Str.FromBase64String(query));

return Query(new AdminQueryViewModel { IndexName = indexName, DecodedQuery = query });
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ public async Task<IActionResult> ResetPasswordPOST()

if (ModelState.IsValid)
{
var token = Encoding.UTF8.GetString(Convert.FromBase64String(model.ResetToken));
var token = Encoding.UTF8.GetString(Str.FromBase64String(model.ResetToken));

if (await _userService.ResetPasswordAsync(model.UsernameOrEmail, token, model.NewPassword, ModelState.AddModelError))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public XmlRpcReader()
return new XRpcData<DateTime> { Value = parsedDateTime };
} },
{ "base64", x => new XRpcData<byte[]> { Value = Convert.FromBase64String((string)x) } },
{ "base64", x => new XRpcData<byte[]> { Value = Str.FromBase64String((string)x).ToArray() } },
{ "struct", x => XRpcData.For(MapToStruct(x)) },
{ "array", x => XRpcData.For(MapToArray(x)) },
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Numerics;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
using OrchardCore;

namespace System.Text.Json.Dynamic;

Expand Down Expand Up @@ -453,7 +454,7 @@ public static explicit operator ulong(JsonDynamicValue value)
{
if (value?._jsonValue.GetObjectValue() is string str)
{
return Convert.FromBase64String(str);
return Str.FromBase64String(str).ToArray();
}

throw new InvalidCastException($"Cannot convert {value} to Byte array");
Expand Down
55 changes: 55 additions & 0 deletions src/OrchardCore/OrchardCore.Abstractions/Str.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using System.Text;

namespace OrchardCore;

public static class Str
{
public static ReadOnlySpan<byte> FromBase64String(string base64)
{
if (string.IsNullOrEmpty(base64))
{
return [];
}
var neededLength = GetByteArrayLengthFromBase64(base64);

using var memoryStream = MemoryStreamFactory.GetStream(neededLength);

Check failure on line 15 in src/OrchardCore/OrchardCore.Abstractions/Str.cs

View workflow job for this annotation

GitHub Actions / Build & Test (ubuntu-latest)

The name 'MemoryStreamFactory' does not exist in the current context

Check failure on line 15 in src/OrchardCore/OrchardCore.Abstractions/Str.cs

View workflow job for this annotation

GitHub Actions / Build & Test (ubuntu-latest)

The name 'MemoryStreamFactory' does not exist in the current context

Check failure on line 15 in src/OrchardCore/OrchardCore.Abstractions/Str.cs

View workflow job for this annotation

GitHub Actions / Build & Test (windows-latest)

The name 'MemoryStreamFactory' does not exist in the current context

Check failure on line 15 in src/OrchardCore/OrchardCore.Abstractions/Str.cs

View workflow job for this annotation

GitHub Actions / Build & Test (windows-latest)

The name 'MemoryStreamFactory' does not exist in the current context
var bytes = memoryStream.GetSpan(neededLength);

if (!Convert.TryFromBase64String(base64, bytes, out var _))
{
throw new FormatException("Invalid Base64 string.");
}

return bytes;
}

public static bool TryFromBase64String(string base64, out ReadOnlySpan<byte> bytes)
{
if (string.IsNullOrEmpty(base64))
{
bytes = [];

return false;
}

Span<byte> data = new byte[GetByteArrayLengthFromBase64(base64)];

if (!Convert.TryFromBase64String(base64, data, out var _))
{
bytes = [];

return false;
}

bytes = data;

return true;
}

// Base64 string length gives us the original byte length. It encodes 3 bytes into 4 characters.
// The formula to calculate the number of bytes from the base64 string length is:
private static int GetByteArrayLengthFromBase64(string base64String)
{
return (base64String.Length * 3) / 4;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,7 @@ public static class MemoryStreamFactory

public static RecyclableMemoryStream GetStream(string tag = null)
=> _manager.GetStream(tag);

public static RecyclableMemoryStream GetStream(int requiredSize, string tag = null)
=> _manager.GetStream(tag, requiredSize);
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ public Task<byte[]> SerializeAsync<TDocument>(TDocument document, int compressTh
var data = JsonSerializer.SerializeToUtf8Bytes(document, _serializerOptions);
if (data.Length >= compressThreshold)
{
data = Compress(data).ToArray();
var stream = MemoryStreamFactory.GetStream();
var length = Compress(data, stream);

data = stream.GetBuffer().AsSpan().Slice(0, length).ToArray();
}

return Task.FromResult(data);
Expand Down Expand Up @@ -59,15 +62,14 @@ internal static bool IsCompressed(byte[] data)
return false;
}

internal static ReadOnlySpan<byte> Compress(byte[] data)
internal static int Compress(byte[] data, Stream output)
{
using var input = new MemoryStream(data);
using var output = MemoryStreamFactory.GetStream();
using var gZip = new GZipStream(output, CompressionMode.Compress);

input.CopyTo(gZip);

return output.GetBuffer().AsSpan().Slice(0, (int)gZip.Length);
return (int)gZip.Length;
}

internal static ReadOnlySpan<byte> Decompress(byte[] data)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,7 @@ public class CommonGeneratorMethods : IGlobalMethodProvider
Name = "base64",
Method = serviceProvider => (Func<string, string>)(encoded =>
{
var neededLength = GetByteArrayLengthFromBase64(encoded);
Span<byte> bytes = new byte[neededLength];
if (!Convert.TryFromBase64String(encoded, bytes, out var bytesWritten))
{
throw new FormatException("Invalid Base64 string.");
}
return Encoding.UTF8.GetString(bytes);
return Encoding.UTF8.GetString(Str.FromBase64String(encoded));
}),
};

Expand All @@ -41,17 +33,8 @@ public class CommonGeneratorMethods : IGlobalMethodProvider
Name = "gzip",
Method = serviceProvider => (Func<string, string>)(encoded =>
{
var neededLength = GetByteArrayLengthFromBase64(encoded);
Span<byte> bytes = new byte[neededLength];
if (!Convert.TryFromBase64String(encoded, bytes, out var _))
{
throw new FormatException("Invalid Base64 string.");
}
using var stream = MemoryStreamFactory.GetStream();
stream.Write(bytes);
stream.Write(Str.FromBase64String(encoded));
stream.Seek(0, SeekOrigin.Begin);
using var gZip = new GZipStream(stream, CompressionMode.Decompress, leaveOpen: true);
Expand All @@ -71,11 +54,4 @@ public class CommonGeneratorMethods : IGlobalMethodProvider

public IEnumerable<GlobalMethod> GetMethods()
=> new[] { _base64, _html, _gZip };

// Base64 string length gives us the original byte length. It encodes 3 bytes into 4 characters.
// The formula to calculate the number of bytes from the base64 string length is:
private static int GetByteArrayLengthFromBase64(string base64String)
{
return (base64String.Length * 3) / 4;
}
}
55 changes: 55 additions & 0 deletions src/OrchardCore/OrchardCore/Str.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using System.Text;

namespace OrchardCore;

public static class Str
{
public static ReadOnlySpan<byte> FromBase64String(string base64)
{
if (string.IsNullOrEmpty(base64))
{
return [];
}
var neededLength = GetByteArrayLengthFromBase64(base64);

using var memoryStream = MemoryStreamFactory.GetStream(neededLength);
var bytes = memoryStream.GetSpan(neededLength);

if (!Convert.TryFromBase64String(base64, bytes, out var _))
{
throw new FormatException("Invalid Base64 string.");
}

return bytes;
}

public static bool TryFromBase64String(string base64, out ReadOnlySpan<byte> bytes)
{
if (string.IsNullOrEmpty(base64))
{
bytes = [];

return false;
}

Span<byte> data = new byte[GetByteArrayLengthFromBase64(base64)];

if (!Convert.TryFromBase64String(base64, data, out var _))
{
bytes = [];

return false;
}

bytes = data;

return true;
}

// Base64 string length gives us the original byte length. It encodes 3 bytes into 4 characters.
// The formula to calculate the number of bytes from the base64 string length is:
private static int GetByteArrayLengthFromBase64(string base64String)
{
return (base64String.Length * 3) / 4;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public async Task<HttpResponseMessage> PostRecipeAsync(JsonObject recipe, bool e
recipe.WriteTo(streamWriter);
}

zipStream.Position = 0;
zipStream.Seek(0, SeekOrigin.Begin);

using var requestContent = new MultipartFormDataContent
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ public async Task<Stream> MediaCreatingAsync(MediaCreatingContext context, Strea
{
var outStream = MemoryStreamFactory.GetStream();
await inputStream.CopyToAsync(outStream);
outStream.Seek(0, SeekOrigin.Begin);

return outStream;
}
Expand Down
2 changes: 2 additions & 0 deletions test/OrchardCore.Tests/Stubs/MemoryFileBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ public async Task SetFileAsync(string subpath, Stream stream)
{
using var ms = MemoryStreamFactory.GetStream();
await stream.CopyToAsync(ms);
ms.Seek(0, SeekOrigin.Begin);

VirtualFiles[subpath] = ms.GetBuffer().AsSpan().Slice((int)ms.Length).ToArray();
}

Expand Down

0 comments on commit 4c00119

Please sign in to comment.