1
0
mirror of https://git.teknik.io/Teknikode/Teknik.git synced 2023-08-02 14:16:22 +02:00

Fixed range requests and consolidated data download

This commit is contained in:
Uncled1023 2022-05-25 23:30:14 -07:00
parent 22c5553d3a
commit dc76918300
6 changed files with 53 additions and 64 deletions

View File

@ -161,7 +161,7 @@ namespace Teknik.Areas.Paste.Controllers
Response.Headers.Add("Content-Disposition", cd.ToString());
return new BufferedFileStreamResult("application/octet-stream", async (response) => await ResponseHelper.StreamToOutput(response, true, new AesCounterStream(fileStream, false, keyBytes, ivBytes), contentSize, _config.PasteConfig.ChunkSize), false);
return new BufferedFileStreamResult("application/octet-stream", async (response) => await ResponseHelper.StreamToOutput(response, new AesCounterStream(fileStream, false, keyBytes, ivBytes), contentSize, _config.PasteConfig.ChunkSize), false);
default:
return View("~/Areas/Paste/Views/Paste/Full.cshtml", model);
}

View File

@ -83,7 +83,7 @@ namespace Teknik.Areas.Podcast.Controllers
[HttpGet]
[AllowAnonymous]
[ResponseCache(Duration = 31536000, Location = ResponseCacheLocation.Any)]
[ResponseCache(Duration = 31536000, Location = ResponseCacheLocation.Any, NoStore = false)]
[TrackDownload]
public IActionResult Download(int episode, string fileName)
{
@ -215,7 +215,7 @@ namespace Teknik.Areas.Podcast.Controllers
// Reset file stream to starting position (or start of range)
fileStream.Seek(startByte, SeekOrigin.Begin);
return new BufferedFileStreamResult(contentType, (response) => ResponseHelper.StreamToOutput(response, true, fileStream, (int)length, 4 * 1024), false);
return new BufferedFileStreamResult(contentType, (response) => ResponseHelper.StreamToOutput(response, fileStream, (int)length, 4 * 1024), false);
}
}
return new StatusCodeResult(StatusCodes.Status404NotFound);

View File

@ -397,28 +397,7 @@ namespace Teknik.Areas.Upload.Controllers
// Reset file stream to starting position (or start of range)
fileStream.Seek(startByte, SeekOrigin.Begin);
try
{
// If the IV is set, and Key is set, then decrypt it while sending
if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(iv))
{
byte[] keyBytes = Encoding.UTF8.GetBytes(key);
byte[] ivBytes = Encoding.UTF8.GetBytes(iv);
var aesStream = new AesCounterStream(fileStream, false, keyBytes, ivBytes);
return new BufferedFileStreamResult(contentType, async (response) => await ResponseHelper.StreamToOutput(response, true, aesStream, (int)length, _config.UploadConfig.ChunkSize), false);
}
else // Otherwise just send it
{
// Send the file
return new BufferedFileStreamResult(contentType, async (response) => await ResponseHelper.StreamToOutput(response, true, fileStream, (int)length, _config.UploadConfig.ChunkSize), false);
}
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Error in Download: {url}", new { url });
}
return DownloadData(url, fileStream, contentType, (int)length, key, iv);
}
}
return new StatusCodeResult(StatusCodes.Status404NotFound);
@ -462,19 +441,7 @@ namespace Teknik.Areas.Upload.Controllers
Response.Headers.Add("Content-Disposition", cd.ToString());
// If the IV is set, and Key is set, then decrypt it while sending
if (decrypt && !string.IsNullOrEmpty(upload.Key) && !string.IsNullOrEmpty(upload.IV))
{
byte[] keyBytes = Encoding.UTF8.GetBytes(upload.Key);
byte[] ivBytes = Encoding.UTF8.GetBytes(upload.IV);
return new BufferedFileStreamResult(upload.ContentType, (response) => ResponseHelper.StreamToOutput(response, true, new AesCounterStream(fileStream, false, keyBytes, ivBytes), (int)upload.ContentLength, _config.UploadConfig.ChunkSize), false);
}
else // Otherwise just send it
{
// Send the file
return new BufferedFileStreamResult(upload.ContentType, (response) => ResponseHelper.StreamToOutput(response, true, fileStream, (int)upload.ContentLength, _config.UploadConfig.ChunkSize), false);
}
return DownloadData(upload.Url, fileStream, upload.ContentType, (int)upload.ContentLength, upload.Key, upload.IV);
}
}
return Json(new { error = new { message = "File Does Not Exist" } });
@ -540,5 +507,33 @@ namespace Teknik.Areas.Upload.Controllers
}
return Json(new { error = new { message = "This Upload does not exist" } });
}
private IActionResult DownloadData(string url, Stream fileStream, string contentType, int length, string key, string iv)
{
try
{
// If the IV is set, and Key is set, then decrypt it while sending
if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(iv))
{
byte[] keyBytes = Encoding.UTF8.GetBytes(key);
byte[] ivBytes = Encoding.UTF8.GetBytes(iv);
var aesStream = new AesCounterStream(fileStream, false, keyBytes, ivBytes);
//return File(aesStream, contentType, true);
return new BufferedFileStreamResult(contentType, async (response) => await ResponseHelper.StreamToOutput(response, aesStream, length, _config.UploadConfig.ChunkSize), false);
}
else // Otherwise just send it
{
// Send the file
return new BufferedFileStreamResult(contentType, async (response) => await ResponseHelper.StreamToOutput(response, fileStream, length, _config.UploadConfig.ChunkSize), false);
}
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Error in Download: {url}", new { url });
}
return new StatusCodeResult(StatusCodes.Status500InternalServerError);
}
}
}

