123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350 |
- /* This file is part of OpenSubtitles Handler
- A library that handle OpenSubtitles.org XML-RPC methods.
- Copyright © Ala Ibrahim Hadid 2013
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- 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 General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- using System;
- using System.Collections.Generic;
- using System.Globalization;
- using System.IO;
- using System.Text;
- using System.Xml;
- using OpenSubtitlesHandler;
- namespace XmlRpcHandler
- {
- /// <summary>
- /// A class for making XML-RPC requests. The requests then can be sent directly as http request.
- /// </summary>
- public class XmlRpcGenerator
- {
- /// <summary>
- /// Generate XML-RPC request using method call.
- /// </summary>
- /// <param name="method">The method call</param>
- /// <returns>The request in xml.</returns>
- public static byte[] Generate(XmlRpcMethodCall method)
- { return Generate(new XmlRpcMethodCall[] { method }); }
- /// <summary>
- /// Generate XML-RPC request using method calls array.
- /// </summary>
- /// <param name="methods">The method calls array</param>
- /// <returns>The request in utf8 xml string as buffer</returns>
- public static byte[] Generate(XmlRpcMethodCall[] methods)
- {
- if (methods == null)
- throw new Exception("No method to write !");
- if (methods.Length == 0)
- throw new Exception("No method to write !");
- // Create xml
- var sett = new XmlWriterSettings();
- sett.Indent = true;
- sett.Encoding = Encoding.UTF8;
- using (var ms = new MemoryStream())
- {
- using (var XMLwrt = XmlWriter.Create(ms, sett))
- {
- // Let's write the methods
- foreach (XmlRpcMethodCall method in methods)
- {
- XMLwrt.WriteStartElement("methodCall");//methodCall
- XMLwrt.WriteStartElement("methodName");//methodName
- XMLwrt.WriteString(method.Name);
- XMLwrt.WriteEndElement();//methodName
- XMLwrt.WriteStartElement("params");//params
- // Write values
- foreach (IXmlRpcValue p in method.Parameters)
- {
- XMLwrt.WriteStartElement("param");//param
- if (p is XmlRpcValueBasic)
- {
- WriteBasicValue(XMLwrt, (XmlRpcValueBasic)p);
- }
- else if (p is XmlRpcValueStruct)
- {
- WriteStructValue(XMLwrt, (XmlRpcValueStruct)p);
- }
- else if (p is XmlRpcValueArray)
- {
- WriteArrayValue(XMLwrt, (XmlRpcValueArray)p);
- }
- XMLwrt.WriteEndElement();//param
- }
- XMLwrt.WriteEndElement();//params
- XMLwrt.WriteEndElement();//methodCall
- }
- XMLwrt.Flush();
- return ms.ToArray();
- }
- }
- }
- /// <summary>
- /// Decode response then return the values
- /// </summary>
- /// <param name="xmlResponse">The response xml string as provided by server as methodResponse</param>
- /// <returns></returns>
- public static XmlRpcMethodCall[] DecodeMethodResponse(string xmlResponse)
- {
- var methods = new List<XmlRpcMethodCall>();
- var sett = new XmlReaderSettings();
- sett.DtdProcessing = DtdProcessing.Ignore;
- sett.IgnoreWhitespace = true;
- MemoryStream str;
- if (xmlResponse.Contains(@"encoding=""utf-8"""))
- {
- str = new MemoryStream(Encoding.UTF8.GetBytes(xmlResponse));
- }
- else
- {
- str = new MemoryStream(Utilities.GetASCIIBytes(xmlResponse));
- }
- using (str)
- {
- using (var XMLread = XmlReader.Create(str, sett))
- {
- var call = new XmlRpcMethodCall("methodResponse");
- // Read parameters
- while (XMLread.Read())
- {
- if (XMLread.Name == "param" && XMLread.IsStartElement())
- {
- IXmlRpcValue val = ReadValue(XMLread);
- if (val != null)
- call.Parameters.Add(val);
- }
- }
- methods.Add(call);
- return methods.ToArray();
- }
- }
- }
- private static void WriteBasicValue(XmlWriter XMLwrt, XmlRpcValueBasic val)
- {
- XMLwrt.WriteStartElement("value");//value
- switch (val.ValueType)
- {
- case XmlRpcBasicValueType.String:
- XMLwrt.WriteStartElement("string");
- if (val.Data != null)
- XMLwrt.WriteString(val.Data.ToString());
- XMLwrt.WriteEndElement();
- break;
- case XmlRpcBasicValueType.Int:
- XMLwrt.WriteStartElement("int");
- if (val.Data != null)
- XMLwrt.WriteString(val.Data.ToString());
- XMLwrt.WriteEndElement();
- break;
- case XmlRpcBasicValueType.Boolean:
- XMLwrt.WriteStartElement("boolean");
- if (val.Data != null)
- XMLwrt.WriteString(((bool)val.Data) ? "1" : "0");
- XMLwrt.WriteEndElement();
- break;
- case XmlRpcBasicValueType.Double:
- XMLwrt.WriteStartElement("double");
- if (val.Data != null)
- XMLwrt.WriteString(val.Data.ToString());
- XMLwrt.WriteEndElement();
- break;
- case XmlRpcBasicValueType.dateTime_iso8601:
- XMLwrt.WriteStartElement("dateTime.iso8601");
- // Get date time format
- if (val.Data != null)
- {
- var time = (DateTime)val.Data;
- string dt = time.Year + time.Month.ToString("D2") + time.Day.ToString("D2") +
- "T" + time.Hour.ToString("D2") + ":" + time.Minute.ToString("D2") + ":" +
- time.Second.ToString("D2");
- XMLwrt.WriteString(dt);
- }
- XMLwrt.WriteEndElement();
- break;
- case XmlRpcBasicValueType.base64:
- XMLwrt.WriteStartElement("base64");
- if (val.Data != null)
- XMLwrt.WriteString(Convert.ToBase64String(BitConverter.GetBytes((long)val.Data)));
- XMLwrt.WriteEndElement();
- break;
- }
- XMLwrt.WriteEndElement();//value
- }
- private static void WriteStructValue(XmlWriter XMLwrt, XmlRpcValueStruct val)
- {
- XMLwrt.WriteStartElement("value");//value
- XMLwrt.WriteStartElement("struct");//struct
- foreach (XmlRpcStructMember member in val.Members)
- {
- XMLwrt.WriteStartElement("member");//member
- XMLwrt.WriteStartElement("name");//name
- XMLwrt.WriteString(member.Name);
- XMLwrt.WriteEndElement();//name
- if (member.Data is XmlRpcValueBasic)
- {
- WriteBasicValue(XMLwrt, (XmlRpcValueBasic)member.Data);
- }
- else if (member.Data is XmlRpcValueStruct)
- {
- WriteStructValue(XMLwrt, (XmlRpcValueStruct)member.Data);
- }
- else if (member.Data is XmlRpcValueArray)
- {
- WriteArrayValue(XMLwrt, (XmlRpcValueArray)member.Data);
- }
- XMLwrt.WriteEndElement();//member
- }
- XMLwrt.WriteEndElement();//struct
- XMLwrt.WriteEndElement();//value
- }
- private static void WriteArrayValue(XmlWriter XMLwrt, XmlRpcValueArray val)
- {
- XMLwrt.WriteStartElement("value");//value
- XMLwrt.WriteStartElement("array");//array
- XMLwrt.WriteStartElement("data");//data
- foreach (IXmlRpcValue o in val.Values)
- {
- if (o is XmlRpcValueBasic)
- {
- WriteBasicValue(XMLwrt, (XmlRpcValueBasic)o);
- }
- else if (o is XmlRpcValueStruct)
- {
- WriteStructValue(XMLwrt, (XmlRpcValueStruct)o);
- }
- else if (o is XmlRpcValueArray)
- {
- WriteArrayValue(XMLwrt, (XmlRpcValueArray)o);
- }
- }
- XMLwrt.WriteEndElement();//data
- XMLwrt.WriteEndElement();//array
- XMLwrt.WriteEndElement();//value
- }
- private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
- private static string ReadString(XmlReader reader)
- {
- if (reader.NodeType == XmlNodeType.Element)
- {
- return reader.ReadElementContentAsString();
- }
- return reader.ReadContentAsString();
- }
- private static IXmlRpcValue ReadValue(XmlReader xmlReader, bool skipRead = false)
- {
- while (skipRead || xmlReader.Read())
- {
- if (xmlReader.Name == "value" && xmlReader.IsStartElement())
- {
- xmlReader.Read();
- if (xmlReader.Name == "string" && xmlReader.IsStartElement())
- {
- return new XmlRpcValueBasic(ReadString(xmlReader), XmlRpcBasicValueType.String);
- }
- else if (xmlReader.Name == "int" && xmlReader.IsStartElement())
- {
- return new XmlRpcValueBasic(int.Parse(ReadString(xmlReader), UsCulture), XmlRpcBasicValueType.Int);
- }
- else if (xmlReader.Name == "boolean" && xmlReader.IsStartElement())
- {
- return new XmlRpcValueBasic(ReadString(xmlReader) == "1", XmlRpcBasicValueType.Boolean);
- }
- else if (xmlReader.Name == "double" && xmlReader.IsStartElement())
- {
- return new XmlRpcValueBasic(double.Parse(ReadString(xmlReader), UsCulture), XmlRpcBasicValueType.Double);
- }
- else if (xmlReader.Name == "dateTime.iso8601" && xmlReader.IsStartElement())
- {
- string date = ReadString(xmlReader);
- int year = int.Parse(date.Substring(0, 4), UsCulture);
- int month = int.Parse(date.Substring(4, 2), UsCulture);
- int day = int.Parse(date.Substring(6, 2), UsCulture);
- int hour = int.Parse(date.Substring(9, 2), UsCulture);
- int minute = int.Parse(date.Substring(12, 2), UsCulture);//19980717T14:08:55
- int sec = int.Parse(date.Substring(15, 2), UsCulture);
- var time = new DateTime(year, month, day, hour, minute, sec);
- return new XmlRpcValueBasic(time, XmlRpcBasicValueType.dateTime_iso8601);
- }
- else if (xmlReader.Name == "base64" && xmlReader.IsStartElement())
- {
- return new XmlRpcValueBasic(BitConverter.ToInt64(Convert.FromBase64String(ReadString(xmlReader)), 0)
- , XmlRpcBasicValueType.Double);
- }
- else if (xmlReader.Name == "struct" && xmlReader.IsStartElement())
- {
- var strct = new XmlRpcValueStruct(new List<XmlRpcStructMember>());
- // Read members...
- while (xmlReader.Read())
- {
- if (xmlReader.Name == "member" && xmlReader.IsStartElement())
- {
- var member = new XmlRpcStructMember("", null);
- xmlReader.Read();// read name
- member.Name = ReadString(xmlReader);
- IXmlRpcValue val = ReadValue(xmlReader, true);
- if (val != null)
- {
- member.Data = val;
- strct.Members.Add(member);
- }
- }
- else if (xmlReader.Name == "struct" && !xmlReader.IsStartElement())
- {
- return strct;
- }
- }
- return strct;
- }
- else if (xmlReader.Name == "array" && xmlReader.IsStartElement())
- {
- var array = new XmlRpcValueArray();
- // Read members...
- while (xmlReader.Read())
- {
- if (xmlReader.Name == "array" && !xmlReader.IsStartElement())
- {
- return array;
- }
- else
- {
- IXmlRpcValue val = ReadValue(xmlReader);
- if (val != null)
- array.Values.Add(val);
- }
- }
- return array;
- }
- }
- else break;
- if (skipRead)
- {
- return null;
- }
- }
- return null;
- }
- }
- }
|