Exemple #1
0
        /// <summary>
        /// Binds the model.
        /// </summary>
        /// <typeparam name="T">Model type</typeparam>
        /// <param name="args">The <see cref="ModelBinderEventArgs{T}" /> instance containing the event data.</param>
        public async Task BindAsync <T>(ModelBinderEventArgs <T> args)
        {
            if (!args.Context.Request.ContentType.Contains("multipart/form-data"))
            {
                return;
            }

            var multipartModelType = typeof(MultipartViewModel);

            if (typeof(T) != multipartModelType)
            {
                throw new ModelBindingException("For HTTP multipart form data model type should be: " + multipartModelType.Name);
            }

            var parser = await MultipartFormDataParser.ParseAsync(args.Context.Request.Body);

            var obj = Activator.CreateInstance <T>();

            var model = (MultipartViewModel)(object)obj;

            model.Files      = parser.Files;
            model.Parameters = parser.Parameters;

            args.SetModel(obj);
        }
 public async Task DoesntInfiniteLoopOnUnclosedInputAsync()
 {
     using (Stream stream = TestUtil.StringToStream(_testCase.Request, Encoding.UTF8))
     {
         // We expect this to throw!
         await Assert.ThrowsAsync <MultipartParseException>(() => MultipartFormDataParser.ParseAsync(stream, Encoding.UTF8)).ConfigureAwait(false);
     }
 }
        public async Task HandlesFullPathAsFileNameWithSemicolonCorrectlyAsync()
        {
            using (Stream stream = TestUtil.StringToStream(_testCase.Request, Encoding.UTF8))
            {
                var parser = await MultipartFormDataParser.ParseAsync(stream, Encoding.UTF8).ConfigureAwait(false);

                Assert.True(_testCase.Validate(parser));
            }
        }
Exemple #4
0
        /// <summary>
        /// Parses the inbound email webhook asynchronously.
        /// </summary>
        /// <param name="stream">The stream.</param>
        /// <returns>The <see cref="InboundEmail"/>.</returns>
        public async Task <InboundEmail> ParseInboundEmailWebhookAsync(Stream stream)
        {
            // We need to be able to rewind the stream.
            // Therefore, we must make a copy of the stream if it doesn't allow changing the position
            if (!stream.CanSeek)
            {
                using (var ms = Utils.MemoryStreamManager.GetStream())
                {
                    await stream.CopyToAsync(ms).ConfigureAwait(false);

                    return(await ParseInboundEmailWebhookAsync(ms).ConfigureAwait(false));
                }
            }

            // It's important to rewind the stream
            stream.Position = 0;

            // Asynchronously parse the multipart content received from SendGrid
            var parser = await MultipartFormDataParser.ParseAsync(stream, Encoding.UTF8).ConfigureAwait(false);

            // Convert the 'charset' from a string into array of KeyValuePair
            var charsetsAsJObject = JObject.Parse(parser.GetParameterValue("charsets", "{}"));
            var charsets          = charsetsAsJObject
                                    .Properties()
                                    .Select(prop =>
            {
                var key   = prop.Name;
                var value = Encoding.GetEncoding(prop.Value.ToString());
                return(new KeyValuePair <string, Encoding>(key, value));
            }).ToArray();

            // Create a dictionary of parsers, one parser for each desired encoding.
            // This is necessary because MultipartFormDataParser can only handle one
            // encoding and SendGrid can use different encodings for parameters such
            // as "from", "to", "text" and "html".
            var encodedParsers = charsets
                                 .Where(c => c.Value != Encoding.UTF8)
                                 .Select(c => c.Value)
                                 .Distinct()
                                 .Select(async encoding =>
            {
                stream.Position = 0;                         // It's important to rewind the stream
                return(new
                {
                    Encoding = encoding,
                    Parser = await MultipartFormDataParser.ParseAsync(stream, encoding).ConfigureAwait(false)
                });
            })
                                 .Select(r => r.Result)
                                 .Union(new[]
            {
                new { Encoding = Encoding.UTF8, Parser = parser }
            })
                                 .ToDictionary(ep => ep.Encoding, ep => ep.Parser);

            return(ParseInboundEmail(encodedParsers, charsets));
        }
