public int Find(byte[] boundary)
            {
                int position = StreamingMultiPartParser.findSequence(
                    buffer, Position, EndPosition,
                    boundary, 0, boundary.Length);

                return(position);
            }
            public bool StartsWith(byte[] prefix, int position = 0)
            {
                if (position < Position || position > EndPosition - prefix.Length)
                {
                    return(false);
                }
                bool result = StreamingMultiPartParser.startsWith(
                    buffer, position, EndPosition,
                    prefix, 0, prefix.Length);

                return(result);
            }
        private async Task parseSection()
        {
            // read headers
            NameValueCollection headers = new NameValueCollection();
            await buffer.Fill(bodyStream);

            while (!buffer.IsEmpty && !buffer.StartsWith(newLine))
            {
                string header = await parseHeader();

                string[] parts = header.Split(new char[] { ':' }, 2);
                if (parts.Length == 2)
                {
                    headers.Add(parts[0].Trim(), parts[1].Trim());
                }
            }
            if (buffer.IsEmpty)
            {
                return;
            }

            // read content
            buffer.Shift(newLine.Length);
            string subBoundary = getSubBoundary(headers);

            if (subBoundary == null)
            {
                MemoryStream content = await parseContent(boundary, newLine);

                if (SectionFound != null)
                {
                    SectionFound(this, new MultiPartSection()
                    {
                        Headers = headers, Content = content
                    });
                }
            }
            else
            {
                StreamingMultiPartParser subParser = new StreamingMultiPartParser(bodyStream, encoding, subBoundary, boundary, buffer);
                if (SectionFound != null)
                {
                    subParser.SectionFound += (o, e) => SectionFound(o, e);
                }
                await subParser.parseInternal();
            }
        }
        public void ShouldParseMultiPartFile()
        {
            Encoding encoding = Encoding.UTF8;
            byte[] binaryContent = encoding.GetBytes(getMultiPartContents());
            MemoryStream bodyStream = new MemoryStream(binaryContent);
            List<MultiPartSection> sections = new List<MultiPartSection>();

            StreamingMultiPartParser parser = new StreamingMultiPartParser(bodyStream, encoding, boundary);
            string parsedPreamble = null;
            string parsedEpilogue = null;
            parser.PreambleFound += (o, e) => parsedPreamble = toString(encoding, e);
            parser.SectionFound += (o, e) => sections.Add(e);
            parser.EpilogueFound += (o, e) => parsedEpilogue = toString(encoding, e);

            parser.Parse().Wait();

            Assert.AreEqual(preamble, parsedPreamble, "The preample was not read correctly.");

            Assert.AreEqual(2, sections.Count, "Two sections should have been parsed from the body.");
            var section1 = sections[0];
            Assert.AreEqual(formDataHeaderValue1, section1.Headers[formDataHeaderName1], "The first header was not parsed.");
            string parsedFormData = toString(encoding, section1.Content);
            Assert.AreEqual(formData, parsedFormData, "The form data was not read correctly.");

            var section2 = sections[1];
            Assert.AreEqual(formDataHeaderValue2, section2.Headers[formDataHeaderName2], "The second header was not parsed.");
            Assert.AreEqual(formDataHeaderValue3, section2.Headers[formDataHeaderName3], "The third header was not parsed.");
            string parsedFileData = toString(encoding, section2.Content);
            Assert.AreEqual(fileData, parsedFileData, "The file data was not read correctly.");

            Assert.AreEqual(epilogue, parsedEpilogue, "The epilogue was not parsed.");
        }
        public void ShouldHandlePreambleWithStartBoundary()
        {
            Encoding encoding = Encoding.UTF8;
            const string boundary = "ABC123abc456";
            const string thisPreamble = "This is an invalid message containing only a preamble.";
            const string contents = thisPreamble + @"
            --" + boundary;
            byte[] binaryContent = encoding.GetBytes(contents);
            MemoryStream bodyStream = new MemoryStream(binaryContent);

            StreamingMultiPartParser parser = new StreamingMultiPartParser(bodyStream, encoding, boundary);
            parser.PreambleFound += (o, e) => Assert.AreEqual(thisPreamble, toString(encoding, e));
            parser.SectionFound += (o, e) => Assert.Fail("No sections should be returned because the message ends prematurely.");
            parser.EpilogueFound += (o, e) => Assert.AreEqual(String.Empty, toString(encoding, e));

            parser.Parse().Wait();
        }
        public void ShouldHandlePreambleOnly()
        {
            Encoding encoding = Encoding.UTF8;
            const string preamble = "This is an invalid message containing only a preamble.";
            byte[] binaryContent = encoding.GetBytes(preamble);
            MemoryStream bodyStream = new MemoryStream(binaryContent);

            StreamingMultiPartParser parser = new StreamingMultiPartParser(bodyStream, encoding, "AaB03x");
            parser.PreambleFound += (o, e) => Assert.AreEqual(preamble, toString(encoding, e));
            parser.SectionFound += (o, e) => Assert.Fail("No sections should be found if the contents are empty.");
            parser.EpilogueFound += (o, e) => Assert.AreEqual(String.Empty, toString(encoding, e));

            parser.Parse().Wait();
        }
        public void ShouldHandlePartialSection()
        {
            Encoding encoding = Encoding.UTF8;
            const string contents = "--" + boundary + @"
            " + formDataHeaderName1 + ": " + formDataHeaderValue1 + @"
            ";
            byte[] binaryContent = encoding.GetBytes(contents);
            MemoryStream bodyStream = new MemoryStream(binaryContent);

            StreamingMultiPartParser parser = new StreamingMultiPartParser(bodyStream, encoding, boundary);
            parser.PreambleFound += (o, e) => Assert.AreEqual(String.Empty, toString(encoding, e));
            parser.SectionFound += (o, e) => Assert.Fail("No sections should be returned if the content is just the end boundary.");
            parser.EpilogueFound += (o, e) => Assert.AreEqual(String.Empty, toString(encoding, e));

            parser.Parse().Wait();
        }
        public void ShouldHandleMultiPartMixedContent()
        {
            Encoding encoding = Encoding.UTF8;
            byte[] binaryContent = encoding.GetBytes(getMultiPartMixedContents());
            MemoryStream bodyStream = new MemoryStream(binaryContent);

            List<MultiPartSection> sections = new List<MultiPartSection>();
            StreamingMultiPartParser parser = new StreamingMultiPartParser(bodyStream, encoding, "AaB03x");
            parser.PreambleFound += (o, e) => Assert.AreEqual(String.Empty, toString(encoding, e));
            parser.SectionFound += (o, e) => sections.Add(e);
            parser.EpilogueFound += (o, e) => Assert.AreEqual(String.Empty, toString(encoding, e));

            parser.Parse().Wait();

            Assert.AreEqual(3, sections.Count, "The wrong number of sections were found.");
            Assert.AreEqual("Larry", toString(encoding, sections[0].Content), "The first section content was wrong.");
            Assert.AreEqual("... contents of file1.txt ...", toString(encoding, sections[1].Content), "The second section content was wrong.");
            Assert.AreEqual("...contents of file2.gif...", toString(encoding, sections[2].Content), "The third section content was wrong.");
        }
        public void ShouldHandleEndBoundaryWithEpilogue()
        {
            Encoding encoding = Encoding.UTF8;
            const string boundary = "ABC123abc456";
            const string epilogue = "This is an epilogue. It comes after the end-boundary.";
            const string contents = "--" + boundary + @"--
            " + epilogue;
            byte[] binaryContent = encoding.GetBytes(contents);
            MemoryStream bodyStream = new MemoryStream(binaryContent);

            StreamingMultiPartParser parser = new StreamingMultiPartParser(bodyStream, encoding, boundary);
            parser.PreambleFound += (o, e) => Assert.AreEqual(String.Empty, toString(encoding, e));
            parser.SectionFound += (o, e) => Assert.Fail("No sections should be returned if the content is just the end boundary.");
            parser.EpilogueFound += (o, e) => Assert.AreEqual(epilogue, toString(encoding, e));

            parser.Parse().Wait();
        }
        public void ShouldHandleEmptyContent()
        {
            Encoding encoding = Encoding.UTF8;
            byte[] binaryContent = encoding.GetBytes(String.Empty);
            MemoryStream bodyStream = new MemoryStream(binaryContent);

            StreamingMultiPartParser parser = new StreamingMultiPartParser(bodyStream, encoding, "AaB03x");
            parser.PreambleFound += (o, e) => Assert.AreEqual(String.Empty, toString(encoding, e));
            parser.SectionFound += (o, e) => Assert.Fail("No sections should be found if the contents are empty.");
            parser.EpilogueFound += (o, e) => Assert.AreEqual(String.Empty, toString(encoding, e));

            parser.Parse().Wait();
        }
        private async Task parseSection()
        {
            // read headers
            NameValueCollection headers = new NameValueCollection();
            await buffer.Fill(bodyStream);
            while (!buffer.IsEmpty && !buffer.StartsWith(newLine))
            {
                string header = await parseHeader();
                string[] parts = header.Split(new char[] { ':' }, 2);
                if (parts.Length == 2)
                {
                    headers.Add(parts[0].Trim(), parts[1].Trim());
                }
            }
            if (buffer.IsEmpty)
            {
                return;
            }

            // read content
            buffer.Shift(newLine.Length);
            string subBoundary = getSubBoundary(headers);
            if (subBoundary == null)
            {
                MemoryStream content = await parseContent(boundary, newLine);
                if (SectionFound != null)
                {
                    SectionFound(this, new MultiPartSection() { Headers = headers, Content = content });
                }
            }
            else
            {
                StreamingMultiPartParser subParser = new StreamingMultiPartParser(bodyStream, encoding, subBoundary, boundary, buffer);
                if (SectionFound != null)
                {
                    subParser.SectionFound += (o, e) => SectionFound(o, e);
                }
                await subParser.parseInternal();
            }
        }
