-
-
Notifications
You must be signed in to change notification settings - Fork 24
Multipart form support #278
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
4585242
Multipart form support
5bdd6ea
Update nanoFramework.WebServer/HttpListenerRequestExtensions.cs
KlausVcb b392979
Update README.md
KlausVcb daac80b
Update nanoFramework.WebServer/HttpMultipartParser/MultipartFormDataP…
KlausVcb c07333a
LineBuffer uses ArrayList instead of Hashtable
556c55e
Merge branch 'HttpMultipartParser' of https://github.com/KlausVcb/nan…
8864355
Indenting fixed
44afa25
StringBuilder used and redundant jump removed (SonarQube)
ddc6386
LineBuffer sealed to conform the dispose pattern (SonarQube)
2b02412
throw MultipartFormDataParserException instead of general Exception (…
d39375e
LineReader.ReadByteLine returning null does have another meaning than…
110b4b4
LineReader.ReadByteLine cognitive complexity reduction (SonarQube)
c933b19
MultipartFormDataParserException in its own file & comment spacing
b213774
Use SpanByte in LineBuffer
edb71fb
Merge branch 'main' into HttpMultipartParser
Ellerbach File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System; | ||
using System.IO; | ||
using System.Net; | ||
using System.Threading; | ||
using nanoFramework.WebServer.HttpMultipartParser; | ||
|
||
namespace nanoFramework.WebServer | ||
{ | ||
/// <summary>Contains extension methods for HttpListenerRequest</summary> | ||
public static class HttpListenerRequestExtensions | ||
{ | ||
/// <summary> | ||
/// Reads a Multipart form from the request | ||
/// </summary> | ||
/// <param name="httpListenerRequest">The request to read the form from</param> | ||
/// <returns>A <see cref="MultipartFormDataParser">MultipartFormDataParser</see> containing a collection of the parameters and files in the form.</returns> | ||
public static MultipartFormDataParser ReadForm(this HttpListenerRequest httpListenerRequest) => | ||
MultipartFormDataParser.Parse(httpListenerRequest.InputStream); | ||
|
||
/// <summary> | ||
/// Reads a body from the HttpListenerRequest inputstream | ||
/// </summary> | ||
/// <param name="httpListenerRequest">The request to read the body from</param> | ||
/// <returns>A byte[] containing the body of the request</returns> | ||
public static byte[] ReadBody(this HttpListenerRequest httpListenerRequest) | ||
{ | ||
byte[] body = new byte[httpListenerRequest.ContentLength64]; | ||
byte[] buffer = new byte[4096]; | ||
Stream stream = httpListenerRequest.InputStream; | ||
|
||
int position = 0; | ||
|
||
while (true) | ||
{ | ||
// The stream is (should be) a NetworkStream which might still be receiving data while | ||
// we're already processing. Give the stream a chance to receive more data or we might | ||
// end up with "zero bytes read" too soon... | ||
Thread.Sleep(1); | ||
|
||
long length = stream.Length; | ||
|
||
if (length > buffer.Length) | ||
{ | ||
length = buffer.Length; | ||
} | ||
|
||
int bytesRead = stream.Read(buffer, 0, (int)length); | ||
|
||
if (bytesRead == 0) | ||
{ | ||
break; | ||
} | ||
|
||
Array.Copy(buffer, 0, body, position, bytesRead); | ||
|
||
position += bytesRead; | ||
} | ||
|
||
return body; | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.Collections; | ||
using System.IO; | ||
|
||
namespace nanoFramework.WebServer.HttpMultipartParser | ||
{ | ||
/// <summary>Represents a single file extracted from a multipart/form-data stream.</summary> | ||
public class FilePart | ||
{ | ||
/// <summary>Initializes a new instance of the <see cref="FilePart" /> class.</summary> | ||
/// <param name="name">The name of the input field used for the upload.</param> | ||
/// <param name="fileName">The name of the file.</param> | ||
/// <param name="data">The file data.</param> | ||
/// <param name="additionalProperties">Additional properties associated with this file.</param> | ||
/// <param name="contentType">The content type.</param> | ||
/// <param name="contentDisposition">The content disposition.</param> | ||
public FilePart(string name, string fileName, Stream data, Hashtable additionalProperties, string contentType, string contentDisposition) | ||
{ | ||
string[] parts = fileName?.Split(GetInvalidFileNameChars()); | ||
|
||
Name = name; | ||
FileName = parts != null && parts.Length > 0 ? parts[parts.Length - 1] : string.Empty; | ||
Data = data; | ||
ContentType = contentType; | ||
ContentDisposition = contentDisposition; | ||
AdditionalProperties = additionalProperties; | ||
} | ||
|
||
/// <summary>Gets the data.</summary> | ||
public Stream Data | ||
{ | ||
get; | ||
} | ||
|
||
/// <summary>Gets the file name.</summary> | ||
public string FileName | ||
{ | ||
get; | ||
} | ||
|
||
/// <summary>Gets the name.</summary> | ||
public string Name | ||
{ | ||
get; | ||
} | ||
|
||
/// <summary>Gets the content-type. Defaults to text/plain if unspecified.</summary> | ||
public string ContentType | ||
{ | ||
get; | ||
} | ||
|
||
/// <summary>Gets the content-disposition. Defaults to form-data if unspecified.</summary> | ||
public string ContentDisposition | ||
{ | ||
get; | ||
} | ||
|
||
/// <summary> | ||
/// Gets the additional properties associated with this file. | ||
/// An additional property is any property other than the "well known" ones such as name, filename, content-type, etc. | ||
/// </summary> | ||
public Hashtable AdditionalProperties | ||
{ | ||
get; | ||
private set; | ||
} | ||
|
||
private static char[] GetInvalidFileNameChars() => new char[] | ||
{ | ||
'\"', '<', '>', '|', '\0', | ||
(char)1, (char)2, (char)3, (char)4, (char)5, (char)6, (char)7, (char)8, (char)9, (char)10, | ||
(char)11, (char)12, (char)13, (char)14, (char)15, (char)16, (char)17, (char)18, (char)19, (char)20, | ||
(char)21, (char)22, (char)23, (char)24, (char)25, (char)26, (char)27, (char)28, (char)29, (char)30, | ||
(char)31, ':', '*', '?', '\\', '/' | ||
}; | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
nanoFramework.WebServer/HttpMultipartParser/HashtableUtility.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.Collections; | ||
|
||
namespace nanoFramework.WebServer.HttpMultipartParser | ||
{ | ||
internal static class HashtableUtility | ||
{ | ||
public static bool TryGetValue(this Hashtable hashtable, string key, out string value) | ||
{ | ||
if (hashtable != null && hashtable.Contains(key)) | ||
{ | ||
var obj = hashtable[key]; | ||
value = obj == null ? string.Empty : obj.ToString(); | ||
return true; | ||
} | ||
|
||
value = null; | ||
return false; | ||
} | ||
} | ||
} |
72 changes: 72 additions & 0 deletions
72
nanoFramework.WebServer/HttpMultipartParser/HeaderUtility.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.Collections; | ||
using System.Text; | ||
|
||
namespace nanoFramework.WebServer.HttpMultipartParser | ||
{ | ||
/// <summary> | ||
/// Provides parsing headers from a Http Multipart Form | ||
/// </summary> | ||
public static class HeaderUtility | ||
{ | ||
/// <summary> | ||
/// Reads headers from a line of text. | ||
/// Headers are delimited by a semi-colon ';' | ||
/// Key-value pairs are separated by colon ':' or equals '=' | ||
/// Values can be delimited by quotes '"' or not | ||
/// </summary> | ||
/// <param name="text">The line of text containing one or more headers</param> | ||
/// <param name="headers"> | ||
/// The hashtable that will receive the key values. | ||
/// Passed in since a Multipart Part can contain multiple lines of headers | ||
/// </param> | ||
public static void ParseHeaders(string text, Hashtable headers) | ||
{ | ||
bool inQuotes = false; | ||
bool inKey = true; | ||
StringBuilder key = new(); | ||
StringBuilder value = new(); | ||
|
||
foreach (char c in text) | ||
KlausVcb marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
if (c == '"') | ||
{ | ||
inQuotes = !inQuotes; | ||
} | ||
else if (inQuotes) | ||
{ | ||
value.Append(c); | ||
} | ||
else if (c == ';') | ||
{ | ||
headers[key.ToString().ToLower()] = value.ToString(); | ||
key.Clear(); | ||
inKey = true; | ||
} | ||
else if (c == '=' || c == ':') | ||
{ | ||
value = value.Clear(); | ||
inKey = false; | ||
} | ||
else if (c != ' ') | ||
{ | ||
if (inKey) | ||
{ | ||
key.Append(c); | ||
} | ||
else | ||
{ | ||
value.Append(c); | ||
} | ||
} | ||
} | ||
|
||
if (key.Length > 0) | ||
{ | ||
headers.Add(key.ToString().ToLower(), value.ToString()); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.