kopano-ol-extension/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/Connect/Soap/SoapRequestEncoder.cs

137 lines
4.3 KiB
C#

/// Copyright 2016 Kopano b.v.
///
/// This program is free software: you can redistribute it and/or modify
/// it under the terms of the GNU Affero General Public License, version 3,
/// as published by the Free Software Foundation.
///
/// This program is distributed in the hope that it will be useful,
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
/// GNU Affero General Public License for more details.
///
/// You should have received a copy of the GNU Affero General Public License
/// along with this program.If not, see<http://www.gnu.org/licenses/>.
///
/// Consult LICENSE file for details
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
namespace Acacia.ZPush.Connect.Soap
{
public class SoapRequestEncoder : RequestEncoder
{
private readonly string _xmlns;
private readonly SoapRequestBase _request;
private readonly SoapParameters _parameters;
public SoapRequestEncoder(string xmlns, SoapParameters serviceParameters, SoapRequestBase request)
{
this._xmlns = xmlns;
this._request = request;
if (serviceParameters != null)
{
_parameters = new SoapParameters(serviceParameters, request.Parameters);
}
else
{
_parameters = request.Parameters;
}
}
public string ServiceName { get; set; }
public override string RequestName
{
get
{
return _request.RequestName;
}
}
#region Encoding
private const string PREFIX = @"<?xml version=""1.0"" encoding=""utf-8""?>
<soap:Envelope xmlns:xsi=""" + SoapConstants.XMLNS_XSI + @"""
xmlns:xsd=""" + SoapConstants.XMLNS_XSD + @"""
xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/""
xmlns:soap-enc=""" + SoapConstants.XMLNS_SOAP_ENC + @"""
xmlns:ns2=""" + SoapConstants.XMLNS_APACHE + @"""
xmlns=""{1}""
>
<soap:Body>
<{0}>
";
private const string SUFFIX = @"
</{0}>
</soap:Body>
</soap:Envelope>";
public override HttpContent GetContent()
{
StringBuilder s = new StringBuilder();
s.Append(string.Format(PREFIX, _request.RequestName, _xmlns));
_parameters.Serialize(s);
s.Append(string.Format(SUFFIX, _request.RequestName));
ByteArrayContent content = new ByteArrayContent(Encoding.UTF8.GetBytes(s.ToString()));
content.Headers.ContentType = new MediaTypeHeaderValue("text/xml");
return content;
}
#endregion
#region Decoding
public override object ParseResponse(string url, Stream result)
{
// Parse xml
XmlDocument xml = new XmlDocument();
using (StreamReader reader = new StreamReader(result))
{
string text = reader.ReadToEnd();
try
{
xml.LoadXml(text);
}
catch (Exception e)
{
Logger.Instance.Error(this, "Error in SOAP response:\nurl={0}\nresponse={1}", url, text);
throw e;
}
}
// Check if it's an error message
CheckFaultResponse(xml);
// Select the respone data
// TODO: do this with proper xmlns
XmlNode part = xml.SelectSingleNode("//*[local-name()='" + _request.RequestName + "Response']/return");
// Let the request handle it
return _request.ParseResponse(part);
}
private void CheckFaultResponse(XmlNode response)
{
XmlNode fault = response?.SelectSingleNode("//*[local-name()='Fault']");
if (response == null || fault != null)
{
string message = fault?.SelectSingleNode("faultstring")?.InnerText;
throw new SoapException(message);
}
}
#endregion
}
}