/// <summary>
        /// Decode digestCredentials to get a DpspSaslResponse instance
        /// </summary>
        /// <param name="digestCredentials">Dpsp digest credentials</param>
        /// <returns>DpspSaslResponse instance</returns>
        public static DpspSaslResponse Decode(string digestCredentials)
        {
            DpspSaslResponse dpspSaslResponse = new DpspSaslResponse();

            DpspResponse.Decode(digestCredentials, dpspSaslResponse);
            return(dpspSaslResponse);
        }
        /// <summary>
        /// Decode
        /// </summary>
        /// <param name="digestCredentials">http digest credentials string</param>
        /// <param name="dpspResponse">dpspResponse instance</param>
        /// <exception cref="ArgumentNullException">
        /// Thrown when digestCredentials or digestCredentials is null
        /// </exception>
        /// <exception cref="ArgumentException">
        /// Thrown when digestCredentials or dpspResponse is invalid
        /// </exception>
        protected static void Decode(
            string digestCredentials,
            DpspResponse dpspResponse)
        {
            if (digestCredentials == null)
            {
                throw new ArgumentNullException("digestCredentials");
            }

            if (digestCredentials.Length == 0)
            {
                throw new ArgumentException(
                          "digestCredentials should not be empty",
                          "digestCredentials");
            }

            if (dpspResponse == null)
            {
                throw new ArgumentNullException("dpspResponse");
            }

            digestCredentials = digestCredentials.TrimStart();

            if (!digestCredentials.StartsWith(DpspUtility.DIGEST + DpspUtility.SPACE))
            {
                throw new ArgumentException(
                          "digestResponseCredentials should start with " + DpspUtility.DIGEST + "(SPACE)",
                          "digestCredentials");
            }

            // ABNF credentials = "Digest" digest-response
            string digestResponse = digestCredentials.Substring(DpspUtility.DIGEST.Length + DpspUtility.SPACE.Length);

            Regex regex = new Regex(
                DpspUtility.ATTRIBUTE_VALUE_PAIR_REGULAR_EXPRESSION_PATTERN,
                RegexOptions.IgnorePatternWhitespace);

            MatchCollection matchCollection = regex.Matches(digestResponse);

            if (matchCollection.Count == 0)
            {
                throw new ArgumentException("invalid digestResponse", "digestCredentials");
            }

            foreach (Match match in matchCollection)
            {
                string key;
                string value;

                if (match.Groups[DpspUtility.Attribute].Success)
                {
                    key = match.Groups[DpspUtility.Attribute].Value;
                }
                else
                {
                    throw new ArgumentException("invalid digestResponse", "digestCredentials");
                }

                if (match.Groups[DpspUtility.VALUE].Success)
                {
                    value = match.Groups[DpspUtility.VALUE].Value;
                }
                else
                {
                    throw new ArgumentException("invalid digestResponse", "digestCredentials");
                }

                dpspResponse.SetAttributeValue(key, value);
            }
        }
 /// <summary>
 /// Set Qop type
 /// </summary>
 /// <param name="dpspResponse">DpspResponse instance</param>
 /// <param name="digestValidationReq">DIGEST_VALIDATION_REQ structure</param>
 /// <returns>DIGEST_VALIDATION_REQ structure</returns>
 private static DIGEST_VALIDATION_REQ SetQopType(
     DpspResponse dpspResponse, DIGEST_VALIDATION_REQ digestValidationReq)
 {
     if (dpspResponse.MessageQop == null || dpspResponse.MessageQop.Length == 0)
     {
         digestValidationReq.QopType = QopType_Values.None;
     }
     else
     {
         switch (dpspResponse.MessageQop.ToLower())
         {
             case QOP_AUTHENTICATION_NAME:
                 digestValidationReq.QopType = QopType_Values.Authenticate;
                 break;
             case QOP_AUTHENTICATION_AND_INTEGRITY_NAME:
                 digestValidationReq.QopType = QopType_Values.AuthenticateAndIntegrity;
                 break;
             case QOP_AUTHENTICATION_WITH_INTEGRITY_AND_ENCRYPTION_NAME:
                 digestValidationReq.QopType =
                     QopType_Values.AuthenticateWithIntegrityProtectionAndEncryption;
                 break;
             default:
                 throw new ArgumentException("invalid QopType value in digestResponse parameter");
         }
     }
     return digestValidationReq;
 }
        /// <summary>
        /// Encode common part of DigestValidationRequest
        /// </summary>
        /// <param name="serverName">server name</param>
        /// <param name="domainName">domain name</param>
        /// <param name="accountName">account name</param>
        /// <param name="digestType">digest type</param>
        /// <param name="digestChallengeAlgorithm">digest challenge algorithm</param>
        /// <param name="dpspResponse">dpspResponse</param>
        /// <param name="payload">DIGEST_VALIDATION_REQ_Payload structure</param>
        /// <param name="digestValidationReq">digestValidationReq</param>
        private static void EncodeCommonPartOfDigestValidationRequest(
            string serverName,
            string domainName,
            string accountName,
            DigestType_Values digestType,
            string digestChallengeAlgorithm,
            DpspResponse dpspResponse,
            ref DIGEST_VALIDATION_REQ_Payload payload,
            ref DIGEST_VALIDATION_REQ digestValidationReq
            )
        {
            digestValidationReq.MessageType = DIGEST_VALIDATION_REQ_MessageType_Values.Default;
            digestValidationReq.Version = DIGEST_VALIDATION_REQ_Version_Values.Default;
            digestValidationReq.DigestType = digestType;
            digestValidationReq = SetQopType(dpspResponse, digestValidationReq);
            digestValidationReq = SetAlgType(digestChallengeAlgorithm, digestValidationReq);
            digestValidationReq.CharsetType = CharsetType_Values.UTF8;
            digestValidationReq.NameFormat = NameFormat_Values.None;
            digestValidationReq.Flags =
                DIGEST_VALIDATION_FLAGS.FormatOfUserNameAndRealmIsDeterminedByDC
                | DIGEST_VALIDATION_FLAGS.RequestIsSentFromServer;

            digestValidationReq.Reserved3 = DIGEST_VALIDATION_REQ_Reserved3_Values.Default;
            digestValidationReq.Reserved4 = Reserved4_Values.Default;
            digestValidationReq.Pad1 = DIGEST_VALIDATION_REQ_Pad1_Values.Default;

            // Each of the strings MUST be included. If the string value is empty,
            // then a terminating null character MUST be used for the value.
            payload.Username = dpspResponse.GetAttributeValue(DpspUtility.USER_NAME_DIRECTIVE);
            payload.Realm = dpspResponse.GetAttributeValue(DpspUtility.REALM_DIRECTIVE);
            payload.Nonce = dpspResponse.GetAttributeValue(DpspUtility.NONCE_DIRECTIVE);
            payload.CNonce = dpspResponse.GetAttributeValue(DpspUtility.CNONCE_DIRECTIVE);
            payload.NonceCount = dpspResponse.GetAttributeValue(DpspUtility.NONCE_COUNT_DIRECTIVE);
            payload.QOP = dpspResponse.GetAttributeValue(DpspUtility.MESSAGE_QOP_DIRECTIVE);
            payload.Response = dpspResponse.GetAttributeValue(DpspUtility.RESPONSE_DIRECTIVE);

            payload.AccountName = accountName; ;
            payload.ServerName = serverName;
            payload.Domain = domainName;
        }
        /// <summary>
        /// Construct DIGEST_VALIDATION_REQ structure
        /// </summary>
        /// <param name="serverName">server name</param>
        /// <param name="domainName">domain name</param>
        /// <param name="accountName">account name</param>
        /// <param name="httpMethod">http method</param>
        /// <param name="digestType">digest type</param>
        /// <param name="digestChallengeAlgorithm">digest challenge algorithm</param>
        /// <param name="dpspResponse">dpspResponse class instance</param>
        /// <returns>DIGEST_VALIDATION_REQ structure</returns>
        /// <exception cref="ArgumentNullException">
        /// Thrown when dpspResponse or httpMethod is null  
        /// </exception>
        /// <exception cref="ArgumentException">
        /// Thrown when httpMethod or digestType input is invalid
        /// </exception>        
        public static DIGEST_VALIDATION_REQ CreateDigestValidationRequestPacket(
            string serverName,
            string domainName,
            string accountName,
            string httpMethod,
            DigestType_Values digestType,
            string digestChallengeAlgorithm,
            DpspResponse dpspResponse)
        {
            if (dpspResponse == null)
            {
                throw new ArgumentNullException("dpspResponse");
            }

            if (httpMethod == null)
            {
                throw new ArgumentNullException("httpMethod");
            }

            DIGEST_VALIDATION_REQ_Payload payload = new DIGEST_VALIDATION_REQ_Payload();

            DIGEST_VALIDATION_REQ digestValidationReq = new DIGEST_VALIDATION_REQ();
            if (digestType == DigestType_Values.Basic)
            {
                EncodeCommonPartOfDigestValidationRequest(
                    serverName,
                    domainName,
                    accountName,
                    digestType,
                    digestChallengeAlgorithm,
                    dpspResponse,
                    ref payload,
                    ref digestValidationReq);

                payload.Algorithm = dpspResponse.GetAttributeValue(DpspUtility.ALGORITHM_DIRECTIVE);
                payload.URI = dpspResponse.GetAttributeValue(DpspUtility.BASIC_DIGEST_URI_DIRECTIVE);
                if (httpMethod.ToUpper().Equals(HTTP_GET) || httpMethod.ToLower().Equals(HTTP_PUT))
                {
                    payload.Method = httpMethod;
                }
                else
                {
                    throw new ArgumentException("invalid http method", "httpMethod");
                }
            }
            else if (digestType == DigestType_Values.SASL)
            {
                EncodeCommonPartOfDigestValidationRequest(
                   serverName,
                   domainName,
                   accountName,
                   digestType,
                   digestChallengeAlgorithm,
                   dpspResponse,
                   ref payload,
                   ref digestValidationReq);

                payload.Method = SASL_AUTHENTICATE;
                payload.URI = dpspResponse.GetAttributeValue(DpspUtility.SASL_DIGEST_URI_DIRECTIVE);
                payload.Authzid = dpspResponse.GetAttributeValue(DpspUtility.AUTHZID_DIRECTIVE);
                payload.Hentity = dpspResponse.GetAttributeValue(DpspUtility.HENTITY_DIRECTIVE);

            }
            else
            {
                throw new ArgumentException(
                    "invalid digestType value",
                    "digestType");
            }

            digestValidationReq.Payload = payload.GetBytes();
            digestValidationReq = UpdatePacketInfo(digestValidationReq);

            return digestValidationReq;
        }
        /// <summary>
        /// Decode
        /// </summary>
        /// <param name="digestCredentials">http digest credentials string</param>
        /// <param name="dpspResponse">dpspResponse instance</param>
        /// <exception cref="ArgumentNullException">
        /// Thrown when digestCredentials or digestCredentials is null 
        /// </exception>
        /// <exception cref="ArgumentException">
        /// Thrown when digestCredentials or dpspResponse is invalid 
        /// </exception>
        protected static void Decode(
            string digestCredentials,
            DpspResponse dpspResponse)
        {
            if (digestCredentials == null)
            {
                throw new ArgumentNullException("digestCredentials");
            }

            if (digestCredentials.Length == 0)
            {
                throw new ArgumentException(
                    "digestCredentials should not be empty",
                    "digestCredentials");
            }

            if (dpspResponse == null)
            {
                throw new ArgumentNullException("dpspResponse");
            }

            digestCredentials = digestCredentials.TrimStart();

            if (!digestCredentials.StartsWith(DpspUtility.DIGEST + DpspUtility.SPACE))
            {
                throw new ArgumentException(
                    "digestResponseCredentials should start with " + DpspUtility.DIGEST + "(SPACE)",
                    "digestCredentials");
            }

            // ABNF credentials = "Digest" digest-response
            string digestResponse = digestCredentials.Substring(DpspUtility.DIGEST.Length + DpspUtility.SPACE.Length);

            Regex regex = new Regex(
                DpspUtility.ATTRIBUTE_VALUE_PAIR_REGULAR_EXPRESSION_PATTERN,
                RegexOptions.IgnorePatternWhitespace);

            MatchCollection matchCollection = regex.Matches(digestResponse);

            if (matchCollection.Count == 0)
            {
                throw new ArgumentException("invalid digestResponse", "digestCredentials");
            }

            foreach (Match match in matchCollection)
            {
                string key;
                string value;

                if (match.Groups[DpspUtility.Attribute].Success)
                {
                    key = match.Groups[DpspUtility.Attribute].Value;
                }
                else
                {
                    throw new ArgumentException("invalid digestResponse", "digestCredentials");
                }

                if (match.Groups[DpspUtility.VALUE].Success)
                {
                    value = match.Groups[DpspUtility.VALUE].Value;
                }
                else
                {
                    throw new ArgumentException("invalid digestResponse", "digestCredentials");
                }

                dpspResponse.SetAttributeValue(key, value);
            }
        }