Browse Source

- Added better error handling in download function.

- Fixed script passthrough to downloads.
pull/50/head
Teknikode 6 years ago
parent
commit
e7f02471e5
  1. 116
      Teknik/Areas/Upload/Controllers/UploadController.cs
  2. 5
      Teknik/Areas/Upload/Scripts/Download.js
  3. 4
      Utilities/Utilities/FileGenerateResult.cs
  4. 2
      Utilities/Utilities/Utilities.csproj

116
Teknik/Areas/Upload/Controllers/UploadController.cs

@ -264,19 +264,22 @@ namespace Teknik.Areas.Upload.Controllers @@ -264,19 +264,22 @@ namespace Teknik.Areas.Upload.Controllers
// Reset file stream to starting position (or start of range)
fs.Seek(startByte, SeekOrigin.Begin);
// If the IV is set, and Key is set, then decrypt it before sending
// If the IV is set, and Key is set, then decrypt it while sending
if (!string.IsNullOrEmpty(upload.Key) && !string.IsNullOrEmpty(upload.IV))
{
byte[] keyBytes = Encoding.UTF8.GetBytes(upload.Key);
byte[] ivBytes = Encoding.UTF8.GetBytes(upload.IV);
return new FileDecryptResult(upload.Url, contentType, (response) => this.GenerateExportFile(response, fs, (int)length, keyBytes, ivBytes, "CTR", "NoPadding", 4 * 1024), false);
return new FileGenerateResult(upload.Url,
contentType,
(response) => this.DecryptStreamToOutput(response, fs, (int)length, keyBytes, ivBytes, "CTR", "NoPadding", Config.UploadConfig.ChunkSize),
false);
}
else
else // Otherwise just send it
{
// Don't buffer the response
Response.Buffer = false;
// Otherwise just send it
// Send the file
return File(fs, contentType);
}
}
@ -288,48 +291,73 @@ namespace Teknik.Areas.Upload.Controllers @@ -288,48 +291,73 @@ namespace Teknik.Areas.Upload.Controllers
return Redirect(Url.SubRouteUrl("error", "Error.Http403"));
}
public void GenerateExportFile(HttpResponseBase response, System.IO.Stream fileStream, int length, byte[] key, byte[] iv, string mode, string padding, int chunkSize)
public void DecryptStreamToOutput(HttpResponseBase response, System.IO.Stream fileStream, int length, byte[] key, byte[] iv, string mode, string padding, int chunkSize)
{
response.Flush();
IBufferedCipher cipher = AES.CreateCipher(false, key, iv, mode, padding);
int curByte = 0;
int processedBytes = 0;
byte[] buffer = new byte[chunkSize];
int bytesToRead = chunkSize;
do
try
{
if (curByte + chunkSize > length)
response.Flush();
IBufferedCipher cipher = AES.CreateCipher(false, key, iv, mode, padding);
int curByte = 0;
int processedBytes = 0;
byte[] buffer = new byte[chunkSize];
int bytesRemaining = length;
int bytesToRead = chunkSize;
do
{
bytesToRead = chunkSize - ((curByte + bytesToRead) - length);
if (chunkSize > bytesRemaining)
{
bytesToRead = bytesRemaining;
}
processedBytes = AES.ProcessCipherBlock(cipher, fileStream, bytesToRead, buffer, 0);
if (processedBytes > 0)
{
response.OutputStream.Write(buffer, 0, processedBytes);
response.Flush();
// Clear the buffer
Array.Clear(buffer, 0, chunkSize);
}
curByte += processedBytes;
bytesRemaining -= processedBytes;
}
processedBytes = AES.ProcessCipherBlock(cipher, fileStream, bytesToRead, buffer, 0);
if (processedBytes > 0)
{
response.OutputStream.Write(buffer, 0, processedBytes);
response.Flush();
while (processedBytes > 0 && bytesRemaining > 0);
if (bytesRemaining > 0)
{
// Clear the buffer
Array.Clear(buffer, 0, chunkSize);
// Finalize processing of the cipher
processedBytes = AES.FinalizeCipherBlock(cipher, buffer, 0);
if (processedBytes > 0)
{
// We have bytes, lets write them to the output
response.OutputStream.Write(buffer, 0, processedBytes);
response.Flush();
}
}
curByte += processedBytes;
}
while (processedBytes > 0 && curByte <= length);
// Clear the buffer
Array.Clear(buffer, 0, chunkSize);
// Finalize processing of the cipher
processedBytes = AES.FinalizeCipherBlock(cipher, buffer, 0);
if (processedBytes > 0)
catch (HttpException httpEx)
{
// We have bytes, lets write them to the output
response.OutputStream.Write(buffer, 0, processedBytes);
response.Flush();
if (httpEx.ErrorCode == -2147023667)
{
// do nothing
}
else
{
Logging.Logger.WriteEntry(httpEx);
}
}
catch (Exception ex)
{
Logging.Logger.WriteEntry(ex);
}
finally
{
// dispose of file stream
fileStream.Dispose();
}
// dispose of file stream
fileStream.Dispose();
}
[HttpPost]
@ -345,24 +373,8 @@ namespace Teknik.Areas.Upload.Controllers @@ -345,24 +373,8 @@ namespace Teknik.Areas.Upload.Controllers
string filePath = Path.Combine(Config.UploadConfig.UploadDirectory, subDir, upload.FileName);
if (System.IO.File.Exists(filePath))
{
byte[] buffer;
FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
try
{
int length = (int)fileStream.Length; // get file length
buffer = new byte[length]; // create buffer
int count; // actual number of bytes read
int sum = 0; // total number of bytes read
// read until Read method returns 0 (end of the stream has been reached)
while ((count = fileStream.Read(buffer, sum, length - sum)) > 0)
sum += count; // sum is a buffer offset for next reading
}
finally
{
fileStream.Close();
}
return File(buffer, System.Net.Mime.MediaTypeNames.Application.Octet, file);
return File(fileStream, System.Net.Mime.MediaTypeNames.Application.Octet, file);
}
}
Redirect(Url.SubRouteUrl("error", "Error.Http404"));

