Exemplo n.º 1
0
        /// <summary>
        /// Parses url encoded form data
        /// </summary>
        /// <returns>An awaitable task.</returns>
        /// <param name="reader">The stream to read from.</param>
        /// <param name="config">The server configuration.</param>
        /// <param name="idletime">The maximum idle time.</param>
        /// <param name="timeouttask">A task that signals request timeout.</param>
        /// <param name="stoptask">A task that signals server stop.</param>
        internal async Task ParseFormData(BufferedStreamReader reader, ServerConfig config, TimeSpan idletime, Task timeouttask, Task stoptask)
        {
            if (string.Equals("application/x-www-form-urlencoded", this.ContentType))
            {
                if (this.ContentLength != 0)
                {
                    if (this.ContentLength > config.MaxUrlEncodedFormSize)
                    {
                        throw new HttpException(HttpStatusCode.PayloadTooLarge);
                    }

                    ParseQueryString(
                        System.Text.Encoding.ASCII.GetString(
                            this.ContentLength > 0
                            ? await reader.RepeatReadAsync(this.ContentLength, idletime, timeouttask, stoptask)
                            : await reader.ReadUntilCrlfAsync(config.MaxRequestLineSize, config.MaxUrlEncodedFormSize, idletime, timeouttask, stoptask)
                            ), this.Form);
                }

                this.Body = new LimitedBodyStream(reader, 0, idletime, timeouttask, stoptask);
            }
            else if (RequestUtility.IsMultipartRequest(this.ContentType) && this.ContentLength > 0 && this.ContentLength < config.MaxUrlEncodedFormSize && config.AutoParseMultipartFormData)
            {
                await ParseMultiPart(
                    async (headers, stream) =>
                {
                    var dispositionItems = RequestUtility.SplitHeaderLine(headers["Content-Disposition"]);
                    if (!string.Equals(dispositionItems.FirstOrDefault().Key, "form-data", StringComparison.OrdinalIgnoreCase))
                    {
                        throw new HttpException(HttpStatusCode.BadRequest);
                    }

                    var name = RequestUtility.GetHeaderComponent(headers["Content-Disposition"], "name");
                    if (string.IsNullOrWhiteSpace("name"))
                    {
                        throw new HttpException(HttpStatusCode.BadRequest);
                    }

                    var filename = RequestUtility.GetHeaderComponent(headers["Content-Disposition"], "filename");
                    var charset  = RequestUtility.GetHeaderComponent(headers["Content-Type"], "charset") ?? "ascii";

                    if (string.IsNullOrWhiteSpace(filename))
                    {
                        using (var sr = new StreamReader(stream, RequestUtility.GetEncodingForCharset(charset)))
                        {
                            var rtask = sr.ReadToEndAsync();
                            var rt    = await Task.WhenAny(timeouttask, stoptask, rtask);
                            if (rt != rtask)
                            {
                                if (rt == stoptask)
                                {
                                    throw new TaskCanceledException();
                                }
                                else
                                {
                                    throw new HttpException(HttpStatusCode.RequestTimeout);
                                }
                            }

                            this.Form[name] = rtask.Result;
                        }
                    }
                    else
                    {
                        var me = new MultipartItem(headers)
                        {
                            Name     = name,
                            Filename = filename,
                            Data     = new MemoryStream()
                        };

                        Task rtask;
                        Task rt;

                        using (var cs = new CancellationTokenSource(idletime))
                        {
                            rtask = stream.CopyToAsync(me.Data, 8 * 1024, cs.Token);
                            rt    = await Task.WhenAny(timeouttask, stoptask, rtask);
                        }

                        if (rt != rtask)
                        {
                            if (rt == stoptask)
                            {
                                throw new TaskCanceledException();
                            }
                            else
                            {
                                throw new HttpException(HttpStatusCode.RequestTimeout);
                            }
                        }

                        rtask.GetAwaiter().GetResult();
                        me.Data.Position = 0;

                        this.Files.Add(me);
                    }
                },
                    reader,
                    config,
                    idletime,
                    timeouttask,
                    stoptask
                    );

                this.Body = new LimitedBodyStream(reader, 0, idletime, timeouttask, stoptask);
            }
            else
            {
                this.Body = new LimitedBodyStream(reader, this.ContentLength, idletime, timeouttask, stoptask);
            }
        }