XmlRpcDeserializer.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. namespace Nwc.XmlRpc
  2. {
  3. using System;
  4. using System.Collections;
  5. using System.IO;
  6. using System.Xml;
  7. using System.Globalization;
  8. /// <summary>Parser context, we maintain contexts in a stack to avoiding recursion. </summary>
  9. struct Context
  10. {
  11. public String Name;
  12. public Object Container;
  13. }
  14. /// <summary>Basic XML-RPC data deserializer.</summary>
  15. /// <remarks>Uses <c>XmlTextReader</c> to parse the XML data. This level of the class
  16. /// only handles the tokens common to both Requests and Responses. This class is not useful in and of itself
  17. /// but is designed to be subclassed.</remarks>
  18. public class XmlRpcDeserializer : XmlRpcXmlTokens
  19. {
  20. private static DateTimeFormatInfo _dateFormat = new DateTimeFormatInfo();
  21. private Object _container;
  22. private Stack _containerStack;
  23. /// <summary>Protected reference to last text.</summary>
  24. protected String _text;
  25. /// <summary>Protected reference to last deserialized value.</summary>
  26. protected Object _value;
  27. /// <summary>Protected reference to last name field.</summary>
  28. protected String _name;
  29. /// <summary>Basic constructor.</summary>
  30. public XmlRpcDeserializer()
  31. {
  32. Reset();
  33. _dateFormat.FullDateTimePattern = ISO_DATETIME;
  34. }
  35. /// <summary>Static method that parses XML data into a response using the Singleton.</summary>
  36. /// <param name="xmlData"><c>StreamReader</c> containing an XML-RPC response.</param>
  37. /// <returns><c>Object</c> object resulting from the deserialization.</returns>
  38. virtual public Object Deserialize(TextReader xmlData)
  39. {
  40. return null;
  41. }
  42. /// <summary>Protected method to parse a node in an XML-RPC XML stream.</summary>
  43. /// <remarks>Method deals with elements common to all XML-RPC data, subclasses of
  44. /// this object deal with request/response spefic elements.</remarks>
  45. /// <param name="reader"><c>XmlTextReader</c> of the in progress parsing data stream.</param>
  46. protected void DeserializeNode(XmlTextReader reader)
  47. {
  48. switch (reader.NodeType)
  49. {
  50. case XmlNodeType.Element:
  51. if (Logger.Delegate != null)
  52. Logger.WriteEntry("START " + reader.Name, LogLevel.Information);
  53. switch (reader.Name)
  54. {
  55. case VALUE:
  56. _value = null;
  57. _text = null;
  58. break;
  59. case STRUCT:
  60. PushContext();
  61. _container = new Hashtable();
  62. break;
  63. case ARRAY:
  64. PushContext();
  65. _container = new ArrayList();
  66. break;
  67. }
  68. break;
  69. case XmlNodeType.EndElement:
  70. if (Logger.Delegate != null)
  71. Logger.WriteEntry("END " + reader.Name, LogLevel.Information);
  72. switch (reader.Name)
  73. {
  74. case BASE64:
  75. _value = Convert.FromBase64String(_text);
  76. break;
  77. case BOOLEAN:
  78. int val = Int16.Parse(_text);
  79. if (val == 0)
  80. _value = false;
  81. else if (val == 1)
  82. _value = true;
  83. break;
  84. case STRING:
  85. _value = _text;
  86. break;
  87. case DOUBLE:
  88. _value = Double.Parse(_text);
  89. break;
  90. case INT:
  91. case ALT_INT:
  92. _value = Int32.Parse(_text);
  93. break;
  94. case DATETIME:
  95. #if __MONO__
  96. _value = DateParse(_text);
  97. #else
  98. _value = DateTime.ParseExact(_text, "F", _dateFormat);
  99. #endif
  100. break;
  101. case NAME:
  102. _name = _text;
  103. break;
  104. case VALUE:
  105. if (_value == null)
  106. _value = _text; // some kits don't use <string> tag, they just do <value>
  107. if ((_container != null) && (_container is IList)) // in an array? If so add value to it.
  108. ((IList)_container).Add(_value);
  109. break;
  110. case MEMBER:
  111. if ((_container != null) && (_container is IDictionary)) // in an struct? If so add value to it.
  112. ((IDictionary)_container).Add(_name, _value);
  113. break;
  114. case ARRAY:
  115. case STRUCT:
  116. _value = _container;
  117. PopContext();
  118. break;
  119. }
  120. break;
  121. case XmlNodeType.Text:
  122. if (Logger.Delegate != null)
  123. Logger.WriteEntry("Text " + reader.Value, LogLevel.Information);
  124. _text = reader.Value;
  125. break;
  126. default:
  127. break;
  128. }
  129. }
  130. /// <summary>Static method that parses XML in a <c>String</c> into a
  131. /// request using the Singleton.</summary>
  132. /// <param name="xmlData"><c>String</c> containing an XML-RPC request.</param>
  133. /// <returns><c>XmlRpcRequest</c> object resulting from the parse.</returns>
  134. public Object Deserialize(String xmlData)
  135. {
  136. StringReader sr = new StringReader(xmlData);
  137. return Deserialize(sr);
  138. }
  139. /// <summary>Pop a Context of the stack, an Array or Struct has closed.</summary>
  140. private void PopContext()
  141. {
  142. Context c = (Context)_containerStack.Pop();
  143. _container = c.Container;
  144. _name = c.Name;
  145. }
  146. /// <summary>Push a Context on the stack, an Array or Struct has opened.</summary>
  147. private void PushContext()
  148. {
  149. Context context;
  150. context.Container = _container;
  151. context.Name = _name;
  152. _containerStack.Push(context);
  153. }
  154. /// <summary>Reset the internal state of the deserializer.</summary>
  155. protected void Reset()
  156. {
  157. _text = null;
  158. _value = null;
  159. _name = null;
  160. _container = null;
  161. _containerStack = new Stack();
  162. }
  163. #if __MONO__
  164. private DateTime DateParse(String str)
  165. {
  166. int year = Int32.Parse(str.Substring(0,4));
  167. int month = Int32.Parse(str.Substring(4,2));
  168. int day = Int32.Parse(str.Substring(6,2));
  169. int hour = Int32.Parse(str.Substring(9,2));
  170. int min = Int32.Parse(str.Substring(12,2));
  171. int sec = Int32.Parse(str.Substring(15,2));
  172. return new DateTime(year,month,day,hour,min,sec);
  173. }
  174. #endif
  175. }
  176. }