Exemple #5
0
        public async Task CanHandleFileAsLastSectionAsync()
        {
            using (Stream stream = TestUtil.StringToStream(_testCase.Request, Encoding.UTF8))
            {
                var parser = await MultipartFormDataParser.ParseAsync(stream, Encoding.UTF8).ConfigureAwait(false);

                Assert.True(_testCase.Validate(parser));
            }
        }
        public async Task AcceptSeveralValuesWithSamePropertyAsync()
        {
            using (Stream stream = TestUtil.StringToStream(_testCase.Request, Encoding.UTF8))
            {
                var parser = await MultipartFormDataParser.ParseAsync(stream, Encoding.UTF8).ConfigureAwait(false);

                Assert.True(_testCase.Validate(parser));
            }
        }
Exemple #7
0
        public async Task MjpegStreamTest_Async()
        {
            using (Stream stream = TestUtil.StringToStream(_testCase.Request, Encoding.UTF8))
            {
                var parser = await MultipartFormDataParser.ParseAsync(stream, "MOBOTIX_Fast_Serverpush", Encoding.UTF8, 32).ConfigureAwait(false);

                Assert.True(_testCase.Validate(parser));
            }
        }
        public async Task CanDetectBoundariesCrossBufferAsync()
        {
            using (Stream stream = TestUtil.StringToStream(_testCase.Request, Encoding.UTF8))
            {
                var parser = await MultipartFormDataParser.ParseAsync(stream, "boundry", Encoding.UTF8, 16).ConfigureAwait(false);

                Assert.True(_testCase.Validate(parser));
            }
        }
        public async Task Parse_empty_form_boundary_specified_async()
        {
            using (Stream stream = TestUtil.StringToStream(_testCase.Request, Encoding.UTF8))
            {
                var parser = await MultipartFormDataParser.ParseAsync(stream, "----WebKitFormBoundaryb4SfPlH9Bv7c2PKS").ConfigureAwait(false);

                Assert.True(_testCase.Validate(parser));
            }
        }
        public async Task GetParameterValueReturnsNullIfNoParameterFoundAsync()
        {
            using (Stream stream = TestUtil.StringToStream(_testCase.Request, Encoding.UTF8))
            {
                var parser = await MultipartFormDataParser.ParseAsync(stream, "boundry", Encoding.UTF8).ConfigureAwait(false);

                Assert.Null(parser.GetParameterValue("does not exist"));
            }
        }
        public async Task FileWithAdditionalParameterTest_Async()
        {
            using (Stream stream = TestUtil.StringToStream(_testCase.Request, Encoding.UTF8))
            {
                var parser = await MultipartFormDataParser.ParseAsync(stream, Encoding.UTF8).ConfigureAwait(false);

                Assert.True(_testCase.Validate(parser));
            }
        }
Exemple #12
0
        public async Task CanHandleFinalDashesInSeperateBufferFromEndBinaryAsync()
        {
            using (Stream stream = TestUtil.StringToStream(_testCase.Request, Encoding.UTF8))
            {
                var parser = await MultipartFormDataParser.ParseAsync(stream, "boundry", Encoding.UTF8, 16).ConfigureAwait(false);

                Assert.True(_testCase.Validate(parser));
            }
        }
        public async Task MultipleFilesAndParamsTestAsync()
        {
            using (Stream stream = TestUtil.StringToStream(_testCase.Request, Encoding.UTF8))
            {
                var parser = await MultipartFormDataParser.ParseAsync(stream, "boundry", Encoding.UTF8, 16).ConfigureAwait(false);

                Assert.True(_testCase.Validate(parser));
            }
        }
        public async Task Parse_empty_form_boundary_omitted_async()
        {
            using (Stream stream = TestUtil.StringToStream(_testCase.Request, Encoding.UTF8))
            {
                var parser = await MultipartFormDataParser.ParseAsync(stream).ConfigureAwait(false);

                Assert.True(_testCase.Validate(parser));
            }
        }
