private Dictionary <string, StringValues> ReadHeaders()
        {
            int totalSize   = 0;
            var accumulator = new KeyMultValuesPair();
            var line        = _stream.ReadLine(HeadersLengthLimit - totalSize);

            while (!string.IsNullOrEmpty(line))
            {
                if (HeadersLengthLimit - totalSize < line.Length)
                {
                    throw new InvalidDataException($"Multipart headers length limit {HeadersLengthLimit} exceeded.");
                }
                totalSize += line.Length;
                int splitIndex = line.IndexOf(':');
                if (splitIndex <= 0)
                {
                    throw new InvalidDataException($"Invalid header line: {line}");
                }

                var name  = line.Substring(0, splitIndex);
                var value = line.Substring(splitIndex + 1, line.Length - splitIndex - 1).Trim();
                accumulator.Append(name, value);
                if (accumulator.KeyCount > HeadersCountLimit)
                {
                    throw new InvalidDataException($"Multipart headers count limit {HeadersCountLimit} exceeded.");
                }

                line = _stream.ReadLine(HeadersLengthLimit - totalSize);
            }

            return(accumulator.GetResults());
        }
예제 #2
0
        public override int Read(byte[] buffer, int offset, int count)
        {
            if (_finished)
            {
                return(0);
            }

            PositionInnerStream();
            if (!_innerStream.EnsureBuffered(_boundary.FinalBoundaryLength))
            {
                throw new IOException("Unexpected end of Stream, the content may have already been read by another component. ");
            }
            var bufferedData = _innerStream.BufferedData;

            // scan for a boundary match, full or partial.
            int read;

            if (SubMatch(bufferedData, _boundary.BoundaryBytes, out var matchOffset, out var matchCount))
            {
                // We found a possible match, return any data before it.
                if (matchOffset > bufferedData.Offset)
                {
                    read = _innerStream.Read(buffer, offset, Math.Min(count, matchOffset - bufferedData.Offset));
                    return(UpdatePosition(read));
                }

                var length = _boundary.BoundaryBytes.Length;
                Debug.Assert(matchCount == length);

                // "The boundary may be followed by zero or more characters of
                // linear whitespace. It is then terminated by either another CRLF"
                // or -- for the final boundary.
                var boundary = _bytePool.Rent(length);
                read = _innerStream.Read(boundary, 0, length);
                _bytePool.Return(boundary);
                Debug.Assert(read == length);                            // It should have all been buffered

                var remainder = _innerStream.ReadLine(lengthLimit: 100); // Whitespace may exceed the buffer.
                remainder = remainder.Trim();
                if (string.Equals("--", remainder, StringComparison.Ordinal))
                {
                    FinalBoundaryFound = true;
                }
                Debug.Assert(FinalBoundaryFound || string.Equals(string.Empty, remainder, StringComparison.Ordinal), "Un-expected data found on the boundary line: " + remainder);
                _finished = true;
                return(0);
            }

            // No possible boundary match within the buffered data, return the data from the buffer.
            read = _innerStream.Read(buffer, offset, Math.Min(count, bufferedData.Count));
            return(UpdatePosition(read));
        }