/// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="requireSSL">Specifies if this mechanism is available to SSL connections only.</param>
        public AUTH_SASL_ServerMechanism_DigestMd5(bool requireSSL)
        {
            m_RequireSSL = requireSSL;

            m_Nonce = Auth_HttpDigest.CreateNonce();
        }
        /// <summary>
        /// Continues authentication process.
        /// </summary>
        /// <param name="clientResponse">Client sent SASL response.</param>
        /// <returns>Retunrns challange response what must be sent to client or null if authentication has completed.</returns>
        /// <exception cref="ArgumentNullException">Is raised when <b>clientResponse</b> is null reference.</exception>
        public override string Continue(string clientResponse)
        {
            if (clientResponse == null)
            {
                throw new ArgumentNullException("clientResponse");
            }

            /* RFC 2831.
             *  The base64-decoded version of the SASL exchange is:
             *
             *  S: realm="elwood.innosoft.com",nonce="OA6MG9tEQGm2hh",qop="auth",
             *     algorithm=md5-sess,charset=utf-8
             *  C: charset=utf-8,username="******",realm="elwood.innosoft.com",
             *     nonce="OA6MG9tEQGm2hh",nc=00000001,cnonce="OA6MHXh6VqTrRk",
             *     digest-uri="imap/elwood.innosoft.com",
             *     response=d388dad90d4bbd760a152321f2143af7,qop=auth
             *  S: rspauth=ea40f60335c427b5527b84dbabcdfffd
             *  C:
             *  S: ok
             *
             *  The password in this example was "secret".
             */

            if (m_State == 0)
            {
                m_State++;

                return("realm=\"" + m_Realm + "\",nonce=\"" + m_Nonce +
                       "\",qop=\"auth\",algorithm=md5-sess,charset=utf-8");
            }
            else if (m_State == 1)
            {
                m_State++;

                Auth_HttpDigest auth = new Auth_HttpDigest(clientResponse, "AUTHENTICATE");
                auth.Qop       = "auth";
                auth.Algorithm = "md5-sess";

                // Check realm and nonce value.
                if (m_Realm != auth.Realm || m_Nonce != auth.Nonce)
                {
                    return("rspauth=\"\"");
                }

                m_UserName = auth.UserName;
                AUTH_e_UserInfo result = OnGetUserInfo(auth.UserName);
                if (result.UserExists)
                {
                    if (auth.Authenticate(result.UserName, result.Password))
                    {
                        m_IsAuthenticated = true;

                        return("rspauth=" + auth.CalculateRspAuth(result.UserName, result.Password));
                    }
                }

                return("rspauth=\"\"");
            }
            else
            {
                m_IsCompleted = true;
            }

            return(null);
        }
        /// <summary>
        /// Continues authentication process.
        /// </summary>
        /// <param name="clientResponse">Client sent SASL response.</param>
        /// <returns>Retunrns challange response what must be sent to client or null if authentication has completed.</returns>
        /// <exception cref="ArgumentNullException">Is raised when <b>clientResponse</b> is null reference.</exception>
        public override string Continue(string clientResponse)
        {
            if (clientResponse == null)
            {
                throw new ArgumentNullException("clientResponse");
            }

            /* RFC 2831.
                The base64-decoded version of the SASL exchange is:

                S: realm="elwood.innosoft.com",nonce="OA6MG9tEQGm2hh",qop="auth",
                   algorithm=md5-sess,charset=utf-8
                C: charset=utf-8,username="******",realm="elwood.innosoft.com",
                   nonce="OA6MG9tEQGm2hh",nc=00000001,cnonce="OA6MHXh6VqTrRk",
                   digest-uri="imap/elwood.innosoft.com",
                   response=d388dad90d4bbd760a152321f2143af7,qop=auth
                S: rspauth=ea40f60335c427b5527b84dbabcdfffd
                C: 
                S: ok

                The password in this example was "secret".
            */

            if (m_State == 0)
            {
                m_State++;

                return "realm=\"" + m_Realm + "\",nonce=\"" + m_Nonce +
                       "\",qop=\"auth\",algorithm=md5-sess,charset=utf-8";
            }
            else if (m_State == 1)
            {
                m_State++;

                Auth_HttpDigest auth = new Auth_HttpDigest(clientResponse, "AUTHENTICATE");
                auth.Qop = "auth";
                auth.Algorithm = "md5-sess";

                // Check realm and nonce value.
                if (m_Realm != auth.Realm || m_Nonce != auth.Nonce)
                {
                    return "rspauth=\"\"";
                }

                m_UserName = auth.UserName;
                AUTH_e_UserInfo result = OnGetUserInfo(auth.UserName);
                if (result.UserExists)
                {
                    if (auth.Authenticate(result.UserName, result.Password))
                    {
                        m_IsAuthenticated = true;

                        return "rspauth=" + auth.CalculateRspAuth(result.UserName, result.Password);
                    }
                }

                return "rspauth=\"\"";
            }
            else
            {
                m_IsCompleted = true;
            }

            return null;
        }