Exemple #15
0
        public async Task CanHandleUnicodeWidthAndAsciiWidthCharactersAsync()
        {
            using (
                Stream stream = TestUtil.StringToStream(_testCase.Request, Encoding.UTF8))
            {
                var parser = await MultipartFormDataParser.ParseAsync(stream, Encoding.UTF8).ConfigureAwait(false);

                Assert.True(_testCase.Validate(parser));
            }
        }
        public async Task CorrectlyHandlesCRLFAsync()
        {
            string request = _testCase.Request.Replace("\n", "\r\n");

            using (Stream stream = TestUtil.StringToStream(request, Encoding.UTF8))
            {
                var parser = await MultipartFormDataParser.ParseAsync(stream, "boundry", Encoding.UTF8).ConfigureAwait(false);

                Assert.True(_testCase.Validate(parser));
            }
        }
        public async Task DoesNotCloseTheStreamAsync()
        {
            using (Stream stream = TestUtil.StringToStream(_testCase.Request, Encoding.UTF8))
            {
                var parser = await MultipartFormDataParser.ParseAsync(stream, "boundry", Encoding.UTF8).ConfigureAwait(false);

                Assert.True(_testCase.Validate(parser));

                stream.Position = 0;
                Assert.True(true, "A closed stream would throw ObjectDisposedException");
            }
        }
        public async Task SmallDataTestAsync()
        {
            using (Stream stream = TestUtil.StringToStream(_testCase.Request))
            {
                // The boundry is missing the first two -- in accordance with the multipart
                // spec. (A -- is added by the parser, this boundry is what would be sent in the
                // requset header)
                var parser = await MultipartFormDataParser.ParseAsync(stream, "---------------------------265001916915724").ConfigureAwait(false);

                Assert.True(_testCase.Validate(parser));
            }
        }
        public async Task CanDetectBoundriesWithNewLineInNextBufferAsync()
        {
            for (int i = 16; i < _testCase.Request.Length; i++)
            {
                using (Stream stream = TestUtil.StringToStream(_testCase.Request, Encoding.UTF8))
                {
                    var parser = await MultipartFormDataParser.ParseAsync(stream, "boundry", Encoding.UTF8, i).ConfigureAwait(false);

                    Assert.True(_testCase.Validate(parser), $"Failure in buffer length {i}");
                }
            }
        }
        public async Task CorrectlyHandleMixedNewlineFormatsAsync()
        {
            // Replace the first '\n' with '\r\n'
            var    regex   = new Regex(Regex.Escape("\n"));
            string request = regex.Replace(_testCase.Request, "\r\n", 1);

            using (Stream stream = TestUtil.StringToStream(request, Encoding.UTF8))
            {
                var parser = await MultipartFormDataParser.ParseAsync(stream, "boundry", Encoding.UTF8).ConfigureAwait(false);

                Assert.True(_testCase.Validate(parser));
            }
        }
Exemple #21
0
        public async Task <FileResponse> SaveAsync()
        {
            var parser = await MultipartFormDataParser.ParseAsync(Request.InputStream);

            if (parser?.Files is null)
            {
                throw HttpException.NotFound("No file uploaded");
            }
            if (parser?.Files.Count != 1)
            {
                throw HttpException.BadRequest("Only 1 file can be uploaded");
            }
            return(await _filesHandler.SaveAsync(parser.Files[0].Data, parser.Files[0].FileName));
        }
