2
0

XmlRpcGenerator.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. /* This file is part of OpenSubtitles Handler
  2. A library that handle OpenSubtitles.org XML-RPC methods.
  3. Copyright © Ala Ibrahim Hadid 2013
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. using System;
  16. using System.Text;
  17. using System.Collections.Generic;
  18. using System.IO;
  19. using System.Xml;
  20. namespace XmlRpcHandler
  21. {
  22. /// <summary>
  23. /// A class for making XML-RPC requests. The requests then can be sent directly as http request.
  24. /// </summary>
  25. public class XmlRpcGenerator
  26. {
  27. /// <summary>
  28. /// Generate XML-RPC request using method call.
  29. /// </summary>
  30. /// <param name="method">The method call</param>
  31. /// <returns>The request in xml.</returns>
  32. public static byte[] Generate(XmlRpcMethodCall method)
  33. { return Generate(new XmlRpcMethodCall[] { method }); }
  34. /// <summary>
  35. /// Generate XML-RPC request using method calls array.
  36. /// </summary>
  37. /// <param name="methods">The method calls array</param>
  38. /// <returns>The request in utf8 xml string as buffer</returns>
  39. public static byte[] Generate(XmlRpcMethodCall[] methods)
  40. {
  41. if (methods == null)
  42. throw new Exception("No method to write !");
  43. if (methods.Length == 0)
  44. throw new Exception("No method to write !");
  45. // Create xml
  46. XmlWriterSettings sett = new XmlWriterSettings();
  47. sett.Indent = true;
  48. sett.Encoding = Encoding.UTF8;
  49. FileStream str = new FileStream(Path.GetTempPath() + "\\request.xml", FileMode.Create, FileAccess.Write);
  50. XmlWriter XMLwrt = XmlWriter.Create(str, sett);
  51. // Let's write the methods
  52. foreach (XmlRpcMethodCall method in methods)
  53. {
  54. XMLwrt.WriteStartElement("methodCall");//methodCall
  55. XMLwrt.WriteStartElement("methodName");//methodName
  56. XMLwrt.WriteString(method.Name);
  57. XMLwrt.WriteEndElement();//methodName
  58. XMLwrt.WriteStartElement("params");//params
  59. // Write values
  60. foreach (IXmlRpcValue p in method.Parameters)
  61. {
  62. XMLwrt.WriteStartElement("param");//param
  63. if (p is XmlRpcValueBasic)
  64. {
  65. WriteBasicValue(XMLwrt, (XmlRpcValueBasic)p);
  66. }
  67. else if (p is XmlRpcValueStruct)
  68. {
  69. WriteStructValue(XMLwrt, (XmlRpcValueStruct)p);
  70. }
  71. else if (p is XmlRpcValueArray)
  72. {
  73. WriteArrayValue(XMLwrt, (XmlRpcValueArray)p);
  74. }
  75. XMLwrt.WriteEndElement();//param
  76. }
  77. XMLwrt.WriteEndElement();//params
  78. XMLwrt.WriteEndElement();//methodCall
  79. }
  80. XMLwrt.Flush();
  81. XMLwrt.Close();
  82. str.Close();
  83. string requestContent = File.ReadAllText(Path.GetTempPath() + "\\request.xml");
  84. return Encoding.UTF8.GetBytes(requestContent);
  85. }
  86. /// <summary>
  87. /// Decode response then return the values
  88. /// </summary>
  89. /// <param name="xmlResponse">The response xml string as provided by server as methodResponse</param>
  90. /// <returns></returns>
  91. public static XmlRpcMethodCall[] DecodeMethodResponse(string xmlResponse)
  92. {
  93. List<XmlRpcMethodCall> methods = new List<XmlRpcMethodCall>();
  94. XmlReaderSettings sett = new XmlReaderSettings();
  95. sett.DtdProcessing = DtdProcessing.Ignore;
  96. sett.IgnoreWhitespace = true;
  97. MemoryStream str = new MemoryStream(Encoding.ASCII.GetBytes(xmlResponse));
  98. if (xmlResponse.Contains(@"encoding=""utf-8"""))
  99. {
  100. str = new MemoryStream(Encoding.UTF8.GetBytes(xmlResponse));
  101. }
  102. XmlReader XMLread = XmlReader.Create(str, sett);
  103. XmlRpcMethodCall call = new XmlRpcMethodCall("methodResponse");
  104. // Read parameters
  105. while (XMLread.Read())
  106. {
  107. if (XMLread.Name == "param" && XMLread.IsStartElement())
  108. {
  109. IXmlRpcValue val = ReadValue(XMLread);
  110. if (val != null)
  111. call.Parameters.Add(val);
  112. }
  113. }
  114. methods.Add(call);
  115. XMLread.Close();
  116. return methods.ToArray();
  117. }
  118. private static void WriteBasicValue(XmlWriter XMLwrt, XmlRpcValueBasic val)
  119. {
  120. XMLwrt.WriteStartElement("value");//value
  121. switch (val.ValueType)
  122. {
  123. case XmlRpcBasicValueType.String:
  124. XMLwrt.WriteStartElement("string");
  125. if (val.Data != null)
  126. XMLwrt.WriteString(val.Data.ToString());
  127. XMLwrt.WriteEndElement();
  128. break;
  129. case XmlRpcBasicValueType.Int:
  130. XMLwrt.WriteStartElement("int");
  131. if (val.Data != null)
  132. XMLwrt.WriteString(val.Data.ToString());
  133. XMLwrt.WriteEndElement();
  134. break;
  135. case XmlRpcBasicValueType.Boolean:
  136. XMLwrt.WriteStartElement("boolean");
  137. if (val.Data != null)
  138. XMLwrt.WriteString(((bool)val.Data) ? "1" : "0");
  139. XMLwrt.WriteEndElement();
  140. break;
  141. case XmlRpcBasicValueType.Double:
  142. XMLwrt.WriteStartElement("double");
  143. if (val.Data != null)
  144. XMLwrt.WriteString(val.Data.ToString());
  145. XMLwrt.WriteEndElement();
  146. break;
  147. case XmlRpcBasicValueType.dateTime_iso8601:
  148. XMLwrt.WriteStartElement("dateTime.iso8601");
  149. // Get date time format
  150. if (val.Data != null)
  151. {
  152. DateTime time = (DateTime)val.Data;
  153. string dt = time.Year + time.Month.ToString("D2") + time.Day.ToString("D2") +
  154. "T" + time.Hour.ToString("D2") + ":" + time.Minute.ToString("D2") + ":" +
  155. time.Second.ToString("D2");
  156. XMLwrt.WriteString(dt);
  157. }
  158. XMLwrt.WriteEndElement();
  159. break;
  160. case XmlRpcBasicValueType.base64:
  161. XMLwrt.WriteStartElement("base64");
  162. if (val.Data != null)
  163. XMLwrt.WriteString(Convert.ToBase64String(BitConverter.GetBytes((long)val.Data)));
  164. XMLwrt.WriteEndElement();
  165. break;
  166. }
  167. XMLwrt.WriteEndElement();//value
  168. }
  169. private static void WriteStructValue(XmlWriter XMLwrt, XmlRpcValueStruct val)
  170. {
  171. XMLwrt.WriteStartElement("value");//value
  172. XMLwrt.WriteStartElement("struct");//struct
  173. foreach (XmlRpcStructMember member in val.Members)
  174. {
  175. XMLwrt.WriteStartElement("member");//member
  176. XMLwrt.WriteStartElement("name");//name
  177. XMLwrt.WriteString(member.Name);
  178. XMLwrt.WriteEndElement();//name
  179. if (member.Data is XmlRpcValueBasic)
  180. {
  181. WriteBasicValue(XMLwrt, (XmlRpcValueBasic)member.Data);
  182. }
  183. else if (member.Data is XmlRpcValueStruct)
  184. {
  185. WriteStructValue(XMLwrt, (XmlRpcValueStruct)member.Data);
  186. }
  187. else if (member.Data is XmlRpcValueArray)
  188. {
  189. WriteArrayValue(XMLwrt, (XmlRpcValueArray)member.Data);
  190. }
  191. XMLwrt.WriteEndElement();//member
  192. }
  193. XMLwrt.WriteEndElement();//struct
  194. XMLwrt.WriteEndElement();//value
  195. }
  196. private static void WriteArrayValue(XmlWriter XMLwrt, XmlRpcValueArray val)
  197. {
  198. XMLwrt.WriteStartElement("value");//value
  199. XMLwrt.WriteStartElement("array");//array
  200. XMLwrt.WriteStartElement("data");//data
  201. foreach (IXmlRpcValue o in val.Values)
  202. {
  203. if (o is XmlRpcValueBasic)
  204. {
  205. WriteBasicValue(XMLwrt, (XmlRpcValueBasic)o);
  206. }
  207. else if (o is XmlRpcValueStruct)
  208. {
  209. WriteStructValue(XMLwrt, (XmlRpcValueStruct)o);
  210. }
  211. else if (o is XmlRpcValueArray)
  212. {
  213. WriteArrayValue(XMLwrt, (XmlRpcValueArray)o);
  214. }
  215. }
  216. XMLwrt.WriteEndElement();//data
  217. XMLwrt.WriteEndElement();//array
  218. XMLwrt.WriteEndElement();//value
  219. }
  220. private static IXmlRpcValue ReadValue(XmlReader xmlReader)
  221. {
  222. while (xmlReader.Read())
  223. {
  224. if (xmlReader.Name == "value" && xmlReader.IsStartElement())
  225. {
  226. xmlReader.Read();
  227. if (xmlReader.Name == "string" && xmlReader.IsStartElement())
  228. {
  229. return new XmlRpcValueBasic(xmlReader.ReadString(), XmlRpcBasicValueType.String);
  230. }
  231. else if (xmlReader.Name == "int" && xmlReader.IsStartElement())
  232. {
  233. return new XmlRpcValueBasic(int.Parse(xmlReader.ReadString()), XmlRpcBasicValueType.Int);
  234. }
  235. else if (xmlReader.Name == "boolean" && xmlReader.IsStartElement())
  236. {
  237. return new XmlRpcValueBasic(xmlReader.ReadString() == "1", XmlRpcBasicValueType.Boolean);
  238. }
  239. else if (xmlReader.Name == "double" && xmlReader.IsStartElement())
  240. {
  241. return new XmlRpcValueBasic(double.Parse(xmlReader.ReadString()), XmlRpcBasicValueType.Double);
  242. }
  243. else if (xmlReader.Name == "dateTime.iso8601" && xmlReader.IsStartElement())
  244. {
  245. string date = xmlReader.ReadString();
  246. int year = int.Parse(date.Substring(0, 4));
  247. int month = int.Parse(date.Substring(4, 2));
  248. int day = int.Parse(date.Substring(6, 2));
  249. int hour = int.Parse(date.Substring(9, 2));
  250. int minute = int.Parse(date.Substring(12, 2));//19980717T14:08:55
  251. int sec = int.Parse(date.Substring(15, 2));
  252. DateTime time = new DateTime(year, month, day, hour, minute, sec);
  253. return new XmlRpcValueBasic(time, XmlRpcBasicValueType.dateTime_iso8601);
  254. }
  255. else if (xmlReader.Name == "base64" && xmlReader.IsStartElement())
  256. {
  257. return new XmlRpcValueBasic(BitConverter.ToInt64(Convert.FromBase64String(xmlReader.ReadString()), 0)
  258. , XmlRpcBasicValueType.Double);
  259. }
  260. else if (xmlReader.Name == "struct" && xmlReader.IsStartElement())
  261. {
  262. XmlRpcValueStruct strct = new XmlRpcValueStruct(new List<XmlRpcStructMember>());
  263. // Read members...
  264. while (xmlReader.Read())
  265. {
  266. if (xmlReader.Name == "member" && xmlReader.IsStartElement())
  267. {
  268. XmlRpcStructMember member = new XmlRpcStructMember("", null);
  269. xmlReader.Read();// read name
  270. member.Name = xmlReader.ReadString();
  271. IXmlRpcValue val = ReadValue(xmlReader);
  272. if (val != null)
  273. {
  274. member.Data = val;
  275. strct.Members.Add(member);
  276. }
  277. }
  278. else if (xmlReader.Name == "struct" && !xmlReader.IsStartElement())
  279. {
  280. return strct;
  281. }
  282. }
  283. return strct;
  284. }
  285. else if (xmlReader.Name == "array" && xmlReader.IsStartElement())
  286. {
  287. XmlRpcValueArray array = new XmlRpcValueArray();
  288. // Read members...
  289. while (xmlReader.Read())
  290. {
  291. if (xmlReader.Name == "array" && !xmlReader.IsStartElement())
  292. {
  293. return array;
  294. }
  295. else
  296. {
  297. IXmlRpcValue val = ReadValue(xmlReader);
  298. if (val != null)
  299. array.Values.Add(val);
  300. }
  301. }
  302. return array;
  303. }
  304. }
  305. else break;
  306. }
  307. return null;
  308. }
  309. }
  310. }