View File

@ -54,10 +54,10 @@ namespace Teknik.Utilities.Cryptography
}
}
public class CounterModeCryptoTransform : ICryptoTransform
public class CounterModeCryptoTransform : ICryptoTransform, IDisposable
{
private readonly int _BlockSize;
private readonly Memory<byte> _IV;
private readonly byte[] _IV;
private readonly byte[] _Counter;
private readonly byte[] _EncryptedCounter;
private readonly ICryptoTransform _CounterEncryptor;
@ -103,13 +103,17 @@ namespace Teknik.Utilities.Cryptography
_BlockSize = symmetricAlgorithm.BlockSize;
// Initialize Counter
_Counter = new byte[initialCounter.Length];
initialCounter.CopyTo(_Counter, 0);
// Initialize the encrypted counter
_EncryptedCounter = new byte[_BlockSize / 8];
_IV = iv;
// Initialize IV
_IV = new byte[iv.Length];
iv.CopyTo(_IV, 0);
_Counter = initialCounter;
_CounterEncryptor = symmetricAlgorithm.CreateEncryptor(key, iv);
// Initialize State
@ -204,7 +208,7 @@ namespace Teknik.Utilities.Cryptography
public void ResetCounter()
{
_IV.CopyTo(_Counter);
_IV.CopyTo(_Counter, 0);
_Iterations = 0;
}

View File

@ -45,7 +45,7 @@ namespace Teknik.Utilities.Cryptography
int processed = 0;
// Read the data from the stream
int bytesRead = await _Inner.ReadAsync(buffer);
int bytesRead = await _Inner.ReadAsync(buffer).ConfigureAwait(false);
if (bytesRead > 0)
{
// Process the read buffer
@ -128,21 +128,20 @@ namespace Teknik.Utilities.Cryptography
if (_Inner != null && CanWrite)
{
// Process the cipher
Memory<byte> output = buffer;
Span<byte> output = buffer;
// Process the buffer
int processed = _Cipher.TransformBlock(output.Span, offset, count);
int processed = _Cipher.TransformBlock(output, offset, count);
// Do we have more?
if (processed < count)
{
// Finalize the cipher
var finalProcessed = _Cipher.TransformFinalBlock(output.Span, processed + offset, count);
var finalProcessed = _Cipher.TransformFinalBlock(output, processed + offset, count);
if (finalProcessed > 0)
processed += finalProcessed;
}
ReadOnlyMemory<byte> readOnlyOutput = buffer;
_Inner.Write(readOnlyOutput.Span);
_Inner.Write(output);
}
}
@ -255,12 +254,6 @@ namespace Teknik.Utilities.Cryptography
base.Dispose(disposing);
}
public override async ValueTask DisposeAsync()
{
await _Inner.DisposeAsync();
await base.DisposeAsync();
}
private void SyncCounter()
{
if (_Cipher != null)

View File

@ -11,8 +11,9 @@ namespace Teknik.Utilities
{
public static class ResponseHelper
{
public async static Task StreamToOutput(HttpResponse response, bool flush, Stream stream, int length, int chunkSize)
public async static Task StreamToOutput(HttpResponse response, Stream stream, int length, int chunkSize)
{
response.RegisterForDisposeAsync(stream);
var bufferSize = chunkSize;
if (length < chunkSize)
bufferSize = length;
@ -27,11 +28,7 @@ namespace Teknik.Utilities
{
await response.Body.WriteAsync(buffer.Slice(0, processedBytes));
// Flush the response
if (flush)
{
//await response.Body.FlushAsync();
}
await response.Body.FlushAsync();
}
}
while (processedBytes > 0);
@ -42,10 +39,10 @@ namespace Teknik.Utilities
}
finally
{
//await response.Body.FlushAsync();
await response.Body.FlushAsync();
// dispose of file stream
stream?.Dispose();
//stream?.Dispose();
}
}
}