예제 #1
0
        public static Task<FormData> ParseMultipart(Stream stream, string boundary) {
            if (stream == null) {
                throw new ArgumentNullException("stream");
            }
            if (boundary == null) {
                throw new ArgumentNullException("boundary");
            }
            if (boundary.Length == 0) {
                throw new ArgumentException("Boundary cannot be empty", "boundary");
            }
            var form = new FormData();

            boundary = "--" + boundary;
            var boundaryBytes = Encoding.UTF8.GetBytes("\r\n" + boundary);

            string currentLine = stream.ReadLine(Encoding.UTF8);
            if (currentLine != boundary) {
                form.IsValid = false;
                return TaskHelper.Completed(form);
            }
            while (true) {
                currentLine = stream.ReadLine(Encoding.UTF8);
                // parse ContentDisposition line
                var match = ContentDispositionFormDataRegex.Match(currentLine);
                if (!match.Success) {
                    form.IsValid = false;
                    return TaskHelper.Completed(form);
                }
                string fieldName = match.Groups[1].Value;
                string fileName = match.Groups[2].Success ? match.Groups[3].Value : null;

                if (fileName != null) {
                    if (!ParseMultipartFile(stream, form, fieldName, fileName, boundaryBytes)) {
                        form.IsValid = false;
                        return TaskHelper.Completed(form);
                    }
                }
                else {
                    if (!ParseMultipartField(stream, form, fieldName, boundaryBytes)) {
                        form.IsValid = false;
                        return TaskHelper.Completed(form);
                    }
                }

                // check end or next
                currentLine = stream.ReadLine(Encoding.UTF8);
                // --boundary-- end
                if (currentLine == "--") {
                    break;
                }
                // --boundary between
                if (currentLine != string.Empty) {
                    form.IsValid = false;
                    return TaskHelper.Completed(form);
                }
            }
            return TaskHelper.Completed(form);
        }
예제 #2
0
        public static Task <FormData> ParseMultipart(Stream stream, string boundary)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }
            if (boundary == null)
            {
                throw new ArgumentNullException("boundary");
            }
            if (boundary.Length == 0)
            {
                throw new ArgumentException("Boundary cannot be empty", "boundary");
            }
            var form = new FormData();

            boundary = "--" + boundary;
            var boundaryBytes = Encoding.UTF8.GetBytes("\r\n" + boundary);

            string currentLine = stream.ReadLine(Encoding.UTF8);

            if (currentLine != boundary)
            {
                form.IsValid = false;
                return(TaskHelper.Completed(form));
            }
            while (true)
            {
                currentLine = stream.ReadLine(Encoding.UTF8);
                // parse ContentDisposition line
                var match = ContentDispositionFormDataRegex.Match(currentLine);
                if (!match.Success)
                {
                    form.IsValid = false;
                    return(TaskHelper.Completed(form));
                }
                string fieldName = match.Groups[1].Value;
                string fileName  = match.Groups[2].Success ? match.Groups[3].Value : null;

                if (fileName != null)
                {
                    if (!ParseMultipartFile(stream, form, fieldName, fileName, boundaryBytes))
                    {
                        form.IsValid = false;
                        return(TaskHelper.Completed(form));
                    }
                }
                else
                {
                    if (!ParseMultipartField(stream, form, fieldName, boundaryBytes))
                    {
                        form.IsValid = false;
                        return(TaskHelper.Completed(form));
                    }
                }

                // check end or next
                currentLine = stream.ReadLine(Encoding.UTF8);
                // --boundary-- end
                if (currentLine == "--")
                {
                    break;
                }
                // --boundary between
                if (currentLine != string.Empty)
                {
                    form.IsValid = false;
                    return(TaskHelper.Completed(form));
                }
            }
            return(TaskHelper.Completed(form));
        }
