示例#1
0
        private static async Task <string> ReadCRLFLineAsync(Stream stream, Encoding encoding, CancellationToken ctsToken = default)
        {
            var bab = new ByteArrayBuilder();

            while (true)
            {
                int ch = await stream.ReadByteAsync(ctsToken);

                if (ch == -1)
                {
                    break;
                }

                if (ch == '\r')
                {
                    var ch2 = await stream.ReadByteAsync(ctsToken);

                    if (ch2 == '\n')
                    {
                        return(bab.ToString(encoding));
                    }
                    bab.Append(new byte[] { (byte)ch, (byte)ch2 });
                    continue;
                }
                bab.Append((byte)ch);
            }
            if (bab.Length > 0)
            {
                return(bab.ToString(encoding));
            }

            return(null);
        }
示例#2
0
        private static async Task <string> ReadCRLFLineAsync(Stream stream, Encoding encoding, CancellationToken ctsToken = default)
        {
            var bab = new ByteArrayBuilder();

            while (true)
            {
                int ch = await stream.ReadByteAsync(ctsToken).ConfigureAwait(false);

                if (ch == -1)
                {
                    break;
                }

                if (ch == '\r')
                {
                    var ch2 = await stream.ReadByteAsync(ctsToken).ConfigureAwait(false);

                    if (ch2 == '\n')
                    {
                        return(bab.ToString(encoding));
                    }
                    bab.Append(new byte[] { (byte)ch, (byte)ch2 });
                    continue;
                }
                bab.Append((byte)ch);
            }

            return(bab.Length > 0
                                ? bab.ToString(encoding)
                                : throw new FormatException("There's no CRLF."));
        }
示例#3
0
        public static async Task <string> ReadStartLineAsync(Stream stream, CancellationToken ctsToken = default)
        {
            // https://tools.ietf.org/html/rfc7230#section-3
            // A recipient MUST parse an HTTP message as a sequence of octets in an
            // encoding that is a superset of US-ASCII[USASCII].

            // Read until the first CRLF
            // the CRLF is part of the startLine
            // https://tools.ietf.org/html/rfc7230#section-3.5
            // Although the line terminator for the start-line and header fields is
            // the sequence CRLF, a recipient MAY recognize a single LF as a line
            // terminator and ignore any preceding CR.
            var bab  = new ByteArrayBuilder();
            int read = 0;

            while (read >= 0)
            {
                read = await stream.ReadByteAsync(ctsToken).ConfigureAwait(false);

                bab.Append((byte)read);
                if (LF == (byte)read)
                {
                    break;
                }
            }

            var startLine = bab.ToString(Encoding.ASCII);

            if (string.IsNullOrEmpty(startLine))
            {
                throw new FormatException($"{nameof(startLine)} cannot be null or empty.");
            }

            return(startLine);
        }
示例#4
0
        async Task <string> ReadLineAsync(bool doAsync, CancellationToken cancellationToken)
        {
            if (stream == null)
            {
                throw new InvalidOperationException();
            }

            using (var builder = new ByteArrayBuilder(64)) {
                bool complete;

                do
                {
                    if (doAsync)
                    {
                        complete = await stream.ReadLineAsync(builder, cancellationToken).ConfigureAwait(false);
                    }
                    else
                    {
                        complete = stream.ReadLine(builder, cancellationToken);
                    }
                } while (!complete);

                // FIXME: All callers expect CRLF to be trimmed, but many also want all trailing whitespace trimmed.
                builder.TrimNewLine();

                return(builder.ToString());
            }
        }
示例#5
0
        public async Task TestReadLineAsync()
        {
            var line1 = "This is a really long line..." + new string ('.', 4096) + "\r\n";
            var line2 = "And this is another line...\r\n";

            using (var stream = new ImapStream(new DummyNetworkStream(), new NullProtocolLogger())) {
                var data = Encoding.ASCII.GetBytes(line1 + line2);

                stream.Stream.Write(data, 0, data.Length);
                stream.Stream.Position = 0;

                using (var builder = new ByteArrayBuilder(64)) {
                    while (!await stream.ReadLineAsync(builder, CancellationToken.None))
                    {
                        ;
                    }

                    var text = builder.ToString();

                    Assert.AreEqual(line1, text, "Line1");
                }

                using (var builder = new ByteArrayBuilder(64)) {
                    while (!await stream.ReadLineAsync(builder, CancellationToken.None))
                    {
                        ;
                    }

                    var text = builder.ToString();

                    Assert.AreEqual(line2, text, "Line2");
                }
            }
        }
 public void ToStringTest()
 {
     using (ByteArrayBuilder builder = new ByteArrayBuilder())
     {
         builder.Append((byte)0x68);
         builder.Append((byte)0x01);
         builder.Append((byte)0x01);
         builder.Append((byte)0x02);
         builder.Append(new byte[2] {
             0x03, 0x04
         });
         string _data     = builder.ToString();
         string _expected = "68 01 01 02 03 04";
         Assert.AreEqual(_expected, _data);
     }
 }
    public static async Task <string> ReadStartLineAsync(Stream stream, CancellationToken ctsToken = default)
    {
        // https://tools.ietf.org/html/rfc7230#section-3
        // A recipient MUST parse an HTTP message as a sequence of octets in an
        // encoding that is a superset of US-ASCII[USASCII].

        // Read until the first CRLF
        // the CRLF is part of the startLine
        // https://tools.ietf.org/html/rfc7230#section-3.5
        // Although the line terminator for the start-line and header fields is
        // the sequence CRLF, a recipient MAY recognize a single LF as a line
        // terminator and ignore any preceding CR.
        var bab  = new ByteArrayBuilder();
        int read = 0;

        while (read >= 0)
        {
            read = await stream.ReadByteAsync(ctsToken).ConfigureAwait(false);

            // End of stream has been reached.
            if (read == -1)
            {
                Logger.LogTrace($"End of stream has been reached during reading HTTP start-line. Read bytes: '{ByteHelpers.ToHex(bab.ToArray())}'.");
                throw new TorConnectionReadException("HTTP start-line is incomplete. Tor circuit probably died.");
            }

            bab.Append((byte)read);
            if (LF == (byte)read)
            {
                break;
            }
        }

        var startLine = bab.ToString(Encoding.ASCII);

        if (string.IsNullOrEmpty(startLine))
        {
            throw new FormatException($"{nameof(startLine)} cannot be null or empty.");
        }

        return(startLine);
    }
