ChunkedReadStream.cs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. using System;
  2. using System.Globalization;
  3. using System.IO;
  4. namespace WinSCP
  5. {
  6. internal class ChunkedReadStream : Stream
  7. {
  8. public ChunkedReadStream(Stream baseStream)
  9. {
  10. _baseStream = baseStream;
  11. _remaining = 0;
  12. _eof = false;
  13. }
  14. public override bool CanRead => !_eof;
  15. public override bool CanSeek => false;
  16. public override bool CanWrite => false;
  17. public override long Length => throw new NotImplementedException();
  18. public override long Position { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
  19. public override void Flush()
  20. {
  21. throw new NotImplementedException();
  22. }
  23. public override int Read(byte[] buffer, int offset, int count)
  24. {
  25. int result;
  26. if (_eof)
  27. {
  28. result = 0;
  29. }
  30. else
  31. {
  32. if (_remaining == 0)
  33. {
  34. string lenStr = string.Empty;
  35. while (!lenStr.EndsWith("\r\n"))
  36. {
  37. if (lenStr.Length > 64)
  38. {
  39. throw new Exception("Too long chunk length line");
  40. }
  41. int b = _baseStream.ReadByte();
  42. if (b < 0)
  43. {
  44. throw new Exception("End of stream reached while reading chunk length line");
  45. }
  46. lenStr += (char)b;
  47. }
  48. lenStr = lenStr.Trim();
  49. _remaining = int.Parse(lenStr, NumberStyles.HexNumber);
  50. if (_remaining == 0)
  51. {
  52. _eof = true;
  53. }
  54. }
  55. // Not sure if it is ok to call Read with 0
  56. if (_remaining > 0)
  57. {
  58. int read = Math.Min(count, _remaining);
  59. result = _baseStream.Read(buffer, offset, read);
  60. _remaining -= result;
  61. }
  62. else
  63. {
  64. result = 0;
  65. }
  66. if (_remaining == 0)
  67. {
  68. int cr = _baseStream.ReadByte();
  69. if (cr != '\r')
  70. {
  71. throw new Exception("Expected CR");
  72. }
  73. int lf = _baseStream.ReadByte();
  74. if (lf != '\n')
  75. {
  76. throw new Exception("Expected LF");
  77. }
  78. }
  79. }
  80. return result;
  81. }
  82. public override long Seek(long offset, SeekOrigin origin)
  83. {
  84. throw new NotImplementedException();
  85. }
  86. public override void SetLength(long value)
  87. {
  88. throw new NotImplementedException();
  89. }
  90. public override void Write(byte[] buffer, int offset, int count)
  91. {
  92. throw new NotImplementedException();
  93. }
  94. private Stream _baseStream;
  95. private int _remaining;
  96. private bool _eof;
  97. }
  98. }