Exemple #22
0
        private static async Task <(UploadFileModel model, Stream?file)> ReadBodyAsFormDataAsync(HttpRequestData req)
        {
            var result = await MultipartFormDataParser.ParseAsync(req.Body);

            var model = new UploadFileModel()
            {
                Name         = result.Parameters.FirstOrDefault(x => x.Name == nameof(UploadFileModel.Name))?.Data !,
                Size         = long.Parse(result.Parameters.FirstOrDefault(x => x.Name == nameof(UploadFileModel.Size))?.Data !),
                Type         = result.Parameters.FirstOrDefault(x => x.Name == nameof(UploadFileModel.Type))?.Data !,
                LastModified = long.Parse(result.Parameters.FirstOrDefault(x => x.Name == nameof(UploadFileModel.LastModified))?.Data !)
            };

            Validator.ValidateObject(model, new ValidationContext(model));

            return(model, result.Files.FirstOrDefault(x => x.Name == "file")?.Data);
        }
    }
        public async Task CorrectlyHandlesMultilineParameterAsync()
        {
            string request = TestUtil.TrimAllLines(
                @"-----------------------------41952539122868
                Content-Disposition: form-data; name=""multilined""

                line 1
                line 2
                line 3
                -----------------------------41952539122868--");

            using (Stream stream = TestUtil.StringToStream(request, Encoding.UTF8))
            {
                var parser = await MultipartFormDataParser.ParseAsync(stream, Encoding.UTF8).ConfigureAwait(false);

                Assert.Equal("line 1\r\nline 2\r\nline 3", parser.GetParameterValue("multilined"));
                Assert.Equal("line 1\r\nline 2\r\nline 3", parser.GetParameterValues("multilined").First());
            }
        }
        private static async Task <(UploadFileModel model, Stream?file)> ReadBodyAsFormDataAsync(HttpRequestData req)
        {
            var base64Bytes = JsonConvert.DeserializeObject <BytesRequestWrapper>(req.Body).Bytes;

            using var memoryStream = new MemoryStream(Convert.FromBase64String(base64Bytes));
            var result = await MultipartFormDataParser.ParseAsync(memoryStream);

            var model = new UploadFileModel()
            {
                Name         = result.Parameters.FirstOrDefault(x => x.Name == nameof(UploadFileModel.Name))?.Data !,
                Size         = long.Parse(result.Parameters.FirstOrDefault(x => x.Name == nameof(UploadFileModel.Size))?.Data !),
                Type         = result.Parameters.FirstOrDefault(x => x.Name == nameof(UploadFileModel.Type))?.Data !,
                LastModified = long.Parse(result.Parameters.FirstOrDefault(x => x.Name == nameof(UploadFileModel.LastModified))?.Data !)
            };

            Validator.ValidateObject(model, new ValidationContext(model));

            return(model, result.Files.FirstOrDefault(x => x.Name == "file")?.Data);
        }
    }
        public async Task HandlesFileWithLastCrLfImmediatlyAfterBufferLengthAsync()
        {
            string request =
                @"------WebKitFormBoundaryphElSb1aBJGfLyAP
Content-Disposition: form-data; name=""fileName""

Testfile
------WebKitFormBoundaryphElSb1aBJGfLyAP
Content-Disposition: form-data; name=""file""; filename=""Testfile""
Content-Type: application/pdf

"
                + new string('\0', 8149)
                + @"
------WebKitFormBoundaryphElSb1aBJGfLyAP--
";

            using (Stream stream = TestUtil.StringToStream(request, Encoding.UTF8))
            {
                var parser = await MultipartFormDataParser.ParseAsync(stream, Encoding.UTF8).ConfigureAwait(false);
            }
        }
        /// <summary>
        /// A frends task form parsing multipart/form-data requests.
        /// Documentation: https://github.com/CommunityHiQ/Frends.Community.Multipart
        /// </summary>
        /// <param name="input">What to repeat.</param>
        /// <param name="cancellationToken"></param>
        ///  <returns>Object { List&lt;{ string Name, string Value }&gt; Parameters, List&lt;{ string Name, byte[] Contents }&gt; Files }</returns>
        public static async Task <Result> ParseMultipartRequest(Input input, CancellationToken cancellationToken)
        {
            var ret  = new List <File>();
            var ret2 = new List <Parameter>();

            using (var stream = new MemoryStream(input.ByteArray))
            {
                var parser = await MultipartFormDataParser.ParseAsync(stream).ConfigureAwait(false);

                foreach (var file in parser.Files)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    var tmp = new File {
                        Name = file.FileName, Contents = ((MemoryStream)file.Data).ToArray()
                    };
                    ret.Add(tmp);
                }

                foreach (var param in parser.Parameters)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    var retParam = new Parameter
                    {
                        Name  = param.Name,
                        Value = param.Data
                    };
                    ret2.Add(retParam);
                }
            }

            var output = new Result
            {
                Files      = ret,
                Parameters = ret2
            };

            return(output);
        }