示例#8
0
        public static ImapToken Create(ImapTokenType type, ByteArrayBuilder builder)
        {
            string value;

            if (type == ImapTokenType.Flag)
            {
                foreach (var token in CommonMessageFlagTokens)
                {
                    value = (string)token.Value;

                    if (builder.Equals(value, true))
                    {
                        return(token);
                    }
                }
            }
            else if (builder.Equals("NIL", true))
            {
                foreach (var token in NilTokens)
                {
                    value = (string)token.Value;

                    if (builder.Equals(value))
                    {
                        return(token);
                    }
                }

                var nil = new ImapToken(ImapTokenType.Nil, builder.ToString());
                NilTokens.Add(nil);

                return(nil);
            }
            else
            {
                if (builder.Equals("FETCH", false))
                {
                    return(Fetch);
                }
                if (builder.Equals("BODY", false))
                {
                    return(Body);
                }
                if (builder.Equals("BODYSTRUCTURE", false))
                {
                    return(BodyStructure);
                }
                if (builder.Equals("ENVELOPE", false))
                {
                    return(Envelope);
                }
                if (builder.Equals("FLAGS", false))
                {
                    return(Flags);
                }
                if (builder.Equals("INTERNALDATE", false))
                {
                    return(InternalDate);
                }
                if (builder.Equals("MODSEQ", false))
                {
                    return(ModSeq);
                }
                if (builder.Equals("RFC822.SIZE", false))
                {
                    return(Rfc822Size);
                }
                if (builder.Equals("UID", false))
                {
                    return(Uid);
                }
                if (builder.Equals("X-GM-LABELS", false))
                {
                    return(XGMLabels);
                }
                if (builder.Equals("X-GM-MSGID", false))
                {
                    return(XGMMsgId);
                }
                if (builder.Equals("X-GM-THRID", false))
                {
                    return(XGMThrId);
                }
            }

            value = builder.ToString();

            return(new ImapToken(type, value));
        }
示例#9
0
        async Task <SmtpResponse> ReadResponseAsync(bool doAsync, CancellationToken cancellationToken)
        {
            CheckDisposed();

            using (var builder = new ByteArrayBuilder(256)) {
                bool needInput = inputIndex == inputEnd;
                bool complete  = false;
                bool newLine   = true;
                bool more      = true;
                int  code      = 0;

                do
                {
                    if (needInput)
                    {
                        await ReadAheadAsync(doAsync, cancellationToken).ConfigureAwait(false);

                        needInput = false;
                    }

                    complete = false;

                    do
                    {
                        int startIndex = inputIndex;

                        if (newLine && inputIndex < inputEnd)
                        {
                            if (!ByteArrayBuilder.TryParse(input, ref inputIndex, inputEnd, out int value))
                            {
                                throw new SmtpProtocolException("Unable to parse status code returned by the server.");
                            }

                            if (inputIndex == inputEnd)
                            {
                                inputIndex = startIndex;
                                needInput  = true;
                                break;
                            }

                            if (code == 0)
                            {
                                code = value;
                            }
                            else if (value != code)
                            {
                                throw new SmtpProtocolException("The status codes returned by the server did not match.");
                            }

                            newLine = false;

                            if (input[inputIndex] != (byte)'\r' && input[inputIndex] != (byte)'\n')
                            {
                                more = input[inputIndex++] == (byte)'-';
                            }
                            else
                            {
                                more = false;
                            }

                            startIndex = inputIndex;
                        }

                        while (inputIndex < inputEnd && input[inputIndex] != (byte)'\r' && input[inputIndex] != (byte)'\n')
                        {
                            inputIndex++;
                        }

                        builder.Append(input, startIndex, inputIndex - startIndex);

                        if (inputIndex < inputEnd && input[inputIndex] == (byte)'\r')
                        {
                            inputIndex++;
                        }

                        if (inputIndex < inputEnd && input[inputIndex] == (byte)'\n')
                        {
                            if (more)
                            {
                                builder.Append(input[inputIndex]);
                            }
                            complete = true;
                            newLine  = true;
                            inputIndex++;
                        }
                    } while (more && inputIndex < inputEnd);

                    if (inputIndex == inputEnd)
                    {
                        needInput = true;
                    }
                } while (more || !complete);

                var message = builder.ToString();

                return(new SmtpResponse((SmtpStatusCode)code, message));
            }
        }