mirror of
https://github.com/bitwarden/server.git
synced 2025-07-01 08:02:49 -05:00
attachment apis and azure storage service
This commit is contained in:
30
src/Api/Utilities/DisableFormValueModelBindingAttribute.cs
Normal file
30
src/Api/Utilities/DisableFormValueModelBindingAttribute.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Bit.Api.Utilities
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
||||
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
|
||||
{
|
||||
public void OnResourceExecuting(ResourceExecutingContext context)
|
||||
{
|
||||
var formValue = context.ValueProviderFactories.OfType<FormValueProviderFactory>().FirstOrDefault();
|
||||
if(formValue != null)
|
||||
{
|
||||
context.ValueProviderFactories.Remove(formValue);
|
||||
}
|
||||
|
||||
var jqFormValue = context.ValueProviderFactories.OfType<JQueryFormValueProviderFactory>().FirstOrDefault();
|
||||
if(jqFormValue != null)
|
||||
{
|
||||
context.ValueProviderFactories.Remove(jqFormValue);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnResourceExecuted(ResourceExecutedContext context)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
58
src/Api/Utilities/MultipartFormDataHelper.cs
Normal file
58
src/Api/Utilities/MultipartFormDataHelper.cs
Normal file
@ -0,0 +1,58 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Bit.Api.Utilities
|
||||
{
|
||||
public static class MultipartFormDataHelper
|
||||
{
|
||||
private static readonly FormOptions _defaultFormOptions = new FormOptions();
|
||||
|
||||
public static async Task GetFilesAsync(this HttpRequest request, Func<Stream, string, Task> callback)
|
||||
{
|
||||
var boundary = GetBoundary(MediaTypeHeaderValue.Parse(request.ContentType),
|
||||
_defaultFormOptions.MultipartBoundaryLengthLimit);
|
||||
var reader = new MultipartReader(boundary, request.Body);
|
||||
|
||||
var section = await reader.ReadNextSectionAsync();
|
||||
while(section != null)
|
||||
{
|
||||
ContentDispositionHeaderValue content;
|
||||
if(ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out content) &&
|
||||
HasFileContentDisposition(content))
|
||||
{
|
||||
await callback(section.Body, HeaderUtilities.RemoveQuotes(content.FileName));
|
||||
}
|
||||
|
||||
section = await reader.ReadNextSectionAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetBoundary(MediaTypeHeaderValue contentType, int lengthLimit)
|
||||
{
|
||||
var boundary = HeaderUtilities.RemoveQuotes(contentType.Boundary);
|
||||
if(string.IsNullOrWhiteSpace(boundary))
|
||||
{
|
||||
throw new InvalidDataException("Missing content-type boundary.");
|
||||
}
|
||||
|
||||
if(boundary.Length > lengthLimit)
|
||||
{
|
||||
throw new InvalidDataException($"Multipart boundary length limit {lengthLimit} exceeded.");
|
||||
}
|
||||
|
||||
return boundary;
|
||||
}
|
||||
|
||||
private static bool HasFileContentDisposition(ContentDispositionHeaderValue content)
|
||||
{
|
||||
// Content-Disposition: form-data; name="myfile1"; filename="Misc 002.jpg"
|
||||
return content != null && content.DispositionType.Equals("form-data") &&
|
||||
(!string.IsNullOrEmpty(content.FileName) || !string.IsNullOrEmpty(content.FileNameStar));
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user