Example #1
0
        /// <summary>
        ///     Parses a section of the stream that is known to be parameter data.
        /// </summary>
        /// <param name="parameters">
        ///     The header parameters of this section. "name" must be a valid key.
        /// </param>
        /// <param name="reader">
        ///     The StreamReader to read the data from
        /// </param>
        /// <returns>
        ///     The <see cref="ParameterPart" /> containing the parsed data (name, value).
        /// </returns>
        /// <exception cref="MultipartParseException">
        ///     thrown if unexpected data is found such as running out of stream before hitting the boundary.
        /// </exception>
        private void ParseParameterPart(Dictionary <string, string> parameters, RebufferableBinaryReader reader)
        {
            var    data      = new StringBuilder();
            bool   firstTime = true;
            string line      = reader.ReadLine();

            while (line != boundary && line != endBoundary)
            {
                if (line == null)
                {
                    throw new MultipartParseException("Unexpected end of stream. Is there an end boundary?");
                }
                if (firstTime)
                {
                    data.Append(line);
                    firstTime = false;
                }
                else
                {
                    data.Append(Environment.NewLine);
                    data.Append(line);
                }
                line = reader.ReadLine();
            }
            if (line == endBoundary)
            {
                readEndBoundary = true;
            }
            var part = new ParameterPart(parameters["name"], data.ToString());

            ParameterHandler(part);
        }
Example #2
0
        /// <summary>
        ///     Detects the boundary from the input stream. Assumes that the
        ///     current position of the reader is the start of the file and therefore
        ///     the beginning of the boundary.
        /// </summary>
        /// <param name="reader">
        ///     The binary reader to parse
        /// </param>
        /// <returns>
        ///     The boundary string
        /// </returns>
        private static string DetectBoundary(RebufferableBinaryReader reader)
        {
            string boundary = string.Concat(reader.ReadLine().Skip(2));

            reader.Buffer("--" + boundary + "\n");
            return(boundary);
        }
Example #3
0
        /// <summary>
        ///     Begins executing the parser. This should be called after all handlers have been set.
        /// </summary>
        public void Run()
        {
            var reader = new RebufferableBinaryReader(stream, Encoding, BinaryBufferSize);

            if (boundary == null)
            {
                boundary = DetectBoundary(reader);
            }
            boundary          = "--" + boundary;
            endBoundary       = boundary + "--";
            boundaryBinary    = Encoding.GetBytes(boundary);
            endBoundaryBinary = Encoding.GetBytes(endBoundary);
            Debug.Assert(BinaryBufferSize >= endBoundaryBinary.Length, "binaryBufferSize must be bigger then the boundary");
            Parse(reader);
        }
Example #4
0
        /// <summary>
        ///     Parses the header of the next section of the multipart stream and
        ///     determines if it contains file data or parameter data.
        /// </summary>
        /// <param name="reader">
        ///     The StreamReader to read data from.
        /// </param>
        /// <exception cref="MultipartParseException">
        ///     thrown if unexpected data is hit such as end of stream.
        /// </exception>
        private void ParseSection(RebufferableBinaryReader reader)
        {
            var    parameters = new Dictionary <string, string>();
            string line       = reader.ReadLine();

            while (line != string.Empty)
            {
                if (line == null)
                {
                    throw new MultipartParseException("Unexpected end of stream");
                }
                if (line == boundary || line == endBoundary)
                {
                    throw new MultipartParseException("Unexpected end of section");
                }
                Dictionary <string, string> values = SplitBySemicolonIgnoringSemicolonsInQuotes(line).Select(x => x.Split(new[] {
                    ':',
                    '='
                }, 2)).Where(x => x.Length == 2).ToDictionary(x => x[0].Trim().Replace("\"", string.Empty).ToLower(), x => x[1].Trim().Replace("\"", string.Empty));
                try
                {
                    foreach (var pair in values)
                    {
                        parameters.Add(pair.Key, pair.Value);
                    }
                }
                catch (ArgumentException)
                {
                    throw new MultipartParseException("Duplicate field in section");
                }
                line = reader.ReadLine();
            }
            if (parameters.ContainsKey("filename"))
            {
                ParseFilePart(parameters, reader);
            }
            else
            {
                ParseParameterPart(parameters, reader);
            }
        }
