Skip to content

Commit fcaf881

Browse files
bkrbtcJericho
andauthored
Use mimetypes for the detection of files in form-data (#89)
* Use mimetypes for the detection of files in form-data * Remove whitespaces * Remove whitespaces * Fix SA1013 Closing brace should be preceded by a space. * Fix SA1001 Commas should be followed by whitespace. * Fix SA1629 Documentation text should end with a period * Fix SA1003 Operator ':' should not appear at the end of a line and also SA1128 Put constructor initializers on their own line * Fix SA1117 The parameters should all be placed on the same line or each parameter should be placed on its own line. * Update Source/HttpMultipartParser/MultipartFormDataParser.cs Co-authored-by: Jericho <desautelsj@hotmail.com> Co-authored-by: Jericho <desautelsj@hotmail.com>
1 parent ec95efd commit fcaf881

3 files changed

Lines changed: 185 additions & 30 deletions

File tree

Source/HttpMultipartParser.UnitTests/HttpMultipartFormParserUnitTests.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,5 +190,30 @@ public async Task HandlesFileWithLastCrLfImmediatlyAfterBufferLengthAsync()
190190
var parser = await MultipartFormDataParser.ParseAsync(stream, Encoding.UTF8).ConfigureAwait(false);
191191
}
192192
}
193+
194+
[Fact]
195+
public async Task HandlesFileWithoutFilename()
196+
{
197+
string request =
198+
@"------WebKitFormBoundaryphElSb1aBJGfLyAP
199+
Content-Disposition: form-data; name=""fileName""
200+
201+
Testfile
202+
------WebKitFormBoundaryphElSb1aBJGfLyAP
203+
Content-Disposition: form-data; name=""file""
204+
Content-Type: application/octet-stream
205+
206+
"
207+
+ new string('\0', 8147)
208+
+ @"
209+
------WebKitFormBoundaryphElSb1aBJGfLyAP--
210+
";
211+
212+
using (Stream stream = TestUtil.StringToStream(request, Encoding.UTF8))
213+
{
214+
var parser = await MultipartFormDataParser.ParseAsync(stream, Encoding.UTF8).ConfigureAwait(false);
215+
Assert.Single(parser.Files);
216+
}
217+
}
193218
}
194219
}

Source/HttpMultipartParser/MultipartFormDataParser.cs

Lines changed: 115 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ public class MultipartFormDataParser
110110
/// </param>
111111
[Obsolete("This constructor is deprecated, please use MultipartFormDataParser.Parse or MultipartFormDataParser.ParseAsync instead.")]
112112
public MultipartFormDataParser(Stream stream)
113-
: this(stream, null, Encoding.UTF8, DefaultBufferSize)
113+
: this(stream, null, Encoding.UTF8, DefaultBufferSize, null)
114114
{
115115
}
116116

@@ -127,7 +127,7 @@ public MultipartFormDataParser(Stream stream)
127127
/// </param>
128128
[Obsolete("This constructor is deprecated, please use MultipartFormDataParser.Parse or MultipartFormDataParser.ParseAsync instead.")]
129129
public MultipartFormDataParser(Stream stream, string boundary)
130-
: this(stream, boundary, Encoding.UTF8, DefaultBufferSize)
130+
: this(stream, boundary, Encoding.UTF8, DefaultBufferSize, null)
131131
{
132132
}
133133

@@ -144,7 +144,7 @@ public MultipartFormDataParser(Stream stream, string boundary)
144144
/// </param>
145145
[Obsolete("This constructor is deprecated, please use MultipartFormDataParser.Parse or MultipartFormDataParser.ParseAsync instead.")]
146146
public MultipartFormDataParser(Stream stream, Encoding encoding)
147-
: this(stream, null, encoding, DefaultBufferSize)
147+
: this(stream, null, encoding, DefaultBufferSize, null)
148148
{
149149
}
150150

@@ -164,7 +164,7 @@ public MultipartFormDataParser(Stream stream, Encoding encoding)
164164
/// </param>
165165
[Obsolete("This constructor is deprecated, please use MultipartFormDataParser.Parse or MultipartFormDataParser.ParseAsync instead.")]
166166
public MultipartFormDataParser(Stream stream, string boundary, Encoding encoding)
167-
: this(stream, boundary, encoding, DefaultBufferSize)
167+
: this(stream, boundary, encoding, DefaultBufferSize, null)
168168
{
169169
}
170170