Example #12
0
        public static MultiPartResponse FromMultiPart(this IWebResponse response)
        {
            if (response == null)
            {
                throw new ArgumentNullException("response");
            }
            // Make sure it is a multi-part request
            string[] parts = response.Response.ContentType.Split(';').Select(s => s.Trim()).ToArray();
            if (!parts[0].Equals(ContentTypePrefix, StringComparison.InvariantCultureIgnoreCase))
            {
                return new MultiPartResponse() { Files = new MultiPartFileLookup(), FormData = new NameValueCollection() };
            }
            // Parse the content type parameters
            var contentTypeParameters = parts
                .Skip(1)
                .Select(p => p.Split(new char[] { '=' }, 2))
                .Where(p => p.Length == 2)
                .ToLookup(p => p[0], p => p[1], StringComparer.InvariantCultureIgnoreCase);
            // Check the boundary is specified, and only once
            if (contentTypeParameters["boundary"].Count() != 1)
            {
                return new MultiPartResponse() { Files = new MultiPartFileLookup(), FormData = new NameValueCollection() };
            }
            string boundary = contentTypeParameters["boundary"].First();

            using (Stream responseStream = response.Response.GetResponseStream())
            {
                Encoding encoding = response.Response.ContentEncoding == null
                    ? Encoding.UTF8
                    : Encoding.GetEncoding(response.Response.ContentEncoding);
                StreamingMultiPartParser parser = new StreamingMultiPartParser(responseStream, encoding, boundary);

                MultiPartFileLookup fileLookup = new MultiPartFileLookup();
                NameValueCollection collection = new NameValueCollection();
                parser.SectionFound += (o, e) =>
                {
                    var data = getSectionData(e);
                    if (data == null)
                    {
                        return;
                    }
                    if (String.IsNullOrWhiteSpace(data.FileName))
                    {
                        string value = encoding.GetString(data.Contents);
                        collection.Add(data.Name, value);
                    }
                    else
                    {
                        var file = new MultiPartFile()
                        {
                            Name = data.Name,
                            FileName = data.FileName,
                            ContentType = data.ContentType,
                            Contents = data.Contents
                        };
                        fileLookup.Add(file.Name, file);
                    }
                };
                return new MultiPartResponse() { Files = fileLookup, FormData = collection };
            }
        }