예제 #3
0
        private static bool ParseMultipartField(Stream stream, FormData form, string fieldName, byte[] boundaryBytes)
        {
            string contentType = null;
            string headerLine;
            Match  match;

            while ((headerLine = stream.ReadLine(Encoding.UTF8)) != string.Empty)
            {
                // parse 'Content-" headers
                match = ContentTypeFormDataRegex.Match(headerLine);
                if (match.Success)
                {
                    // nested: Content-Type: multipart/mixed; boundary=BbC04y
                    contentType = match.Groups[1].Value.Trim();
                    if (match.Groups[2].Success)
                    {
                        string fileBoundary      = match.Groups[4].Value;
                        byte[] fileBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + fileBoundary);
                        byte[] temp;
                        if (!stream.ReadTo(fileBoundaryBytes, out temp))
                        {
                            return(false);
                        }
                        if (stream.ReadLine(Encoding.UTF8) != string.Empty)
                        {
                            return(false);
                        }
                        bool moreFiles = true;
                        while (moreFiles)
                        {
                            string line = stream.ReadLine(Encoding.UTF8);
                            match = ContentDispositionFileRegex.Match(line);
                            if (!match.Success)
                            {
                                return(false);
                            }
                            string filename = match.Groups[1].Value;
                            if (!ParseMultipartFile(stream, form, fieldName, filename, fileBoundaryBytes))
                            {
                                return(false);
                            }
                            line = stream.ReadLine(Encoding.UTF8);
                            if (line == "--")
                            {
                                moreFiles = false;
                            }
                            else if (line != string.Empty)
                            {
                                return(false);
                            }
                        }
                        // NB: CrLf already ripped here
                        var boundaryNoCrLf = new byte[boundaryBytes.Length - 2];
                        Array.Copy(boundaryBytes, 2, boundaryNoCrLf, 0, boundaryBytes.Length - 2);
                        if (!stream.ReadTo(boundaryNoCrLf, out temp))
                        {
                            return(false);
                        }
                        if (temp.Length != 0)
                        {
                            return(false);
                        }
                        return(true);
                    }
                }
            }
            if (contentType == null)
            {
                contentType = "text/plain";
            }

            byte[] value;
            if (!stream.ReadTo(boundaryBytes, out value))
            {
                return(false);
            }
            // handle charset: content-type: text/plain;charset=windows-1250
            match = CharsetRegex.Match(contentType);
            Encoding encoding = match.Success ? Encoding.GetEncoding(match.Groups[2].Value) : Encoding.UTF8;

            form[fieldName] = encoding.GetString(value);

            return(true);
        }
예제 #4
0
        private static bool ParseMultipartFile(Stream stream, FormData form, string fieldName, string fileName, byte[] boundaryBytes) {
            string contentType = null;
            string headerLine;
            while ((headerLine = stream.ReadLine(Encoding.UTF8)) != string.Empty) {
                // parse 'Content-" headers
                var match = ContentTypeFileRegex.Match(headerLine);
                if (match.Success) {
                    contentType = match.Groups[1].Value.Trim();
                }
            }
            if (contentType == null) {
                //todo: infer from file type (extension)
                contentType = "application/octet-stream";
            }

            byte[] data;
            if (!stream.ReadTo(boundaryBytes, out data)) {
                return false;
            }
            form.Files.Add(new PostedFile(fieldName, fileName, data, contentType));
            return true;
        }
예제 #5
0
        private static bool ParseMultipartField(Stream stream, FormData form, string fieldName, byte[] boundaryBytes) {
            string contentType = null;
            string headerLine;
            Match match;
            while ((headerLine = stream.ReadLine(Encoding.UTF8)) != string.Empty) {
                // parse 'Content-" headers
                match = ContentTypeFormDataRegex.Match(headerLine);
                if (match.Success) {
                    // nested: Content-Type: multipart/mixed; boundary=BbC04y
                    contentType = match.Groups[1].Value.Trim();
                    if (match.Groups[2].Success) {
                        string fileBoundary = match.Groups[4].Value;
                        byte[] fileBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + fileBoundary);
                        byte[] temp;
                        if (!stream.ReadTo(fileBoundaryBytes, out temp)) {
                            return false;
                        }
                        if (stream.ReadLine(Encoding.UTF8) != string.Empty) {
                            return false;
                        }
                        bool moreFiles = true;
                        while (moreFiles) {
                            string line = stream.ReadLine(Encoding.UTF8);
                            match = ContentDispositionFileRegex.Match(line);
                            if (!match.Success) {
                                return false;
                            }
                            string filename = match.Groups[1].Value;
                            if (!ParseMultipartFile(stream, form, fieldName, filename, fileBoundaryBytes)) {
                                return false;
                            }
                            line = stream.ReadLine(Encoding.UTF8);
                            if (line == "--") {
                                moreFiles = false;
                            }
                            else if (line != string.Empty) {
                                return false;
                            }
                        }
                        // NB: CrLf already ripped here
                        var boundaryNoCrLf = new byte[boundaryBytes.Length - 2];
                        Array.Copy(boundaryBytes, 2, boundaryNoCrLf, 0, boundaryBytes.Length - 2);
                        if (!stream.ReadTo(boundaryNoCrLf, out temp)) {
                            return false;
                        }
                        if (temp.Length != 0) {
                            return false;
                        }
                        return true;
                    }
                }
            }
            if (contentType == null) {
                contentType = "text/plain";
            }

            byte[] value;
            if (!stream.ReadTo(boundaryBytes, out value)) {
                return false;
            }
            // handle charset: content-type: text/plain;charset=windows-1250
            match = CharsetRegex.Match(contentType);
            Encoding encoding = match.Success ? Encoding.GetEncoding(match.Groups[2].Value) : Encoding.UTF8;
            form[fieldName] = encoding.GetString(value);

            return true;
        }
