<commit_before>﻿// Copyright (c) 2009 7Clouds

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Security.Authentication;

namespace Stratosphere.Imap
{
    [Flags]
    public enum ImapFetchOption
    {
        Envelope = 0x1,
        Flags = 0x2,
        BodyStructure = 0x4
    }

    public sealed class ImapClient : IDisposable
    {
        private readonly NetworkCredential _credentials;
        private readonly string _hostName;
        private readonly int _portNumber;
        private readonly bool _enableSsl;

        private TcpClient _tcpClient;
        private StreamReader _reader;
        private StreamWriter _writer;

        private long _nextCommandNumber;
        public long NextCommandNumber { get { return _nextCommandNumber; } }

        public ImapClient(string hostName, int portNumber, bool enableSsl, NetworkCredential credentials)
        {
            _hostName = hostName;
            _portNumber = portNumber;
            _enableSsl = enableSsl;
            _credentials = credentials;
        }

        public bool TryLogin()
        {
            if (InitializeConnection())
            {
                SendReceiveResult result = SendReceive(string.Format("LOGIN {0} {1}", _credentials.UserName, _credentials.Password));

                if (result.Status == SendReceiveStatus.OK)
                {
                    return true;
                }
                else if (result.Status == SendReceiveStatus.Bad)
                {
                    throw new InvalidOperationException();
                }
            }

            Dispose();
            return false;
        }

        public bool TrySaslLogin(string mechanism, string data)
        {
            if (InitializeConnection())
            {
                SendReceiveResult result = SendReceive(string.Format("AUTHENTICATE {0} {1}", mechanism, data));

                if (result.Status == SendReceiveStatus.OK)
                {
                    return true;
                }
                else //if (result.Status == SendReceiveStatus.Bad)
                {
                    StringBuilder linesBuilder = new StringBuilder();
                    foreach (var line in result.Lines)
                    {
                        linesBuilder.AppendLine(line);
                    }
                    throw new ArgumentException(linesBuilder.ToString(), "data");
                }
            }

            Dispose();
            return false;
        }

        private bool InitializeConnection()
        {
            bool isOk = false;

            if (null == _tcpClient)
            {
                _tcpClient = new TcpClient(_hostName, _portNumber);

                if (_enableSsl)
                {
                    SslStream sslStream = new SslStream(_tcpClient.GetStream(), false);
                    sslStream.AuthenticateAsClient(_hostName, null, SslProtocols.Tls, false);

                    _reader = new StreamReader(sslStream, Encoding.ASCII);
                    _writer = new StreamWriter(sslStream, Encoding.ASCII);
                }
                else
                {
                    _reader = new StreamReader(_tcpClient.GetStream(), Encoding.ASCII);
                    _writer = new StreamWriter(_tcpClient.GetStream(), Encoding.ASCII);
                }

                string response = _reader.ReadLine();

                isOk = (response.StartsWith("* OK"));
            }

            return isOk;
        }

        public IEnumerable<string> ListFolders(string reference, string wildcard)
        {
            SendReceiveResult result = SendReceive(string.Format("LIST \"{0}\" \"{1}\"", reference, wildcard));

            if (result.Status == SendReceiveStatus.OK)
            {
                foreach (string line in result.Lines)
                {
                    ImapList list = ImapList.Parse(line);
                    yield return list.GetStringAt(4);
                }
            }
            else if (result.Status == SendReceiveStatus.Bad)
            {
                throw new InvalidOperationException();
            }
        }
        
