InvokeMessage.cs

Contains the functions for sending SOAP messages. Including the logic for signing, encrypting, and constructing the messages. Uses the RequestClient class to send the SOAP-envelopes to the correct endpoint.

// ------------------------------------------------------------------------------------------
// <copyright file="InvokeMessage.cs" company="Pointsharp AB">
//   Pointsharp AB
// </copyright>
// <summary>
//   Defines the Client partial class.
// </summary>
// ------------------------------------------------------------------------------------------

namespace SecMaker.NiP.Client
{
    using System;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Xml;

    public partial class Client
    {
        /// <summary>
        /// Invokes the SOAP message request.
        /// </summary>
        /// <returns>
        /// Returns the SOAP message response as System.String.
        /// </returns>
        public string InvokeMessage(bool verbose)
        {
            var sContractName =
                Utility.GetNodeName(_sMessage);

            var useEncryption =
                UseEncryption(sContractName);

            if (useEncryption)
            {
                EncryptMessage();
            }

            RequestClient.Url = _sUrl;
            RequestClient.DataToSend = _sMessage;
            RequestClient.Method = RequestClient.HttpVerbEnum.POST;
            RequestClient.ActionName = sContractName;
            RequestClient.ContentType = "text/xml; charset=\"utf-8\"";

            _sMessage =
                RequestClient.InvokeClient();

            if (useEncryption)
            {
                DecryptMessage();
            }
            if (verbose)
            {
                Console.WriteLine(_sMessage);
            }
            return _sMessage;
        }

        /// <summary>
        /// Returns condition of using encryption.
        /// GetVersion, Login and GetObject:ApplicationInfo are exceptions for encryption because the user not has beed logged on yet.
        /// </summary>
        /// <param name="contractName">
        /// Contract name of the call as System.String.
        /// </param>
        /// <returns>
        /// Returns condition as System.Boolean.
        /// </returns>
        private bool UseEncryption(string contractName)
        {
            if (_encryptionDisabled)
            {
                return false;
            }
            else return
              (contractName != "GetVersion") &&
              (contractName != "Login") &&
              (contractName != "Logout") &&
              (!_sMessage.ToUpper().Contains("APPLICATIONINFO"));
        }

        /// <summary>
        /// Encrypts the Info element of the requests and inserts the blob, instead of Info, Info into the message.
        /// </summary>
        private void EncryptMessage()
        {
            var sInfo = Utility.GetInfoTest(_sMessage);

            if (!string.IsNullOrEmpty(sInfo))
            {
                Derive();
                var data = Utility.ToBytes(Utility.FormatInfoBlob(sInfo, _sBlobFormat));

                data = Utility.Compress(data, _sCompressionMode);

                data = Utility.AesEncryption(data, _key, _iv);

                var sb = new StringBuilder();

                sb.Append("<Info>");
                sb.Append("<SessionId>");
                sb.Append(_sSessionId);
                sb.Append("</SessionId>");
                sb.Append("<Blob>");
                sb.Append(Utility.ToBase64String(data));
                sb.Append("</Blob>");
                sb.Append("<Count>");
                sb.Append(_counter);
                sb.Append("</Count>");
                sb.Append("</Info>");
                RegexOptions options = RegexOptions.Singleline;
                Regex regex = new Regex("<Info>.*</Info>", options);

                _sMessage = regex.Replace(_sMessage, sb.ToString());
            }
        }


        /// <summary>
        /// Decrypts the Blob element of the reponse and inserts the Info element, instead of Blob, into the message.
        /// </summary>
        private void DecryptMessage()
        {
            if ((_key == null) || (_iv == null))
            {
                Derive();
            }
            //If the message is not a success we have nothing to decrypt
            if (!_sMessage.Contains("NPR_SUCCESS"))
            {
                return;
            }
            var sBlob =
                Utility.ParseXmlElem(_sMessage, "<Blob>");

            var data =
                Convert.FromBase64String(sBlob);

            data =
                Utility.AesDecryption(data, _key, _iv);

            data =
                Utility.Decompress(data, _sCompressionMode);

            _sMessage =
                _sMessage.Replace("<Blob>", string.Empty);

            _sMessage =
                _sMessage.Replace("</Blob>", string.Empty);
            _sMessage =
                _sMessage.Replace(sBlob, Utility.ReformatInfoBlob(
                    Utility.ToString(data)
                    , _sBlobFormat));
        }
    }
}