public override void Parse() { try { MimeReaderState state = MimeReaderState.ReadingHeaders; MimeHeaderReader headerReader = new MimeHeaderReader(_encoding); // Read the first chunk int read = _stream.Read(_buffer, 0, _buffer.Length); // Skip past the first boundary int position = IndexOf(0, read) + _boundary.Length; // If the end is here, we're done (empty request) if (_encoding.GetString(_buffer, position, 2) == "--" && (char)_buffer[position + 3] == '\r' || (char)_buffer[position + 3] == '\n') { return; } // Skip past the end line if ((char)_buffer[position] == '\r') { position += 2; } else if ((char)_buffer[position] == '\n') { position += 1; } int zeroReads = 0; while (state != MimeReaderState.Finished) { switch (state) { case MimeReaderState.ReadingHeaders: position += headerReader.Read(_buffer, position); if (headerReader.HeaderComplete) { state = MimeReaderState.ReadingBody; _handler.BeginPart(headerReader.Headers); headerReader.Reset(); } break; case MimeReaderState.ReadingBody: int boundaryPos = IndexOf(position, read); // If block ends with \r or \n or a combo, consider that a boundary start if (boundaryPos == -1) { if (read > 1 && _buffer[read - 2] == '\r') { boundaryPos = read - 2; } else if (read > 0 && (_buffer[read - 1] == '\r' || _buffer[read - 1] == '\n')) { boundaryPos = read - 1; } } // If boundary not found if (boundaryPos == -1) { _handler.PartData(ref _buffer, position, read - position); position += read - position; } else { int actualLength; actualLength = boundaryPos - position; if (actualLength >= 2) { if ((char)_buffer[boundaryPos - 2] == '\r') { actualLength -= 2; } else if ((char)_buffer[boundaryPos - 2] == '\n') { actualLength -= 1; } } _handler.PartData(ref _buffer, position, actualLength); // Check for end if (boundaryPos <= read - (_boundary.Length + 2)) { // Check for "--" which means last part bool isLast = (_encoding.GetString(_buffer, boundaryPos + _boundary.Length, 2) == "--"); if (isLast) { state = MimeReaderState.Finished; } else { state = MimeReaderState.ReadingHeaders; } _handler.EndPart(isLast, true); position += (boundaryPos + _boundary.Length - position + 2); } // Boundary laps over else { // Also take the possible cr/lf combo removed above boundaryPos -= ((boundaryPos - position) - actualLength); int boundaryFragmentLength = read - boundaryPos; // Move the boundary data to the front of the buffer Buffer.BlockCopy(_buffer, boundaryPos, _buffer, 0, boundaryFragmentLength); // Load in more data read = _stream.Read(_buffer, boundaryFragmentLength, _buffer.Length - boundaryFragmentLength); // Reset position position = 0; // Adjust read count because of existing data in buffer read += boundaryFragmentLength; } } break; } // Get more data if we need it if (state != MimeReaderState.Finished) { if (position >= read) { read = _stream.Read(_buffer, 0, _buffer.Length); position = 0; if (read == 0) { if (zeroReads == 10) { throw new UploadDisconnectedException(); } zeroReads++; System.Threading.Thread.Sleep(100); } else { zeroReads = 0; } } } } } catch (UploadCancelledException) { throw; } catch { _handler.EndPart(false, false); throw; } }
public override void Parse() { try { MimeReaderState state = MimeReaderState.ReadingHeaders; MimeHeaderReader headerReader = new MimeHeaderReader(_encoding); // Read the first chunk int read = _stream.Read(_buffer, 0, _buffer.Length); // Skip past the first boundary int position = IndexOf(0, read) + _boundary.Length; // If the end is here, we're done (empty request) if (_encoding.GetString(_buffer, position, 2) == "--" && (char)_buffer[position + 3] == '\r' || (char)_buffer[position + 3] == '\n') return; // Skip past the end line if ((char)_buffer[position] == '\r') position += 2; else if ((char)_buffer[position] == '\n') position += 1; int zeroReads = 0; while (state != MimeReaderState.Finished) { switch (state) { case MimeReaderState.ReadingHeaders: position += headerReader.Read(_buffer, position); if (headerReader.HeaderComplete) { state = MimeReaderState.ReadingBody; _handler.BeginPart(headerReader.Headers); headerReader.Reset(); } break; case MimeReaderState.ReadingBody: int boundaryPos = IndexOf(position, read); // If block ends with \r or \n or a combo, consider that a boundary start if (boundaryPos == -1) { if (read > 1 && _buffer[read - 2] == '\r') boundaryPos = read - 2; else if (read > 0 && (_buffer[read - 1] == '\r' || _buffer[read - 1] == '\n')) boundaryPos = read - 1; } // If boundary not found if (boundaryPos == -1) { _handler.PartData(ref _buffer, position, read - position); position += read - position; } else { int actualLength; actualLength = boundaryPos - position; if (actualLength >= 2) { if ((char)_buffer[boundaryPos - 2] == '\r') actualLength -= 2; else if ((char)_buffer[boundaryPos - 2] == '\n') actualLength -= 1; } _handler.PartData(ref _buffer, position, actualLength); // Check for end if (boundaryPos <= read - (_boundary.Length + 2)) { // Check for "--" which means last part bool isLast = (_encoding.GetString(_buffer, boundaryPos + _boundary.Length, 2) == "--"); if (isLast) { state = MimeReaderState.Finished; } else { state = MimeReaderState.ReadingHeaders; } _handler.EndPart(isLast, true); position += (boundaryPos + _boundary.Length - position + 2); } // Boundary laps over else { // Also take the possible cr/lf combo removed above boundaryPos -= ((boundaryPos - position) - actualLength); int boundaryFragmentLength = read - boundaryPos; // Move the boundary data to the front of the buffer Buffer.BlockCopy(_buffer, boundaryPos, _buffer, 0, boundaryFragmentLength); // Load in more data read = _stream.Read(_buffer, boundaryFragmentLength, _buffer.Length - boundaryFragmentLength); // Reset position position = 0; // Adjust read count because of existing data in buffer read += boundaryFragmentLength; } } break; } // Get more data if we need it if (state != MimeReaderState.Finished) { if (position >= read) { read = _stream.Read(_buffer, 0, _buffer.Length); position = 0; if (read == 0) { if (zeroReads == 10) throw new UploadDisconnectedException(); zeroReads++; System.Threading.Thread.Sleep(100); } else { zeroReads = 0; } } } } } catch (UploadCancelledException) { throw; } catch { _handler.EndPart(false, false); throw; } }