1
0
mirror of https://github.com/bitwarden/server.git synced 2025-06-30 15:42:48 -05:00

support for attachments keys

load existing items and set attachments on key update
This commit is contained in:
Kyle Spearrin
2018-11-14 17:19:04 -05:00
parent 73cc221deb
commit 7cda459127
11 changed files with 138 additions and 68 deletions

View File

@ -13,40 +13,54 @@ namespace Bit.Api.Utilities
{
private static readonly FormOptions _defaultFormOptions = new FormOptions();
public static async Task GetFileAsync(this HttpRequest request, Func<Stream, string, Task> callback)
{
await request.GetFilesAsync(1, callback);
}
private static async Task GetFilesAsync(this HttpRequest request, int? fileCount, Func<Stream, string, Task> callback)
public static async Task GetFileAsync(this HttpRequest request, Func<Stream, string, string, Task> callback)
{
var boundary = GetBoundary(MediaTypeHeaderValue.Parse(request.ContentType),
_defaultFormOptions.MultipartBoundaryLengthLimit);
var reader = new MultipartReader(boundary, request.Body);
var section = await reader.ReadNextSectionAsync();
var fileNumber = 1;
while(section != null && fileNumber <= fileCount)
var firstSection = await reader.ReadNextSectionAsync();
if(firstSection != null)
{
if(ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var content) &&
HasFileContentDisposition(content))
if(ContentDispositionHeaderValue.TryParse(firstSection.ContentDisposition, out var firstContent))
{
var fileName = HeaderUtilities.RemoveQuotes(content.FileName).ToString();
using(section.Body)
if(HasFileContentDisposition(firstContent))
{
await callback(section.Body, fileName);
// Old style with just data
var fileName = HeaderUtilities.RemoveQuotes(firstContent.FileName).ToString();
using(firstSection.Body)
{
await callback(firstSection.Body, fileName, null);
}
}
else if(HasKeyDisposition(firstContent))
{
// New style with key, then data
string key = null;
using(var sr = new StreamReader(firstSection.Body))
{
key = await sr.ReadToEndAsync();
}
var secondSection = await reader.ReadNextSectionAsync();
if(secondSection != null)
{
if(ContentDispositionHeaderValue.TryParse(secondSection.ContentDisposition,
out var secondContent) && HasFileContentDisposition(secondContent))
{
var fileName = HeaderUtilities.RemoveQuotes(secondContent.FileName).ToString();
using(secondSection.Body)
{
await callback(secondSection.Body, fileName, key);
}
}
secondSection = null;
}
}
}
if(fileNumber >= fileCount)
{
section = null;
}
else
{
section = await reader.ReadNextSectionAsync();
fileNumber++;
}
firstSection = null;
}
}
@ -68,9 +82,15 @@ namespace Bit.Api.Utilities
private static bool HasFileContentDisposition(ContentDispositionHeaderValue content)
{
// Content-Disposition: form-data; name="myfile1"; filename="Misc 002.jpg"
// Content-Disposition: form-data; name="data"; filename="Misc 002.jpg"
return content != null && content.DispositionType.Equals("form-data") &&
(!StringSegment.IsNullOrEmpty(content.FileName) || !StringSegment.IsNullOrEmpty(content.FileNameStar));
}
private static bool HasKeyDisposition(ContentDispositionHeaderValue content)
{
// Content-Disposition: form-data; name="key";
return content != null && content.DispositionType.Equals("form-data") && content.Name == "key";
}
}
}