Example #13
0
        public static MultiPartResponse FromMultiPart(this IWebResponse response)
        {
            if (response == null)
            {
                throw new ArgumentNullException("response");
            }
            // Make sure it is a multi-part request
            string[] parts = response.Response.ContentType.Split(';').Select(s => s.Trim()).ToArray();
            if (!parts[0].Equals(ContentTypePrefix, StringComparison.InvariantCultureIgnoreCase))
            {
                return(new MultiPartResponse()
                {
                    Files = new MultiPartFileLookup(), FormData = new NameValueCollection()
                });
            }
            // Parse the content type parameters
            var contentTypeParameters = parts
                                        .Skip(1)
                                        .Select(p => p.Split(new char[] { '=' }, 2))
                                        .Where(p => p.Length == 2)
                                        .ToLookup(p => p[0], p => p[1], StringComparer.InvariantCultureIgnoreCase);

            // Check the boundary is specified, and only once
            if (contentTypeParameters["boundary"].Count() != 1)
            {
                return(new MultiPartResponse()
                {
                    Files = new MultiPartFileLookup(), FormData = new NameValueCollection()
                });
            }
            string boundary = contentTypeParameters["boundary"].First();

            using (Stream responseStream = response.Response.GetResponseStream())
            {
                Encoding encoding = response.Response.ContentEncoding == null
                    ? Encoding.UTF8
                    : Encoding.GetEncoding(response.Response.ContentEncoding);
                StreamingMultiPartParser parser = new StreamingMultiPartParser(responseStream, encoding, boundary);

                MultiPartFileLookup fileLookup = new MultiPartFileLookup();
                NameValueCollection collection = new NameValueCollection();
                parser.SectionFound += (o, e) =>
                {
                    var data = getSectionData(e);
                    if (data == null)
                    {
                        return;
                    }
                    if (String.IsNullOrWhiteSpace(data.FileName))
                    {
                        string value = encoding.GetString(data.Contents);
                        collection.Add(data.Name, value);
                    }
                    else
                    {
                        var file = new MultiPartFile()
                        {
                            Name        = data.Name,
                            FileName    = data.FileName,
                            ContentType = data.ContentType,
                            Contents    = data.Contents
                        };
                        fileLookup.Add(file.Name, file);
                    }
                };
                return(new MultiPartResponse()
                {
                    Files = fileLookup, FormData = collection
                });
            }
        }