@@ -185,7 +185,7 @@ public MultipartFormDataParser(Stream stream, string boundary, Encoding encoding
185185
/// </param>
186186
[Obsolete("This constructor is deprecated, please use MultipartFormDataParser.Parse or MultipartFormDataParser.ParseAsync instead.")]
187187
public MultipartFormDataParser(Stream stream, Encoding encoding, int binaryBufferSize)
188-
: this(stream, null, encoding, binaryBufferSize)
188+
: this(stream, null, encoding, binaryBufferSize, null)
189189
{
190190
}
191191

@@ -209,8 +209,35 @@ public MultipartFormDataParser(Stream stream, Encoding encoding, int binaryBuffe
209209
/// </param>
210210
[Obsolete("This constructor is deprecated, please use MultipartFormDataParser.Parse or MultipartFormDataParser.ParseAsync instead.")]
211211
public MultipartFormDataParser(Stream stream, string boundary, Encoding encoding, int binaryBufferSize)
212+
: this(stream, boundary, encoding, binaryBufferSize, null)
212213
{
213-
ParseStream(stream, boundary, encoding, binaryBufferSize);
214+
}
215+
216+
/// <summary>
217+
/// Initializes a new instance of the <see cref="MultipartFormDataParser" /> class
218+
/// with the boundary, stream, input encoding and buffer size.
219+
/// </summary>
220+
/// <param name="stream">
221+
/// The stream containing the multipart data.
222+
/// </param>
223+
/// <param name="boundary">
224+
/// The multipart/form-data boundary. This should be the value
225+
/// returned by the request header.
226+
/// </param>
227+
/// <param name="encoding">
228+
/// The encoding of the multipart data.
229+
/// </param>
230+
/// <param name="binaryBufferSize">
231+
/// The size of the buffer to use for parsing the multipart form data. This must be larger
232+
/// then (size of boundary + 4 + # bytes in newline).
233+
/// </param>
234+
/// <param name="binaryMimeTypes">
235+
/// List of mimetypes that should be detected as file.
236+
/// </param>
237+
[Obsolete("This constructor is deprecated, please use MultipartFormDataParser.Parse or MultipartFormDataParser.ParseAsync instead.")]
238+
public MultipartFormDataParser(Stream stream, string boundary, Encoding encoding, int binaryBufferSize, string[] binaryMimeTypes)
239+
{
240+
ParseStream(stream, boundary, encoding, binaryBufferSize, binaryMimeTypes);
214241
}
215242

216243
/// <summary>
@@ -251,7 +278,7 @@ private MultipartFormDataParser()
251278
/// </returns>
252279
public static MultipartFormDataParser Parse(Stream stream)
253280
{
254-
return MultipartFormDataParser.Parse(stream, null, Encoding.UTF8, DefaultBufferSize);
281+
return MultipartFormDataParser.Parse(stream, null, Encoding.UTF8, DefaultBufferSize, null);
255282
}
256283

257284
/// <summary>
@@ -270,7 +297,7 @@ public static MultipartFormDataParser Parse(Stream stream)
270297
/// </returns>
271298
public static MultipartFormDataParser Parse(Stream stream, string boundary)
272299
{
273-
return MultipartFormDataParser.Parse(stream, boundary, Encoding.UTF8, DefaultBufferSize);
300+
return MultipartFormDataParser.Parse(stream, boundary, Encoding.UTF8, DefaultBufferSize, null);
274301
}
275302

276303
/// <summary>
@@ -288,7 +315,7 @@ public static MultipartFormDataParser Parse(Stream stream, string boundary)
288315
/// </returns>
289316
public static MultipartFormDataParser Parse(Stream stream, Encoding encoding)
290317
{
291-
return MultipartFormDataParser.Parse(stream, null, encoding, DefaultBufferSize);
318+
return MultipartFormDataParser.Parse(stream, null, encoding, DefaultBufferSize, null);
292319
}
293320

294321
/// <summary>
@@ -310,7 +337,7 @@ public static MultipartFormDataParser Parse(Stream stream, Encoding encoding)
310337
/// </returns>
311338
public static MultipartFormDataParser Parse(Stream stream, string boundary, Encoding encoding)
312339
{
313-
return MultipartFormDataParser.Parse(stream, boundary, encoding, DefaultBufferSize);
340+
return MultipartFormDataParser.Parse(stream, boundary, encoding, DefaultBufferSize, null);
314341
}
315342

316343
/// <summary>
@@ -332,7 +359,7 @@ public static MultipartFormDataParser Parse(Stream stream, string boundary, Enco
332359
/// </returns>
333360
public static MultipartFormDataParser Parse(Stream stream, Encoding encoding, int binaryBufferSize)
334361
{
335-
return MultipartFormDataParser.Parse(stream, null, encoding, binaryBufferSize);
362+
return MultipartFormDataParser.Parse(stream, null, encoding, binaryBufferSize, null);
336363
}
337364

338365
/// <summary>
@@ -357,9 +384,38 @@ public static MultipartFormDataParser Parse(Stream stream, Encoding encoding, in
357384
/// A new instance of the <see cref="MultipartFormDataParser"/> class.
358385
/// </returns>
359386
public static MultipartFormDataParser Parse(Stream stream, string boundary, Encoding encoding, int binaryBufferSize)
387+
{
388+
return MultipartFormDataParser.Parse(stream, boundary, encoding, binaryBufferSize, null);
389+
}
390+
391+
/// <summary>
392+
/// Parse the stream into a new instance of the <see cref="MultipartFormDataParser" /> class
393+
/// with the boundary, input encoding and buffer size.
394+
/// </summary>
395+
/// <param name="stream">
396+
/// The stream containing the multipart data.
397+
/// </param>
398+
/// <param name="boundary">
399+
/// The multipart/form-data boundary. This should be the value
400+
/// returned by the request header.
401+
/// </param>
402+
/// <param name="encoding">
403+
/// The encoding of the multipart data.
404+
/// </param>
405+
/// <param name="binaryBufferSize">
406+
/// The size of the buffer to use for parsing the multipart form data. This must be larger
407+
/// then (size of boundary + 4 + # bytes in newline).
408+
/// </param>
409+
/// <param name="binaryMimeTypes">
410+
/// List of mimetypes that should be detected as file.
411+
/// </param>
412+
/// <returns>
413+
/// A new instance of the <see cref="MultipartFormDataParser"/> class.
414+
/// </returns>
415+
public static MultipartFormDataParser Parse(Stream stream, string boundary, Encoding encoding, int binaryBufferSize, string[] binaryMimeTypes)
360416
{
361417
var parser = new MultipartFormDataParser();
362-
parser.ParseStream(stream, boundary, encoding, binaryBufferSize);
418+
parser.ParseStream(stream, boundary, encoding, binaryBufferSize, binaryMimeTypes);
363419
return parser;
364420
}
365421

@@ -375,7 +431,7 @@ public static MultipartFormDataParser Parse(Stream stream, string boundary, Enco
375431
/// </returns>
376432
public static Task<MultipartFormDataParser> ParseAsync(Stream stream)
377433
{
378-
return MultipartFormDataParser.ParseAsync(stream, null, Encoding.UTF8, DefaultBufferSize);
434+
return MultipartFormDataParser.ParseAsync(stream, null, Encoding.UTF8, DefaultBufferSize, null);
379435
}
380436

381437
/// <summary>
@@ -394,7 +450,7 @@ public static Task<MultipartFormDataParser> ParseAsync(Stream stream)
394450
/// </returns>
395451
public static Task<MultipartFormDataParser> ParseAsync(Stream stream, string boundary)
396452
{
397-
return MultipartFormDataParser.ParseAsync(stream, boundary, Encoding.UTF8, DefaultBufferSize);
453+
return MultipartFormDataParser.ParseAsync(stream, boundary, Encoding.UTF8, DefaultBufferSize, null);
398454
}
399455

400456
/// <summary>
@@ -412,7 +468,7 @@ public static Task<MultipartFormDataParser> ParseAsync(Stream stream, string bou
412468
/// </returns>
413469
public static Task<MultipartFormDataParser> ParseAsync(Stream stream, Encoding encoding)
414470
{
415-
return MultipartFormDataParser.ParseAsync(stream, null, encoding, DefaultBufferSize);
471+
return MultipartFormDataParser.ParseAsync(stream, null, encoding, DefaultBufferSize, null);
416472
}
417473

418474
/// <summary>
@@ -434,7 +490,7 @@ public static Task<MultipartFormDataParser> ParseAsync(Stream stream, Encoding e
434490
/// </returns>
435491
public static Task<MultipartFormDataParser> ParseAsync(Stream stream, string boundary, Encoding encoding)
436492
{
437-
return MultipartFormDataParser.ParseAsync(stream, boundary, encoding, DefaultBufferSize);
493+
return MultipartFormDataParser.ParseAsync(stream, boundary, encoding, DefaultBufferSize, null);
438494
}
439495

440496
/// <summary>
@@ -456,7 +512,7 @@ public static Task<MultipartFormDataParser> ParseAsync(Stream stream, string bou
456512
/// </returns>
457513
public static Task<MultipartFormDataParser> ParseAsync(Stream stream, Encoding encoding, int binaryBufferSize)
458514
{
459-
return MultipartFormDataParser.ParseAsync(stream, null, encoding, binaryBufferSize);
515+
return MultipartFormDataParser.ParseAsync(stream, null, encoding, binaryBufferSize, null);
460516
}
461517

462518
/// <summary>
@@ -480,10 +536,39 @@ public static Task<MultipartFormDataParser> ParseAsync(Stream stream, Encoding e
480536
/// <returns>
481537
/// A new instance of the <see cref="MultipartFormDataParser"/> class.
482538
/// </returns>
483-
public static async Task<MultipartFormDataParser> ParseAsync(Stream stream, string boundary, Encoding encoding, int binaryBufferSize)
539+
public static Task<MultipartFormDataParser> ParseAsync(Stream stream, string boundary, Encoding encoding, int binaryBufferSize)
540+
{
541+
return MultipartFormDataParser.ParseAsync(stream, null, encoding, binaryBufferSize, null);
542+
}
543+
544+
/// <summary>
545+
/// Asynchronously parse the stream into a new instance of the <see cref="MultipartFormDataParser" /> class
546+
/// with the boundary, input encoding and buffer size.
547+
/// </summary>
548+
/// <param name="stream">
549+
/// The stream containing the multipart data.
550+
/// </param>
551+
/// <param name="boundary">
552+
/// The multipart/form-data boundary. This should be the value
553+
/// returned by the request header.
554+
/// </param>
555+
/// <param name="encoding">
556+
/// The encoding of the multipart data.
557+
/// </param>
558+
/// <param name="binaryBufferSize">
559+
/// The size of the buffer to use for parsing the multipart form data. This must be larger
560+
/// then (size of boundary + 4 + # bytes in newline).
561+
/// </param>
562+
/// <param name="binaryMimeTypes">
563+
/// List of mimetypes that should be detected as file.
564+
/// </param>
565+
/// <returns>
566+
/// A new instance of the <see cref="MultipartFormDataParser"/> class.
567+
/// </returns>
568+
public static async Task<MultipartFormDataParser> ParseAsync(Stream stream, string boundary, Encoding encoding, int binaryBufferSize, string[] binaryMimeTypes)
484569
{
485570
var parser = new MultipartFormDataParser();
486-
await parser.ParseStreamAsync(stream, boundary, encoding, binaryBufferSize).ConfigureAwait(false);
571+
await parser.ParseStreamAsync(stream, boundary, encoding, binaryBufferSize, binaryMimeTypes).ConfigureAwait(false);
487572
return parser;
488573
}
489574

@@ -549,12 +634,15 @@ public IEnumerable<string> GetParameterValues(string name)
549634
/// The size of the buffer to use for parsing the multipart form data. This must be larger
550635
/// then (size of boundary + 4 + # bytes in newline).
551636
/// </param>
552-
private void ParseStream(Stream stream, string boundary, Encoding encoding, int binaryBufferSize)
637+
/// <param name="binaryMimeTypes">
638+
/// List of mimetypes that should be detected as file.
639+
/// </param>
640+
private void ParseStream(Stream stream, string boundary, Encoding encoding, int binaryBufferSize, string[] binaryMimeTypes)
553641
{
554642
Files = new List<FilePart>();
555643
Parameters = new List<ParameterPart>();
556644

557-
var streamingParser = new StreamingMultipartFormDataParser(stream, boundary, encoding, binaryBufferSize);
645+
var streamingParser = new StreamingMultipartFormDataParser(stream, boundary, encoding, binaryBufferSize, binaryMimeTypes);
558646
streamingParser.ParameterHandler += parameterPart => Parameters.Add(parameterPart);
559647

560648
streamingParser.FileHandler += (name, fileName, type, disposition, buffer, bytes, partNumber) =>
@@ -594,12 +682,15 @@ private void ParseStream(Stream stream, string boundary, Encoding encoding, int
594682
/// The size of the buffer to use for parsing the multipart form data. This must be larger
595683
/// then (size of boundary + 4 + # bytes in newline).
596684
/// </param>
597-
private async Task ParseStreamAsync(Stream stream, string boundary, Encoding encoding, int binaryBufferSize)
685+
/// <param name="binaryMimeTypes">
686+
/// List of mimetypes that should be detected as file.
687+
/// </param>
688+
private async Task ParseStreamAsync(Stream stream, string boundary, Encoding encoding, int binaryBufferSize, string[] binaryMimeTypes)
598689
{
599690
Files = new List<FilePart>();
600691
Parameters = new List<ParameterPart>();
601692

602-
var streamingParser = new StreamingMultipartFormDataParser(stream, boundary, encoding, binaryBufferSize);
693+
var streamingParser = new StreamingMultipartFormDataParser(stream, boundary, encoding, binaryBufferSize, binaryMimeTypes);
603694
streamingParser.ParameterHandler += parameterPart => Parameters.Add(parameterPart);
604695

605696
streamingParser.FileHandler += (name, fileName, type, disposition, buffer, bytes, partNumber) =>
@@ -624,4 +715,4 @@ private async Task ParseStreamAsync(Stream stream, string boundary, Encoding enc
624715

625716
#endregion
626717
}
627-
}
718+
}

0 commit comments

Comments
 (0)