Example #5
0
 /// <summary>
 ///     Begins the parsing of the stream into objects.
 /// </summary>
 /// <param name="reader">
 ///     The multipart/form-data binary reader to parse from.
 /// </param>
 /// <exception cref="MultipartParseException">
 ///     thrown on finding unexpected data such as a boundary before we are ready for one.
 /// </exception>
 private void Parse(RebufferableBinaryReader reader)
 {
     while (true)
     {
         string line = reader.ReadLine();
         if (line == boundary)
         {
             break;
         }
         if (line == null)
         {
             throw new MultipartParseException("Could not find expected boundary");
         }
     }
     while (!readEndBoundary)
     {
         ParseSection(reader);
     }
     if (StreamClosedHandler != null)
     {
         StreamClosedHandler();
     }
 }
Example #6
0
        /// <summary>
        ///     Parses a section of the stream that is known to be file data.
        /// </summary>
        /// <param name="parameters">
        ///     The header parameters of this file, expects "name" and "filename" to be valid keys
        /// </param>
        /// <param name="reader">
        ///     The StreamReader to read the data from
        /// </param>
        /// <returns>
        ///     The <see cref="FilePart" /> con[]              taining the parsed data (name, filename, stream containing file).
        /// </returns>
        private void ParseFilePart(Dictionary <string, string> parameters, RebufferableBinaryReader reader)
        {
            string name               = parameters["name"];
            string filename           = parameters["filename"];
            string contentType        = parameters.ContainsKey("content-type") ? parameters["content-type"] : "text/plain";
            string contentDisposition = parameters.ContainsKey("content-disposition") ? parameters["content-disposition"] : "form-data";
            var    curBuffer          = new byte[BinaryBufferSize];
            var    prevBuffer         = new byte[BinaryBufferSize];
            var    fullBuffer         = new byte[BinaryBufferSize * 2];
            int    curLength          = 0;
            int    prevLength         = 0;
            int    fullLength         = 0;

            prevLength = reader.Read(prevBuffer, 0, prevBuffer.Length);
            do
            {
                curLength = reader.Read(curBuffer, 0, curBuffer.Length);
                Buffer.BlockCopy(prevBuffer, 0, fullBuffer, 0, prevLength);
                Buffer.BlockCopy(curBuffer, 0, fullBuffer, prevLength, curLength);
                fullLength = prevLength + curLength;
                int endBoundaryPos    = SubsequenceFinder.Search(fullBuffer, endBoundaryBinary, fullLength);
                int endBoundaryLength = endBoundaryBinary.Length;
                int boundaryPos       = SubsequenceFinder.Search(fullBuffer, boundaryBinary, fullLength);
                int boundaryLength    = boundaryBinary.Length;
                if (boundaryPos + boundaryLength == fullLength)
                {
                    boundaryPos = -1;
                }
                int endPos       = -1;
                int endPosLength = 0;
                if (endBoundaryPos >= 0 && boundaryPos >= 0)
                {
                    if (boundaryPos < endBoundaryPos)
                    {
                        endPos       = boundaryPos;
                        endPosLength = boundaryLength;
                    }
                    else
                    {
                        endPos          = endBoundaryPos;
                        endPosLength    = endBoundaryLength;
                        readEndBoundary = true;
                    }
                }
                else if (boundaryPos >= 0 && endBoundaryPos < 0)
                {
                    endPos       = boundaryPos;
                    endPosLength = boundaryLength;
                }
                else if (boundaryPos < 0 && endBoundaryPos >= 0)
                {
                    endPos          = endBoundaryPos;
                    endPosLength    = endBoundaryLength;
                    readEndBoundary = true;
                }
                if (endPos != -1)
                {
                    int boundaryNewlineOffset = CalculateNewlineLength(ref fullBuffer, Math.Min(fullLength - 1, endPos + endPosLength));
                    int maxNewlineBytes       = Encoding.GetMaxByteCount(2);
                    int bufferNewlineOffset   = FindNextNewline(ref fullBuffer, Math.Max(0, endPos - maxNewlineBytes), maxNewlineBytes);
                    int bufferNewlineLength   = CalculateNewlineLength(ref fullBuffer, bufferNewlineOffset);
                    FileHandler(name, filename, contentType, contentDisposition, fullBuffer, endPos - bufferNewlineLength);
                    int writeBackOffset = endPos + endPosLength + boundaryNewlineOffset;
                    int writeBackAmount = (prevLength + curLength) - writeBackOffset;
                    var writeBackBuffer = new byte[writeBackAmount];
                    Buffer.BlockCopy(fullBuffer, writeBackOffset, writeBackBuffer, 0, writeBackAmount);
                    reader.Buffer(writeBackBuffer);
                    break;
                }
                FileHandler(name, filename, contentType, contentDisposition, prevBuffer, prevLength);
                byte[] tempBuffer = curBuffer;
                curBuffer  = prevBuffer;
                prevBuffer = tempBuffer;
                prevLength = curLength;
            }while (prevLength != 0);
        }