5
Teknik/Areas/Upload/Scripts/Download.js

@ -45,11 +45,14 @@ function downloadFile() { @@ -45,11 +45,14 @@ function downloadFile() {
$("#progress").children('.progress-bar').html('Error Occured');
}
// Create a blob for the aes script
var scriptBlob = GenerateBlobURL(aesScriptSrc);
// Execute worker with data
var objData =
{
cmd: 'decrypt',
script: aesScriptSrc,
script: scriptBlob,
key: key,
iv: iv,
chunkSize: chunkSize,

4
Utilities/Utilities/FileDecryptResult.cs → Utilities/Utilities/FileGenerateResult.cs

@ -13,7 +13,7 @@ namespace Teknik.Utilities @@ -13,7 +13,7 @@ namespace Teknik.Utilities
/// <summary>
/// MVC action result that generates the file content using a delegate that writes the content directly to the output stream.
/// </summary>
public class FileDecryptResult : FileResult
public class FileGenerateResult : FileResult
{
private readonly Action<HttpResponseBase> responseDelegate;
@ -26,7 +26,7 @@ namespace Teknik.Utilities @@ -26,7 +26,7 @@ namespace Teknik.Utilities
/// <param name="contentType">Type of the content.</param>
/// <param name="content">Delegate with Stream parameter. This is the stream to which content should be written.</param>
/// <param name="bufferOutput">use output buffering. Set to false for large files to prevent OutOfMemoryException.</param>
public FileDecryptResult(string fileName, string contentType, Action<HttpResponseBase> response, bool bufferOutput)
public FileGenerateResult(string fileName, string contentType, Action<HttpResponseBase> response, bool bufferOutput)
: base(contentType)
{
if (response == null)

2
Utilities/Utilities/Utilities.csproj

@ -105,7 +105,7 @@ @@ -105,7 +105,7 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="FileDecryptResult.cs" />
<Compile Include="FileGenerateResult.cs" />
<Compile Include="HttpWebResponseResult.cs" />
<Compile Include="BundleExtensions.cs" />
<Compile Include="ByteExtensions.cs" />

Loading…
Cancel
Save