        public ImapFolder SelectFolder(string folderName)
        {
            ImapFolder folder = null;
            SendReceiveResult result = SendReceive(string.Format("SELECT \"{0}\"", folderName));

            if (result.Status == SendReceiveStatus.OK)
            {
                folder = new ImapFolder(result.Lines);
            }
            else if (result.Status == SendReceiveStatus.Bad)<commit_msg>Adding ListFoldersWithFlags and support for running XLIST<commit_after>﻿// Copyright (c) 2009 7Clouds

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Security.Authentication;

namespace Stratosphere.Imap
{
    [Flags]
    public enum ImapFetchOption
    {
        Envelope = 0x1,
        Flags = 0x2,
        BodyStructure = 0x4
    }

    public sealed class ImapClient : IDisposable
    {
        private readonly NetworkCredential _credentials;
        private readonly string _hostName;
        private readonly int _portNumber;
        private readonly bool _enableSsl;

        private TcpClient _tcpClient;
        private StreamReader _reader;
        private StreamWriter _writer;

        private long _nextCommandNumber;
        public long NextCommandNumber { get { return _nextCommandNumber; } }

        public ImapClient(string hostName, int portNumber, bool enableSsl, NetworkCredential credentials)
        {
            _hostName = hostName;
            _portNumber = portNumber;
            _enableSsl = enableSsl;
            _credentials = credentials;
        }

        public bool TryLogin()
        {
            if (InitializeConnection())
            {
                SendReceiveResult result = SendReceive(string.Format("LOGIN {0} {1}", _credentials.UserName, _credentials.Password));

                if (result.Status == SendReceiveStatus.OK)
                {
                    return true;
                }
                else if (result.Status == SendReceiveStatus.Bad)
                {
                    throw new InvalidOperationException();
                }
            }

            Dispose();
            return false;
        }

        public bool TrySaslLogin(string mechanism, string data)
        {
            if (InitializeConnection())
            {
                SendReceiveResult result = SendReceive(string.Format("AUTHENTICATE {0} {1}", mechanism, data));

                if (result.Status == SendReceiveStatus.OK)
                {
                    return true;
                }
                else //if (result.Status == SendReceiveStatus.Bad)
                {
                    StringBuilder linesBuilder = new StringBuilder();
                    foreach (var line in result.Lines)
                    {
                        linesBuilder.AppendLine(line);
                    }
                    throw new ArgumentException(linesBuilder.ToString(), "data");
                }
            }

            Dispose();
            return false;
        }

        private bool InitializeConnection()
        {
            bool isOk = false;

            if (null == _tcpClient)
            {
                _tcpClient = new TcpClient(_hostName, _portNumber);

                if (_enableSsl)
                {
                    SslStream sslStream = new SslStream(_tcpClient.GetStream(), false);
                    sslStream.AuthenticateAsClient(_hostName, null, SslProtocols.Tls, false);

                    _reader = new StreamReader(sslStream, Encoding.ASCII);
                    _writer = new StreamWriter(sslStream, Encoding.ASCII);
                }
                else
                {
                    _reader = new StreamReader(_tcpClient.GetStream(), Encoding.ASCII);
                    _writer = new StreamWriter(_tcpClient.GetStream(), Encoding.ASCII);
                }

                string response = _reader.ReadLine();

                isOk = (response.StartsWith("* OK"));
            }

            return isOk;
        }

        public IEnumerable<string> ListFolders(string reference, string wildcard)
        {
            SendReceiveResult result = SendReceive(string.Format("LIST \"{0}\" \"{1}\"", reference, wildcard));

            if (result.Status == SendReceiveStatus.OK)
            {
                foreach (string line in result.Lines)
                {
                    ImapList list = ImapList.Parse(line);
                    yield return list.GetStringAt(4);
                }
            }
            else if (result.Status == SendReceiveStatus.Bad)
            {
                throw new InvalidOperationException();
            }
        }

        public IEnumerable<KeyValuePair<string, IEnumerable<string>>> ListFoldersWithFlags(string reference, string wildcard, bool useXList)
        {
            SendReceiveResult result = SendReceive(string.Format("{0}LIST \"{1}\" \"{2}\"", 
                (useXList ? "X" : string.Empty), reference, wildcard));

            if (result.Status == SendReceiveStatus.OK)
            {
                foreach (string line in result.Lines)
                {
                    ImapList list = ImapList.Parse(line);
                    List<string> flags = new List<string>();

                    var flagsList = list.GetListAt(2);
                    for (int i = 0; i < flagsList.Count; ++i)
                    {
                        if (flagsList.IsStringAt(i))
                        {
                            flags.Add(flagsList.GetStringAt(i));
                        }
                    }

                    yield return new KeyValuePair<string, IEnumerable<string>>(list.GetStringAt(4), flags);
                }
            }
            else if (result.Status == SendReceiveStatus.Bad)
            {
                throw new InvalidOperationException();
            }
        }

        public ImapFolder SelectFolder(string folderName)
        {
            ImapFolder folder = null;
            SendReceiveResult result = SendReceive(string.Format("SELECT \"{0}\"", folderName));

            if (result.Status == SendReceiveStatus.OK)
            {
                folder = new ImapFolder(result.Lines);
            }
            else if (result.Status == SendReceiveStatus.Bad)
{'fraction_non_alphanumeric': 0.08329429401292983, 'fraction_numerical': 0.00468471844842125, 'mean_word_length': 1.4962581852198316, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '221229', 'n_tokens_mistral': 2706, 'n_tokens_neox': 2497, 'n_words': 593}