예제 #6
0
 /// <summary>
 /// Builds a FormData from the specified input stream, 
 /// which is assumed to be in x-www-form-urlencoded format.
 /// </summary>
 /// <param name="stream">the input stream</param>
 /// <returns>a populated FormData object</returns>
 public static Task<FormData> ParseUrlEncoded(Stream stream) {
     var form = new FormData();
     string input = stream.ReadAll();
     var pairs = input.Split(UrlSplitTokens, StringSplitOptions.RemoveEmptyEntries);
     foreach (var pair in pairs) {
         var nameValue = pair.Split('=');
         form[nameValue[0]] = UrlHelper.Decode(nameValue[1]);
     }
     return TaskHelper.Completed(form);
 }
예제 #7
0
        public void HandleMultipartData()
        {
            string httpContent = @"--AaB03x
Content-Disposition: form-data; name=""SingleFile""; filename=""single.txt""
Content-Type: text/plain

Just a text file.
--AaB03x
Content-Disposition: form-data; name=""Test""

Pass
--AaB03x
Content-Disposition: form-data; name=""MultipleFiles""
Content-Type: multipart/mixed; boundary=BbC04y

--BbC04y
Content-Disposition: file; filename=""file1.txt""
Content-Type: text/plain

...contents of file1.txt...
--BbC04y
Content-Disposition: file; filename=""file2.gif""
Content-Type: image/gif
Content-Transfer-Encoding: binary

...contents of file2.gif...
--BbC04y--
--AaB03x--";

            var host    = new TestHostAndServer(FormsMiddleware.ParseFormData, Pipeline.ReturnDone);
            var request = TestRequest.Post("/")
                          .WithContentType(FormData.GetMultipartContentType("AaB03x"))
                          .WithContent(httpContent);
            IContext context = host.Process(request);
            var      form    = context.Request.FormData;

            form.IsValid.ShouldBeTrue();
            form.Files.Count.ShouldEqual(3);
            var file = form.Files[0];

            file.FieldName.ShouldEqual("SingleFile");
            file.FileName.ShouldEqual("single.txt");
            file.ContentType.ShouldEqual("text/plain");
            file.ContentLength.ShouldEqual(17);
            file.InputStream.ReadAll()
            .ShouldEqual("Just a text file.");
            file = form.Files[1];
            file.FieldName.ShouldEqual("MultipleFiles");
            file.FileName.ShouldEqual("file1.txt");
            file.ContentType.ShouldEqual("text/plain");
            file.ContentLength.ShouldEqual(27);
            file.InputStream.ReadAll()
            .ShouldEqual("...contents of file1.txt...");
            file = form.Files[2];
            file.FieldName.ShouldEqual("MultipleFiles");
            file.FileName.ShouldEqual("file2.gif");
            file.ContentType.ShouldEqual("image/gif");
            file.ContentLength.ShouldEqual(27);
            file.InputStream.ReadAll()
            .ShouldEqual("...contents of file2.gif...");
            form.Values.Count.ShouldEqual(1);
            form["Test"].ShouldEqual("Pass");
        }