Exemple #27
0
        public async Task <Stream> Download(string fileName, CancellationToken cancellationToken)
        {
            await RefreshAccessTokenIfRequired(cancellationToken).ConfigureAwait(false);

            // Check and search file
            var fileList = await GetGoogleDriveFileList(cancellationToken).ConfigureAwait(false);

            var targetFile = fileList.Files.Find(f => f.Name == fileName);

            if (targetFile is null)
            {
                return(null);
            }

            var client = _httpClientFactory.CreateClient();

            using var getFileStreamRM  = GetAuthHttpRequestMessage();
            getFileStreamRM.Method     = HttpMethod.Get;
            getFileStreamRM.RequestUri = new System.Uri($"https://www.googleapis.com/drive/v3/files/{targetFile.Id}?alt=media");
            var fileResponse = await client.SendAsync(getFileStreamRM, cancellationToken).ConfigureAwait(false);

            var fileContent = fileResponse.Content;

            using var fullStream = await fileContent.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);

            var multipart = await MultipartFormDataParser.ParseAsync(fullStream).ConfigureAwait(false);

            foreach (var file in multipart.Files)
            {
                if (file.ContentType == MediaTypeNames.Application.Octet)
                {
                    return(file.Data);
                }
            }

            return(null);
        }
        public async Task HandlesFileWithoutFilename()
        {
            string request =
                @"------WebKitFormBoundaryphElSb1aBJGfLyAP
Content-Disposition: form-data; name=""fileName""

Testfile
------WebKitFormBoundaryphElSb1aBJGfLyAP
Content-Disposition: form-data; name=""file""
Content-Type: application/octet-stream

"
                + new string('\0', 8147)
                + @"
------WebKitFormBoundaryphElSb1aBJGfLyAP--
";

            using (Stream stream = TestUtil.StringToStream(request, Encoding.UTF8))
            {
                var parser = await MultipartFormDataParser.ParseAsync(stream, Encoding.UTF8).ConfigureAwait(false);

                Assert.Single(parser.Files);
            }
        }
 public async Task ConstructingWithNullStreamFailsAsync()
 {
     await Assert.ThrowsAsync <ArgumentNullException>(() => MultipartFormDataParser.ParseAsync(Stream.Null)).ConfigureAwait(false);
 }
Exemple #30
0
        /// <summary>
        /// Parses the inbound email webhook asynchronously.
        /// </summary>
        /// <param name="stream">The stream.</param>
        /// <returns>The <see cref="InboundEmail"/>.</returns>
        public async Task <InboundEmail> ParseInboundEmailWebhookAsync(Stream stream)
        {
            // We need to be able to rewind the stream.
            // Therefore, we must make a copy of the stream if it doesn't allow changing the position
            if (!stream.CanSeek)
            {
                using (var ms = Utils.MemoryStreamManager.GetStream())
                {
                    await stream.CopyToAsync(ms).ConfigureAwait(false);

                    return(await ParseInboundEmailWebhookAsync(ms).ConfigureAwait(false));
                }
            }

            // It's important to rewind the stream
            stream.Position = 0;

            // Asynchronously parse the multipart content received from SendGrid
            var parser = await MultipartFormDataParser.ParseAsync(stream, Encoding.UTF8).ConfigureAwait(false);

            // Convert the 'charset' from a string into array of KeyValuePair
            var charsetsAsJObject = JObject.Parse(parser.GetParameterValue("charsets", "{}"));
            var charsets          = charsetsAsJObject
                                    .Properties()
                                    .Select(prop =>
            {
                var key          = prop.Name;
                var encodingName = prop.Value.ToString();

                try
                {
                    var encoding = Encoding.GetEncoding(encodingName);
                    return(new KeyValuePair <string, Encoding>(key, encoding));
                }
                catch (ArgumentException)
                {
                    // ArgumentException is thrown when an "unusual" code page was used to encode a section of the email
                    // For example: {"to":"UTF-8","subject":"UTF-8","from":"UTF-8","text":"iso-8859-10"}
                    // We can see that 'iso-8859-10' was used to encode the "Text" but this encoding is not supported in
                    // .net (neither dotnet full nor dotnet core). Therefore we fallback on UTF-8. This is obviously not
                    // perfect because UTF-8 may or may not be able to handle all the encoded characters, but it's better
                    // than simply erroring out.
                    // See https://github.com/Jericho/StrongGrid/issues/341 for discussion.
                    return(new KeyValuePair <string, Encoding>(key, Encoding.UTF8));
                }
            }).ToArray();

            // Create a dictionary of parsers, one parser for each desired encoding.
            // This is necessary because MultipartFormDataParser can only handle one
            // encoding and SendGrid can use different encodings for parameters such
            // as "from", "to", "text" and "html".
            var encodedParsers = charsets
                                 .Where(c => !c.Value.Equals(Encoding.UTF8))
                                 .Select(c => c.Value)
                                 .Distinct()
                                 .Select(async encoding =>
            {
                stream.Position = 0;                         // It's important to rewind the stream
                return(new
                {
                    Encoding = encoding,
                    Parser = await MultipartFormDataParser.ParseAsync(stream, encoding).ConfigureAwait(false)
                });
            })
                                 .Select(r => r.Result)
                                 .Union(new[]
            {
                new { Encoding = Encoding.UTF8, Parser = parser }
            })
                                 .ToDictionary(ep => ep.Encoding, ep => ep.Parser);

            return(ParseInboundEmail(encodedParsers, charsets));
        }