public object ParseBase64(XmlNode node, Type valueType, ParseStack parseStack) { if (valueType.IsNoByteArray()) { throw new XmlRpcTypeMismatchException(parseStack.ParseType + " contains base64 value where " + XmlRpcServiceInfo.GetXmlRpcTypeString(valueType) + " expected " + parseStack.Dump()); } parseStack.Push("base64"); try { if (node.FirstChild == null) { return(new byte[0]); } var base64String = node.FirstChild.Value; var buffer = new Span <byte>(); if (!Convert.TryFromBase64String(base64String, buffer, out _)) { throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains invalid base64 value " + parseStack.Dump()); } return(buffer.ToArray()); } finally { parseStack.Pop(); } }
public object ParseLong(XmlNode node, Type valueType, ParseStack parseStack) { if (valueType.IsNoLong()) { throw new XmlRpcTypeMismatchException(parseStack.ParseType + " contains i8 value where " + XmlRpcServiceInfo.GetXmlRpcTypeString(valueType) + " expected " + parseStack.Dump()); } parseStack.Push("i8"); try { var valueNode = node.FirstChild; if (valueNode == null) { throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains invalid i8 element " + parseStack.Dump()); } var strValue = valueNode.Value; if (!long.TryParse(strValue, out var parseResult)) { throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains invalid i8 value " + parseStack.Dump()); } return(parseResult); } finally { parseStack.Pop(); } }
void ReportMissingMembers(Type valueType, Hashtable names, ParseStack parseStack) { var sb = new StringBuilder(); var errorCount = 0; var sep = string.Empty; foreach (string key in names.Keys) { var memberAction = AttributeHelper.MemberMappingAction(valueType, key, MappingAction.Error); if (memberAction == MappingAction.Error) { sb.Append(sep); sb.Append(key); sep = " "; errorCount++; } } if (errorCount == 0) { return; } var plural = string.Empty; if (errorCount > 1) { plural = "s"; } throw new XmlRpcTypeMismatchException(parseStack.ParseType + " contains class value with missing non-optional member" + plural + ": " + sb.ToString() + " " + parseStack.Dump()); }
public object ParseBoolean(XmlNode node, Type valueType, ParseStack parseStack) { if (valueType.IsNoBoolean()) { throw new XmlRpcTypeMismatchException(parseStack.ParseType + " contains boolean value where " + XmlRpcServiceInfo.GetXmlRpcTypeString(valueType) + " expected " + parseStack.Dump()); } parseStack.Push("boolean"); try { var textbool = node.FirstChild.Value; if (!bool.TryParse(textbool, out var parseResult)) { if (!textbool.Equals("0") && !textbool.Equals("1")) { throw new XmlRpcInvalidXmlRpcException($"reponse contains invalid boolean value '{textbool}' " + parseStack.Dump()); } parseResult = textbool.Equals("1"); } return(valueType == typeof(XmlRpcBoolean) ? new XmlRpcBoolean(parseResult) : (object)parseResult); } finally { parseStack.Pop(); } }
public XmlRpcRequest DeserializeRequest(Stream inputStream, Type serviceType) { _parseStack = new ParseStack("request"); var xdoc = XmlDocumentLoader.LoadXmlDocument(inputStream); return(DeserializeRequest(xdoc, serviceType)); }
public object ParseString(XmlNode node, Type valueType, ParseStack parseStack) { if (valueType.IsNoString()) { throw new XmlRpcTypeMismatchException(parseStack.ParseType + " contains string value where " + XmlRpcServiceInfo.GetXmlRpcTypeString(valueType) + " expected " + parseStack.Dump()); } parseStack.Push("string"); try { return(node.FirstChild == null ? string.Empty : node.FirstChild.Value); } finally { parseStack.Pop(); } }
public object ParseDateTime(XmlNode node, Type valueType, ParseStack parseStack) { if (valueType.IsNoDateTime()) { throw new XmlRpcTypeMismatchException(parseStack.ParseType + " contains dateTime.iso8601 value where " + XmlRpcServiceInfo.GetXmlRpcTypeString(valueType) + " expected " + parseStack.Dump()); } parseStack.Push("dateTime"); try { var child = node.FirstChild; if (child == null) { if (_config.MapEmptyDateTimeToMinValue()) { return(DateTime.MinValue); } else { throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains empty dateTime value " + parseStack.Dump()); } } var datestring = child.Value; if (!DateTime8601.TryParseDateTime8601(datestring, out var retVal)) { if (_config.MapZerosDateTimeToMinValue() && datestring.StartsWith("0000") && (datestring == "00000000T00:00:00" || datestring == "0000-00-00T00:00:00Z" || datestring == "00000000T00:00:00Z" || datestring == "0000-00-00T00:00:00")) { retVal = DateTime.MinValue; } else { throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains invalid dateTime value " + parseStack.Dump()); } } return(valueType == typeof(XmlRpcDateTime) ? new XmlRpcDateTime(retVal) : (object)retVal); } finally { parseStack.Pop(); } }
object ParseMultiDimArray(XmlNode node, Type ValueType, ParseStack parseStack) { // parse the type name to get element type and array rank Type elemType = ValueType.GetElementType(); int rank = ValueType.GetArrayRank(); // elements will be stored sequentially as nested arrays are parsed ArrayList elements = new ArrayList(); // create array to store length of each dimension - initialize to // all zeroes so that when parsing we can determine if an array for // that dimension has been parsed already int[] dimLengths = new int[rank]; dimLengths.Initialize(); ParseMultiDimElements(node, rank, 0, elemType, elements, dimLengths, parseStack); // build arguments to define array dimensions and create the array object[] args = new object[dimLengths.Length]; for (int argi = 0; argi < dimLengths.Length; argi++) { args[argi] = dimLengths[argi]; } Array ret = (Array)Activator.CreateInstance(ValueType, args); // copy elements into new multi-dim array //!! make more efficient int length = ret.Length; for (int e = 0; e < length; e++) { int[] indices = new int[dimLengths.Length]; int div = 1; for (int f = (indices.Length - 1); f >= 0; f--) { indices[f] = (e / div) % dimLengths[f]; div *= dimLengths[f]; } ret.SetValue(elements[e], indices); } return(ret); }
public object ParseDouble(XmlNode node, Type ValueType, ParseStack parseStack) { if (ValueType.IsNoDouble()) { throw new XmlRpcTypeMismatchException(parseStack.ParseType + " contains double value where " + XmlRpcServiceInfo.GetXmlRpcTypeString(ValueType) + " expected " + parseStack.Dump()); } parseStack.Push("double"); try { if (!double.TryParse(node.FirstChild.Value, out var parseResult)) { throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains invalid double value " + parseStack.Dump()); } return(ValueType == typeof(XmlRpcDouble) ? new XmlRpcDouble(parseResult) : (object)parseResult); } finally { parseStack.Pop(); } }
public XmlRpcFaultException ParseFault(XmlNode faultNode, ParseStack parseStack) { var valueNode = faultNode.SelectSingleNode("value"); var structNode = valueNode.SelectSingleNode("struct"); if (structNode == null) { throw new XmlRpcInvalidXmlRpcException("class element missing from fault response."); } var fault = new XmlFault(); try { fault = (XmlFault)ParseValue(structNode, typeof(XmlFault), parseStack); } catch (Exception ex) { // some servers incorrectly return fault code in a string if (!_config.AllowStringFaultCode()) { throw; } try { var faultStrCode = (FaultStructStringCode)ParseValue(structNode, typeof(FaultStructStringCode), parseStack); fault.faultCode = Convert.ToInt32(faultStrCode.faultCode); fault.faultString = faultStrCode.faultString; } catch (Exception) { // use exception from when attempting to parse code as integer throw ex; } } return(new XmlRpcFaultException(fault.faultCode, fault.faultString)); }
void ParseMultiDimElements(XmlNode node, int Rank, int CurRank, Type elemType, ArrayList elements, int[] dimLengths, ParseStack parseStack) { if (node.Name != "array") { throw new XmlRpcTypeMismatchException( "param element does not contain array element."); } XmlNode dataNode = node.SelectSingleNode("data"); XmlNode[] childNodes = dataNode.SelectChildNodes("value"); int nodeCount = childNodes.Length; //!! check that multi dim array is not jagged if (dimLengths[CurRank] != 0 && nodeCount != dimLengths[CurRank]) { throw new XmlRpcNonRegularArrayException( "Multi-dimensional array must not be jagged."); } dimLengths[CurRank] = nodeCount; // in case first array at this rank if (CurRank < (Rank - 1)) { foreach (XmlNode vNode in childNodes) { XmlNode arrayNode = vNode.SelectSingleNode("array"); ParseMultiDimElements(arrayNode, Rank, CurRank + 1, elemType, elements, dimLengths, parseStack); } } else { foreach (XmlNode vNode in childNodes) { XmlNode vvNode = vNode.SelectValueNode(); elements.Add(ParseValue(vvNode, elemType, parseStack)); } } }
XmlRpcFaultException ParseFault( XmlNode faultNode, ParseStack parseStack, MappingAction mappingAction) { XmlNode valueNode = faultNode.SelectSingleNode("./value"); XmlNode structNode = valueNode.SelectSingleNode("./struct"); if (structNode == null) { throw new XmlRpcInvalidXmlRpcException( "struct element missing from fault response."); } Fault fault; try { fault = (Fault)ParseValue(structNode, typeof(Fault), parseStack, mappingAction); } catch(Exception ex) { // some servers incorrectly return fault code in a string if (AllowStringFaultCode) throw; else { FaultStructStringCode faultStrCode; try { faultStrCode = (FaultStructStringCode)ParseValue(structNode, typeof(FaultStructStringCode), parseStack, mappingAction); fault.faultCode = Convert.ToInt32(faultStrCode.faultCode); fault.faultString = faultStrCode.faultString; } catch (Exception) { // use exception from when attempting to parse code as integer throw ex; } } } return new XmlRpcFaultException(fault.faultCode, fault.faultString); }
Object ParseDouble( XmlNode node, Type ValueType, ParseStack parseStack, MappingAction mappingAction) { if (ValueType != null && ValueType != typeof(Object) && ValueType != typeof(System.Double) #if !FX1_0 && ValueType != typeof(double?) #endif && ValueType != typeof(XmlRpcDouble)) { throw new XmlRpcTypeMismatchException(parseStack.ParseType + " contains double value where " + XmlRpcServiceInfo.GetXmlRpcTypeString(ValueType) + " expected " + StackDump(parseStack)); } Double retVal; parseStack.Push("double"); try { retVal = Double.Parse(node.FirstChild.Value, CultureInfo.InvariantCulture.NumberFormat); } catch(Exception) { throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains invalid double value " + StackDump(parseStack)); } finally { parseStack.Pop(); } if (ValueType == typeof(XmlRpcDouble)) return new XmlRpcDouble(retVal); else return retVal; }
object ParseStruct( XmlNode node, Type valueType, ParseStack parseStack) { if (valueType.IsPrimitive) { throw new XmlRpcTypeMismatchException(parseStack.ParseType + " contains class value where " + XmlRpcServiceInfo.GetXmlRpcTypeString(valueType) + " expected " + parseStack.Dump()); } if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(Nullable <>)) { valueType = valueType.GetGenericArguments()[0]; } object retObj; try { retObj = Activator.CreateInstance(valueType); } catch (Exception) { throw new XmlRpcTypeMismatchException(parseStack.ParseType + " contains class value where " + XmlRpcServiceInfo.GetXmlRpcTypeString(valueType) + " expected (as type " + valueType.Name + ") " + parseStack.Dump()); } // Note: mapping action on a class is only applied locally - it // does not override the global mapping action when members of the // class are parsed MappingAction localAction = _config.MappingAction; if (valueType != null) { parseStack.Push("class mapped to type " + valueType.Name); localAction = AttributeHelper.StructMappingAction(valueType, localAction); } else { parseStack.Push("struct"); } // create map of field names and remove each name from it as // processed so we can determine which fields are missing // TODO: replace HashTable with lighter collection Hashtable names = new Hashtable(); foreach (FieldInfo fi in valueType.GetFields()) { if (Attribute.IsDefined(fi, typeof(NonSerializedAttribute))) { continue; } names.Add(fi.Name, fi.Name); } foreach (PropertyInfo pi in valueType.GetProperties()) { if (Attribute.IsDefined(pi, typeof(NonSerializedAttribute))) { continue; } names.Add(pi.Name, pi.Name); } XmlNode[] members = node.SelectChildNodes("member"); int fieldCount = 0; foreach (XmlNode member in members) { if (member.Name != "member") { continue; } var(nameNode, nameIsDuplicated) = member.SelectPossibleDoupletteNode("name"); var(valueNode, valueIsDuplicated) = member.SelectPossibleDoupletteNode("value"); if (nameNode == null || nameNode.FirstChild == null) { throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains a member with missing name" + " " + parseStack.Dump()); } if (nameIsDuplicated) { throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains member with more than one name element" + " " + parseStack.Dump()); } string name = nameNode.FirstChild.Value; if (valueNode == null) { throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains class member " + name + " with missing value " + " " + parseStack.Dump()); } if (valueIsDuplicated) { throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains member with more than one value element" + " " + parseStack.Dump()); } string structName = AttributeHelper.GetStructName(valueType, name); if (structName != null) { name = structName; } MemberInfo mi = valueType.GetField(name); if (mi == null) { mi = valueType.GetProperty(name); } if (mi == null) { continue; } if (names.Contains(name)) { names.Remove(name); } else { if (Attribute.IsDefined(mi, typeof(NonSerializedAttribute))) { parseStack.Push(String.Format("member {0}", name)); throw new XmlRpcNonSerializedMember("Cannot map XML-RPC class " + "member onto member marked as [NonSerialized]: " + " " + parseStack.Dump()); } if (!_config.IgnoreDuplicateMembers()) { throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains class value with duplicate member " + nameNode.FirstChild.Value + " " + parseStack.Dump()); } else { continue; // ignore duplicate member } } object valObj = null; switch (mi.MemberType) { case MemberTypes.Field: FieldInfo fi = (FieldInfo)mi; if (valueType == null) { parseStack.Push(String.Format("member {0}", name)); } else { parseStack.Push(String.Format("member {0} mapped to type {1}", name, fi.FieldType.Name)); } try { XmlNode vvvNode = valueNode.SelectValueNode(); valObj = ParseValue(vvvNode, fi.FieldType, parseStack); } catch (XmlRpcInvalidXmlRpcException) { if (valueType != null && localAction == MappingAction.Error) { MappingAction memberAction = AttributeHelper.MemberMappingAction(valueType, name, MappingAction.Error); if (memberAction == MappingAction.Error) { throw; } } } finally { parseStack.Pop(); } fi.SetValue(retObj, valObj); break; case MemberTypes.Property: PropertyInfo pi = (PropertyInfo)mi; if (valueType == null) { parseStack.Push(String.Format("member {0}", name)); } else { parseStack.Push(String.Format("member {0} mapped to type {1}", name, pi.PropertyType.Name)); } XmlNode vvNode = valueNode.SelectValueNode(); valObj = ParseValue(vvNode, pi.PropertyType, parseStack); parseStack.Pop(); pi.SetValue(retObj, valObj, null); break; } fieldCount++; } if (localAction == MappingAction.Error && names.Count > 0) { ReportMissingMembers(valueType, names, parseStack); } parseStack.Pop(); return(retObj); }
string StackDump(ParseStack parseStack) { StringBuilder sb = new StringBuilder(); foreach (string elem in parseStack) { sb.Insert(0, elem); sb.Insert(0, " : "); } sb.Insert(0, parseStack.ParseType); sb.Insert(0, "["); sb.Append("]"); return sb.ToString(); }
Object ParseValue( XmlNode node, Type ValueType, ParseStack parseStack, MappingAction mappingAction) { Type parsedType; Type parsedArrayType; return ParseValue(node, ValueType, parseStack, mappingAction, out parsedType, out parsedArrayType); }
Object ParseString( XmlNode node, Type ValueType, ParseStack parseStack, MappingAction mappingAction) { if (ValueType != null && ValueType != typeof(System.String) && ValueType != typeof(Object)) { throw new XmlRpcTypeMismatchException(parseStack.ParseType + " contains string value where " + XmlRpcServiceInfo.GetXmlRpcTypeString(ValueType) + " expected " + StackDump(parseStack)); } string ret; parseStack.Push("string"); try { if (node.FirstChild == null) ret = ""; else ret = node.FirstChild.Value; } finally { parseStack.Pop(); } return ret; }
Object ParseMultiDimArray(XmlNode node, Type ValueType, ParseStack parseStack, MappingAction mappingAction) { // parse the type name to get element type and array rank #if (!COMPACT_FRAMEWORK) Type elemType = ValueType.GetElementType(); int rank = ValueType.GetArrayRank(); #else string[] checkMultiDim = Regex.Split(ValueType.FullName, "\\[,[,]*\\]$"); Type elemType = Type.GetType(checkMultiDim[0]); string commas = ValueType.FullName.Substring(checkMultiDim[0].Length+1, ValueType.FullName.Length-checkMultiDim[0].Length-2); int rank = commas.Length+1; #endif // elements will be stored sequentially as nested arrays are parsed ArrayList elements = new ArrayList(); // create array to store length of each dimension - initialize to // all zeroes so that when parsing we can determine if an array for // that dimension has been parsed already int[] dimLengths = new int[rank]; dimLengths.Initialize(); ParseMultiDimElements(node, rank, 0, elemType, elements, dimLengths, parseStack, mappingAction); // build arguments to define array dimensions and create the array Object[] args = new Object[dimLengths.Length]; for (int argi=0; argi<dimLengths.Length; argi++) { args[argi] = dimLengths[argi]; } Array ret = (Array)CreateArrayInstance(ValueType, args); // copy elements into new multi-dim array //!! make more efficient int length = ret.Length; for (int e=0; e<length; e++) { int[] indices = new int[dimLengths.Length]; int div = 1; for (int f=(indices.Length-1); f>=0; f--) { indices[f] = (e/div)%dimLengths[f]; div*=dimLengths[f]; } ret.SetValue(elements[e], indices); } return ret; }
public object ParseHashtable(XmlNode node, ParseStack parseStack) { var retObj = new XmlRpcStruct(); parseStack.Push("class mapped to XmlRpcStruct"); try { var members = node.SelectChildNodes("member"); foreach (var member in members) { var(nameNode, hasMultipleNameNodes) = member.SelectPossibleDoupletteNode("name"); var(valueNode, hasMultipleValueNodes) = member.SelectPossibleDoupletteNode("value"); if (nameNode == null || nameNode.FirstChild == null) { throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains a member with missing name" + " " + parseStack.Dump()); } if (hasMultipleNameNodes) { throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains member with more than one name element" + " " + parseStack.Dump()); } var rpcName = nameNode.FirstChild.Value; if (valueNode == null) { throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains class member " + rpcName + " with missing value " + " " + parseStack.Dump()); } if (hasMultipleValueNodes) { throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains member with more than one value element" + " " + parseStack.Dump()); } if (retObj.Contains(rpcName)) { if (_config.IgnoreDuplicateMembers()) { continue; } throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains class value with duplicate member " + nameNode.FirstChild.Value + " " + parseStack.Dump()); } parseStack.Push($"member {rpcName}"); try { var vvNode = valueNode.SelectValueNode(); var valObj = ParseValue(vvNode, null, parseStack); retObj.Add(rpcName, valObj); } finally { parseStack.Pop(); } } } finally { parseStack.Pop(); } return(retObj); }
object ParseValue(XmlNode node, Type ValueType, ParseStack parseStack, out Type ParsedType, out Type ParsedArrayType) { var parser = new XmlSystemTypeParser(_config); ParsedType = null; ParsedArrayType = null; // if suppplied type is System.object then ignore it because // if doesn't provide any useful information (parsing methods // expect null in this case) Type valType = ValueType; if (valType != null && valType.BaseType == null) { valType = null; } object retObj; if (node == null) { retObj = ""; } else if (node is XmlText || node is XmlWhitespace) { if (valType != null && valType != typeof(string)) { throw new XmlRpcTypeMismatchException(parseStack.ParseType + " contains implicit string value where " + XmlRpcServiceInfo.GetXmlRpcTypeString(valType) + " expected " + parseStack.Dump()); } retObj = node.Value; } else { if (node.Name == "array") { retObj = ParseArray(node, valType, parseStack); } else if (node.Name == "base64") { retObj = parser.ParseBase64(node, valType, parseStack); } else if (node.Name == "struct") { // if we don't know the expected class type then we must // parse the XML-RPC class as an instance of XmlRpcStruct if (valType != null && valType != typeof(XmlRpcStruct) && !valType.IsSubclassOf(typeof(XmlRpcStruct))) { retObj = ParseStruct(node, valType, parseStack); } else { retObj = ParseHashtable(node, parseStack); } } else if (node.Name == "i4" || node.Name == "int") // integer has two representations in XML-RPC spec { retObj = parser.ParseInt(node, valType, parseStack); ParsedType = typeof(int); ParsedArrayType = typeof(int[]); } else if (node.Name == "i8") { retObj = parser.ParseLong(node, valType, parseStack); ParsedType = typeof(long); ParsedArrayType = typeof(long[]); } else if (node.Name == "string") { retObj = parser.ParseString(node, valType, parseStack); ParsedType = typeof(string); ParsedArrayType = typeof(string[]); } else if (node.Name == "boolean") { retObj = parser.ParseBoolean(node, valType, parseStack); ParsedType = typeof(bool); ParsedArrayType = typeof(bool[]); } else if (node.Name == "double") { retObj = parser.ParseDouble(node, valType, parseStack); ParsedType = typeof(double); ParsedArrayType = typeof(double[]); } else if (node.Name == "dateTime.iso8601") { retObj = parser.ParseDateTime(node, valType, parseStack); ParsedType = typeof(DateTime); ParsedArrayType = typeof(DateTime[]); } else { throw new XmlRpcInvalidXmlRpcException("Invalid value element: <" + node.Name + ">"); } } return(retObj); }
public object ParseValue(XmlNode node, Type ValueType, ParseStack parseStack) { return(ParseValue(node, ValueType, parseStack, out _, out _)); }
Object ParseHashtable( XmlNode node, Type valueType, ParseStack parseStack, MappingAction mappingAction) { XmlRpcStruct retObj = new XmlRpcStruct(); parseStack.Push("struct mapped to XmlRpcStruct"); try { XmlNodeList members = node.SelectNodes("./member"); foreach (XmlNode member in members) { if (member.Name != "member") continue; XmlNode nameNode; bool dupName; XmlNode valueNode; bool dupValue; SelectTwoNodes(member, "name", out nameNode, out dupName, "value", out valueNode, out dupValue); if (nameNode == null) throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains a member with missing name element" + " " + StackDump(parseStack)); if (dupName) throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains member with more than one name element" + " " + StackDump(parseStack)); string rpcName = nameNode.FirstChild.Value; if (valueNode == null) throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains struct member " + rpcName + " with missing value " + " " + StackDump(parseStack)); if (dupValue) throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains member with more than one value element" + " " + StackDump(parseStack)); if (retObj.Contains(rpcName)) { if (!IgnoreDuplicateMembers) throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains struct value with duplicate member " + nameNode.FirstChild.Value + " " + StackDump(parseStack)); else continue; } object valObj; parseStack.Push(String.Format("member {0}", rpcName)); try { XmlNode vvNode = valueNode.SelectSingleNode("./*"); if (vvNode == null) vvNode = valueNode.FirstChild; valObj = ParseValue(vvNode, null, parseStack, mappingAction); } finally { parseStack.Pop(); } retObj.Add(rpcName, valObj); } } finally { parseStack.Pop(); } return retObj; }
Object ParseInt( XmlNode node, Type ValueType, ParseStack parseStack, MappingAction mappingAction) { if (ValueType != null && ValueType != typeof(Object) && ValueType != typeof(System.Int32) #if !FX1_0 && ValueType != typeof(int?) #endif && ValueType != typeof(XmlRpcInt)) { throw new XmlRpcTypeMismatchException(parseStack.ParseType + " contains int value where " + XmlRpcServiceInfo.GetXmlRpcTypeString(ValueType) + " expected " + StackDump(parseStack)); } int retVal; parseStack.Push("integer"); try { XmlNode valueNode = node.FirstChild; if (valueNode == null) { throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType +" contains invalid int element " + StackDump(parseStack)); } try { String strValue = valueNode.Value; retVal = Int32.Parse(strValue); } catch(Exception) { throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains invalid int value " + StackDump(parseStack)); } } finally { parseStack.Pop(); } if (ValueType == typeof(XmlRpcInt)) return new XmlRpcInt(retVal); else return retVal; }
object ParseArray(XmlNode node, Type valueType, ParseStack parseStack) { // required type must be an array if (valueType != null && !(valueType.IsArray == true || valueType == typeof(Array) || valueType == typeof(object))) { throw new XmlRpcTypeMismatchException(parseStack.ParseType + " contains array value where " + XmlRpcServiceInfo.GetXmlRpcTypeString(valueType) + " expected " + parseStack.Dump()); } if (valueType != null) { XmlRpcType xmlRpcType = XmlRpcServiceInfo.GetXmlRpcType(valueType); if (xmlRpcType == XmlRpcType.MultiDimArray) { parseStack.Push("array mapped to type " + valueType.Name); object ret = ParseMultiDimArray(node, valueType, parseStack); return(ret); } parseStack.Push("array mapped to type " + valueType.Name); } else { parseStack.Push("array"); } var dataNode = node.SelectSingleNode("data"); var childNodes = dataNode.SelectChildNodes("value"); var nodeCount = childNodes.Length; var elements = new object[nodeCount]; // determine type of array elements Type elemType; if (valueType != null && valueType != typeof(Array) && valueType != typeof(object)) { elemType = valueType.GetElementType(); } else { elemType = typeof(object); } bool bGotType = false; Type useType = null; int i = 0; foreach (XmlNode vNode in childNodes) { parseStack.Push(String.Format("element {0}", i)); XmlNode vvNode = vNode.SelectValueNode(); elements[i++] = ParseValue(vvNode, elemType, parseStack, out Type parsedType, out Type parsedArrayType); if (bGotType == false) { useType = parsedArrayType; bGotType = true; } else { if (useType != parsedArrayType) { useType = null; } } parseStack.Pop(); } object[] args = new object[1]; args[0] = nodeCount; object retObj; if (valueType != null && valueType != typeof(Array) && valueType != typeof(object)) { retObj = Activator.CreateInstance(valueType, args); } else { if (useType == null) { retObj = Activator.CreateInstance(typeof(object[]), args); } else { retObj = Activator.CreateInstance(useType, args); } } for (int j = 0; j < elements.Length; j++) { ((Array)retObj).SetValue(elements[j], j); } parseStack.Pop(); return(retObj); }
void ParseMultiDimElements(XmlNode node, int Rank, int CurRank, Type elemType, ArrayList elements, int[] dimLengths, ParseStack parseStack, MappingAction mappingAction) { if (node.Name != "array") { throw new XmlRpcTypeMismatchException( "param element does not contain array element."); } XmlNode dataNode = node.SelectSingleNode("./data"); XmlNodeList childNodes = dataNode.SelectNodes("./value"); int nodeCount = childNodes.Count; //!! check that multi dim array is not jagged if (dimLengths[CurRank] != 0 && nodeCount != dimLengths[CurRank]) { throw new XmlRpcNonRegularArrayException( "Multi-dimensional array must not be jagged."); } dimLengths[CurRank] = nodeCount; // in case first array at this rank if (CurRank < (Rank-1)) { foreach (XmlNode vNode in childNodes) { XmlNode arrayNode = vNode.SelectSingleNode("./array"); ParseMultiDimElements(arrayNode, Rank, CurRank+1, elemType, elements, dimLengths, parseStack, mappingAction); } } else { foreach (XmlNode vNode in childNodes) { XmlNode vvNode = vNode.SelectSingleNode("./*"); if (node == null) node = vNode.FirstChild; elements.Add(ParseValue(vvNode, elemType, parseStack, mappingAction)); } } }
public XmlRpcResponse DeserializeResponse(XmlDocument xdoc, Type returnType) { XmlRpcResponse response = new XmlRpcResponse(); Object retObj = null; XmlNode methodResponseNode = xdoc.SelectSingleNode("./methodResponse"); if (methodResponseNode == null) { throw new XmlRpcInvalidXmlRpcException( "Response XML not valid XML-RPC - missing methodResponse element."); } // check for fault response XmlNode faultNode = methodResponseNode.SelectSingleNode("./fault"); if (faultNode != null) { ParseStack parseStack = new ParseStack("fault response"); // TODO: use global action setting MappingAction mappingAction = MappingAction.Error; XmlRpcFaultException faultEx = ParseFault(faultNode, parseStack, mappingAction); throw faultEx; } XmlNode paramsNode = methodResponseNode.SelectSingleNode("./params"); if (paramsNode == null && returnType != null) { if (returnType == typeof(void)) return null; else throw new XmlRpcInvalidXmlRpcException( "Response XML not valid XML-RPC - missing params element."); } XmlNode paramNode = paramsNode.SelectSingleNode("./param"); if (paramNode == null && returnType != null) { if (returnType == typeof(void)) return null; else throw new XmlRpcInvalidXmlRpcException( "Response XML not valid XML-RPC - missing params element."); } XmlNode valueNode = paramNode.SelectSingleNode("./value"); if (valueNode == null) { throw new XmlRpcInvalidXmlRpcException( "Response XML not valid XML-RPC - missing value element."); } if (returnType == typeof(void)) { retObj = null; } else { ParseStack parseStack = new ParseStack("response"); // TODO: use global action setting MappingAction mappingAction = MappingAction.Error; XmlNode node = valueNode.SelectSingleNode("./*"); if (node == null) node = valueNode.FirstChild; retObj = ParseValue(node, returnType, parseStack, mappingAction); } response.retVal = retObj; return response; }
Object ParseStruct( XmlNode node, Type valueType, ParseStack parseStack, MappingAction mappingAction) { if (valueType.IsPrimitive) { throw new XmlRpcTypeMismatchException(parseStack.ParseType + " contains struct value where " + XmlRpcServiceInfo.GetXmlRpcTypeString(valueType) + " expected " + StackDump(parseStack)); } #if !FX1_0 if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(Nullable<>)) { valueType = valueType.GetGenericArguments()[0]; } #endif object retObj; try { retObj = Activator.CreateInstance(valueType); } catch (Exception ex) { throw new XmlRpcTypeMismatchException(parseStack.ParseType + " contains struct value where " + XmlRpcServiceInfo.GetXmlRpcTypeString(valueType) + " expected (as type " + valueType.Name + ") " + StackDump(parseStack)); } // Note: mapping action on a struct is only applied locally - it // does not override the global mapping action when members of the // struct are parsed MappingAction localAction = mappingAction; if (valueType != null) { parseStack.Push("struct mapped to type " + valueType.Name); localAction = StructMappingAction(valueType, mappingAction); } else { parseStack.Push("struct"); } // create map of field names and remove each name from it as // processed so we can determine which fields are missing // TODO: replace HashTable with lighter collection Hashtable names = new Hashtable(); foreach (FieldInfo fi in valueType.GetFields()) { names.Add(fi.Name, fi.Name); } foreach (PropertyInfo pi in valueType.GetProperties()) { names.Add(pi.Name, pi.Name); } XmlNodeList members = node.SelectNodes("./member"); int fieldCount = 0; foreach (XmlNode member in members) { if (member.Name != "member") continue; XmlNode nameNode; bool dupName; XmlNode valueNode; bool dupValue; SelectTwoNodes(member, "name", out nameNode, out dupName, "value", out valueNode, out dupValue); if (nameNode == null) throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains a member with missing name element" + " " + StackDump(parseStack)); if (dupName) throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains member with more than one name element" + " " + StackDump(parseStack)); string name = nameNode.FirstChild.Value; if (valueNode == null) throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains struct member " + name + " with missing value " + " " + StackDump(parseStack)); if (dupValue) throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains member with more than one value element" + " " + StackDump(parseStack)); string structName = GetStructName(valueType, name); if (structName != null) name = structName; if (names.Contains(name)) names.Remove(name); else { if (!IgnoreDuplicateMembers && (valueType.GetField(name) != null || valueType.GetProperty(name) != null)) throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains struct value with duplicate member " + nameNode.FirstChild.Value + " " + StackDump(parseStack)); else continue; // ignore duplicate member } MemberInfo[] mis = valueType.GetMember(name); if (mis.Length == 0) { continue; // allow unexpected members } Object valObj = null; switch (mis[0].MemberType) { case MemberTypes.Field: FieldInfo fi = (FieldInfo)mis[0]; if (valueType == null) parseStack.Push(String.Format("member {0}", name)); else parseStack.Push(String.Format("member {0} mapped to type {1}", name,fi.FieldType.Name)); try { XmlNode vvvNode = valueNode.SelectSingleNode("./*"); if (vvvNode == null) vvvNode = valueNode.FirstChild; valObj = ParseValue(vvvNode, fi.FieldType, parseStack, mappingAction); } catch(XmlRpcInvalidXmlRpcException) { if (valueType != null && localAction == MappingAction.Error) { MappingAction memberAction = MemberMappingAction(valueType, name, MappingAction.Error); if (memberAction == MappingAction.Error) throw; } } finally { parseStack.Pop(); } fi.SetValue(retObj, valObj); break ; case MemberTypes.Property : PropertyInfo pi = (PropertyInfo)mis[0] ; if (valueType == null) parseStack.Push(String.Format("member {0}", name)); else parseStack.Push(String.Format("member {0} mapped to type {1}", name,pi.PropertyType.Name)); XmlNode vvNode = valueNode.SelectSingleNode("./*"); if (vvNode == null) vvNode = valueNode.FirstChild; valObj = ParseValue(vvNode, pi.PropertyType, parseStack, mappingAction); parseStack.Pop(); pi.SetValue(retObj, valObj, null); break ; } fieldCount++; } if (localAction == MappingAction.Error && names.Count > 0) ReportMissingMembers(valueType, names, parseStack); parseStack.Pop(); return retObj; }
Object ParseArray( XmlNode node, Type ValueType, ParseStack parseStack, MappingAction mappingAction) { // required type must be an array if (ValueType != null && !(ValueType.IsArray == true || ValueType == typeof(Array) || ValueType == typeof(object))) { throw new XmlRpcTypeMismatchException(parseStack.ParseType + " contains array value where " + XmlRpcServiceInfo.GetXmlRpcTypeString(ValueType) + " expected " + StackDump(parseStack)); } if (ValueType != null) { XmlRpcType xmlRpcType = XmlRpcServiceInfo.GetXmlRpcType(ValueType); if (xmlRpcType == XmlRpcType.tMultiDimArray) { parseStack.Push("array mapped to type " + ValueType.Name); Object ret = ParseMultiDimArray(node, ValueType, parseStack, mappingAction); return ret; } parseStack.Push("array mapped to type " + ValueType.Name); } else parseStack.Push("array"); XmlNode dataNode = node.SelectSingleNode("./data"); XmlNodeList childNodes = dataNode.SelectNodes("./value"); int nodeCount = childNodes.Count; Object[] elements = new Object[nodeCount]; // determine type of array elements Type elemType = null; if (ValueType != null && ValueType != typeof(Array) && ValueType != typeof(object)) { #if (!COMPACT_FRAMEWORK) elemType = ValueType.GetElementType(); #else string[] checkMultiDim = Regex.Split(ValueType.FullName, "\\[\\]$"); // determine assembly of array element type Assembly asmbly = ValueType.Assembly; string[] asmblyName = asmbly.FullName.Split(','); string elemTypeName = checkMultiDim[0] + ", " + asmblyName[0]; elemType = Type.GetType(elemTypeName); #endif } else { elemType = typeof(object); } bool bGotType = false; Type useType = null; int i = 0; foreach (XmlNode vNode in childNodes) { parseStack.Push(String.Format("element {0}", i)); XmlNode vvNode = vNode.SelectSingleNode("./*"); if (vvNode == null) vvNode = vNode.FirstChild; Type parsedType; Type parsedArrayType; elements[i++] = ParseValue(vvNode, elemType, parseStack, mappingAction, out parsedType, out parsedArrayType); if (bGotType == false) { useType = parsedArrayType; bGotType = true; } else { if (useType != parsedArrayType) useType = null; } parseStack.Pop(); } Object[] args = new Object[1]; args[0] = nodeCount; Object retObj = null; if (ValueType != null && ValueType != typeof(Array) && ValueType != typeof(object)) { retObj = CreateArrayInstance(ValueType, args); } else { if (useType == null) retObj = CreateArrayInstance(typeof(object[]), args); else retObj = CreateArrayInstance(useType, args); } for (int j=0; j < elements.Length; j++) { ((Array)retObj).SetValue(elements[j], j); } parseStack.Pop(); return retObj; }
void ReportMissingMembers( Type valueType, Hashtable names, ParseStack parseStack) { StringBuilder sb = new StringBuilder(); int errorCount = 0; string sep = ""; foreach (string s in names.Keys) { MappingAction memberAction = MemberMappingAction(valueType, s, MappingAction.Error); if (memberAction == MappingAction.Error) { sb.Append(sep); sb.Append(s); sep = " "; errorCount++; } } if (errorCount > 0) { string plural = ""; if (errorCount > 1) plural = "s"; throw new XmlRpcTypeMismatchException(parseStack.ParseType + " contains struct value with missing non-optional member" + plural + ": " + sb.ToString() + " " + StackDump(parseStack)); } }
Object ParseBoolean( XmlNode node, Type ValueType, ParseStack parseStack, MappingAction mappingAction) { if (ValueType != null && ValueType != typeof(Object) && ValueType != typeof(System.Boolean) #if !FX1_0 && ValueType != typeof(bool?) #endif && ValueType != typeof(XmlRpcBoolean)) { throw new XmlRpcTypeMismatchException(parseStack.ParseType + " contains boolean value where " + XmlRpcServiceInfo.GetXmlRpcTypeString(ValueType) + " expected " + StackDump(parseStack)); } bool retVal; parseStack.Push("boolean"); try { string s = node.FirstChild.Value; if (s == "1") { retVal = true; } else if (s == "0") { retVal = false; } else { throw new XmlRpcInvalidXmlRpcException( "reponse contains invalid boolean value " + StackDump(parseStack)); } } finally { parseStack.Pop(); } if (ValueType == typeof(XmlRpcBoolean)) return new XmlRpcBoolean(retVal); else return retVal; }
public XmlRpcRequest DeserializeRequest(XmlDocument xdoc, Type svcType) { XmlRpcRequest request = new XmlRpcRequest(); XmlNode callNode = xdoc.SelectSingleNode("./methodCall"); if (callNode == null) { throw new XmlRpcInvalidXmlRpcException( "Request XML not valid XML-RPC - missing methodCall element."); } XmlNode methodNode = callNode.SelectSingleNode("./methodName"); if (methodNode == null) { throw new XmlRpcInvalidXmlRpcException( "Request XML not valid XML-RPC - missing methodName element."); } request.method = methodNode.FirstChild.Value; if (request.method == "") { throw new XmlRpcInvalidXmlRpcException( "Request XML not valid XML-RPC - empty methodName."); } request.mi = null; ParameterInfo[] pis = new ParameterInfo[0]; if (svcType != null) { // retrieve info for the method which handles this XML-RPC method XmlRpcServiceInfo svcInfo = XmlRpcServiceInfo.CreateServiceInfo(svcType); request.mi = svcInfo.GetMethodInfo(request.method); // if a service type has been specified and we cannot find the requested // method then we must throw an exception if (request.mi == null) { string msg = String.Format("unsupported method called: {0}", request.method); throw new XmlRpcUnsupportedMethodException(msg); } // method must be marked with XmlRpcMethod attribute Attribute attr = Attribute.GetCustomAttribute(request.mi, typeof(XmlRpcMethodAttribute)); if (attr == null) { throw new XmlRpcMethodAttributeException( "Method must be marked with the XmlRpcMethod attribute."); } pis = request.mi.GetParameters(); } XmlNode paramsNode = callNode.SelectSingleNode("./params"); if (paramsNode == null) { if (svcType != null) { if (pis.Length == 0) { request.args = new object[0]; return request; } else { throw new XmlRpcInvalidParametersException( "Method takes parameters and params element is missing."); } } else { request.args = new object[0]; return request; } } XmlNodeList paramNodes = paramsNode.SelectNodes("./param"); int paramsPos = GetParamsPos(pis); if (paramNodes.Count < paramsPos) { throw new XmlRpcInvalidParametersException( "Method takes parameters and there is incorrect number of param " + "elements."); } ParseStack parseStack = new ParseStack("request"); // TODO: use global action setting MappingAction mappingAction = MappingAction.Error; int paramObjCount = (paramsPos == -1 ?paramNodes.Count : paramsPos + 1); Object[] paramObjs = new Object[paramObjCount]; // parse ordinary parameters int ordinaryParams = (paramsPos == -1 ?paramNodes.Count :paramsPos); for (int i = 0; i < ordinaryParams; i++) { XmlNode paramNode = paramNodes[i]; XmlNode valueNode = paramNode.SelectSingleNode("./value"); if (valueNode == null) throw new XmlRpcInvalidXmlRpcException("Missing value element."); XmlNode node = valueNode.SelectSingleNode("./*"); if (node == null) node = valueNode.FirstChild; if (svcType != null) { parseStack.Push(String.Format("parameter {0}", i + 1)); // TODO: why following commented out? // parseStack.Push(String.Format("parameter {0} mapped to type {1}", // i, pis[i].ParameterType.Name)); paramObjs[i] = ParseValue(node, pis[i].ParameterType, parseStack, mappingAction); } else { parseStack.Push(String.Format("parameter {0}", i)); paramObjs[i] = ParseValue(node, null, parseStack, mappingAction); } parseStack.Pop(); } // parse params parameters if (paramsPos != -1) { Type paramsType = pis[paramsPos].ParameterType.GetElementType(); Object[] args = new Object[1]; args[0] = paramNodes.Count - paramsPos; Array varargs = (Array)CreateArrayInstance(pis[paramsPos].ParameterType, args); for (int i = 0; i < varargs.Length; i++) { XmlNode paramNode = paramNodes[i + paramsPos]; XmlNode valueNode = paramNode.SelectSingleNode("value"); if (valueNode == null) throw new XmlRpcInvalidXmlRpcException("Missing value element."); XmlNode node = valueNode.SelectSingleNode("./*"); if (node == null) node = valueNode.FirstChild; parseStack.Push(String.Format("parameter {0}", i + 1 + paramsPos)); varargs.SetValue(ParseValue(node, paramsType, parseStack, mappingAction), i); parseStack.Pop(); } paramObjs[paramsPos] = varargs; } request.args = paramObjs; return request; }
Object ParseLong( XmlNode node, Type ValueType, ParseStack parseStack, MappingAction mappingAction) { if (ValueType != null && ValueType != typeof(Object) && ValueType != typeof(System.Int64) #if !FX1_0 && ValueType != typeof(long?)) #endif { throw new XmlRpcTypeMismatchException(parseStack.ParseType + " contains i8 value where " + XmlRpcServiceInfo.GetXmlRpcTypeString(ValueType) + " expected " + StackDump(parseStack)); } long retVal; parseStack.Push("i8"); try { XmlNode valueNode = node.FirstChild; if (valueNode == null) { throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains invalid i8 element " + StackDump(parseStack)); } try { String strValue = valueNode.Value; retVal = Int64.Parse(strValue); } catch (Exception) { throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains invalid i8 value " + StackDump(parseStack)); } } finally { parseStack.Pop(); } return retVal; }
//#if (DEBUG) //#endif public Object ParseValue( XmlNode node, Type ValueType, ParseStack parseStack, MappingAction mappingAction, out Type ParsedType, out Type ParsedArrayType) { ParsedType = null; ParsedArrayType = null; // if suppplied type is System.Object then ignore it because // if doesn't provide any useful information (parsing methods // expect null in this case) Type valType = ValueType; if (valType != null && valType.BaseType == null) valType = null; Object retObj = null; if (node == null) { retObj = ""; } else if (node is XmlText || node is XmlWhitespace) { if (valType != null && valType != typeof(string)) { throw new XmlRpcTypeMismatchException(parseStack.ParseType + " contains implicit string value where " + XmlRpcServiceInfo.GetXmlRpcTypeString(valType) + " expected " + StackDump(parseStack)); } retObj = node.Value; } else { if (node.Name == "array") retObj = ParseArray(node, valType, parseStack, mappingAction); else if (node.Name == "base64") retObj = ParseBase64(node, valType, parseStack, mappingAction); else if (node.Name == "struct") { // if we don't know the expected struct type then we must // parse the XML-RPC struct as an instance of XmlRpcStruct if (valType != null && valType != typeof(XmlRpcStruct) && !valType.IsSubclassOf(typeof(XmlRpcStruct))) { retObj = ParseStruct(node, valType, parseStack, mappingAction); } else { if (valType == null || valType == typeof(object)) valType = typeof(XmlRpcStruct); // TODO: do we need to validate type here? retObj = ParseHashtable(node, valType, parseStack, mappingAction); } } else if (node.Name == "i4" // integer has two representations in XML-RPC spec || node.Name == "int") { retObj = ParseInt(node, valType, parseStack, mappingAction); ParsedType = typeof(int); ParsedArrayType = typeof(int[]); } else if (node.Name == "string") { retObj = ParseString(node, valType, parseStack, mappingAction); ParsedType = typeof(string); ParsedArrayType = typeof(string[]); } else if (node.Name == "boolean") { retObj = ParseBoolean(node, valType, parseStack, mappingAction); ParsedType = typeof(bool); ParsedArrayType = typeof(bool[]); } else if (node.Name == "double") { retObj = ParseDouble(node, valType, parseStack, mappingAction); ParsedType = typeof(double); ParsedArrayType = typeof(double[]); } else if (node.Name == "dateTime.iso8601") { retObj = ParseDateTime(node, valType, parseStack, mappingAction); ParsedType = typeof(DateTime); ParsedArrayType = typeof(DateTime[]); } } return retObj; }
public XmlRpcRequest DeserializeRequest(XmlDocument xdoc, Type svcType) { XmlRpcRequest request = new XmlRpcRequest(); XmlNode callNode = SelectSingleNode(xdoc, "methodCall"); if (callNode == null) { throw new XmlRpcInvalidXmlRpcException( "Request XML not valid XML-RPC - missing methodCall element."); } XmlNode methodNode = SelectSingleNode(callNode, "methodName"); if (methodNode == null) { throw new XmlRpcInvalidXmlRpcException( "Request XML not valid XML-RPC - missing methodName element."); } if (methodNode.FirstChild == null) { throw new XmlRpcInvalidXmlRpcException( "Request XML not valid XML-RPC - missing methodName element."); } request.method = methodNode.FirstChild.Value; if (request.method == "") { throw new XmlRpcInvalidXmlRpcException( "Request XML not valid XML-RPC - empty methodName."); } request.mi = null; ParameterInfo[] pis = new ParameterInfo[0]; if (svcType != null) { // retrieve info for the method which handles this XML-RPC method XmlRpcServiceInfo svcInfo = XmlRpcServiceInfo.CreateServiceInfo(svcType); request.mi = svcInfo.GetMethodInfo(request.method); // if a service type has been specified and we cannot find the requested // method then we must throw an exception if (request.mi == null) { string msg = String.Format("unsupported method called: {0}", request.method); throw new XmlRpcUnsupportedMethodException(msg); } // method must be marked with XmlRpcMethod attribute Attribute attr = Attribute.GetCustomAttribute(request.mi, typeof(XmlRpcMethodAttribute)); if (attr == null) { throw new XmlRpcMethodAttributeException( "Method must be marked with the XmlRpcMethod attribute."); } pis = request.mi.GetParameters(); } XmlNode paramsNode = SelectSingleNode(callNode, "params"); if (paramsNode == null) { if (svcType != null) { if (pis.Length == 0) { request.args = new object[0]; return request; } // JB Change // Sometimes tapatalk calls the same method with both parameters and no parameters // This allows us to handle that by changing the no parameter case into an empty parameter array else if(pis.Length == 1 && pis[0].ParameterType == typeof(object[])) { paramsNode = xdoc.CreateNode(XmlNodeType.Element, "params", ""); //var paramNode = xdoc.CreateNode(XmlNodeType.Element, "param", ""); //paramsNode.AppendChild(paramNode); // var valueNode = xdoc.CreateNode(XmlNodeType.Element, "value", ""); //paramNode.AppendChild(valueNode); // var arrayNode = xdoc.CreateNode(XmlNodeType.Element, "string", ""); //valueNode.AppendChild(arrayNode); // var dataNode = xdoc.CreateNode(XmlNodeType.Element, "data", ""); //arrayNode.AppendChild(dataNode); } else { throw new XmlRpcInvalidParametersException( "Method takes parameters and params element is missing."); } } else { request.args = new object[0]; return request; } } XmlNode[] paramNodes = SelectNodes(paramsNode, "param"); int paramsPos = GetParamsPos(pis); int minParamCount = paramsPos == -1 ? pis.Length : paramsPos; if (svcType != null && paramNodes.Length < minParamCount) { throw new XmlRpcInvalidParametersException( "Request contains too few param elements based on method signature."); } if (svcType != null && paramsPos == -1 && paramNodes.Length > pis.Length) { throw new XmlRpcInvalidParametersException( "Request contains too many param elements based on method signature."); } ParseStack parseStack = new ParseStack("request"); // TODO: use global action setting MappingAction mappingAction = MappingAction.Error; int paramObjCount = (paramsPos == -1 ? paramNodes.Length : paramsPos + 1); Object[] paramObjs = new Object[paramObjCount]; // parse ordinary parameters int ordinaryParams = (paramsPos == -1 ? paramNodes.Length : paramsPos); for (int i = 0; i < ordinaryParams; i++) { XmlNode paramNode = paramNodes[i]; XmlNode valueNode = SelectSingleNode(paramNode, "value"); if (valueNode == null) throw new XmlRpcInvalidXmlRpcException("Missing value element."); XmlNode node = SelectValueNode(valueNode); if (svcType != null) { parseStack.Push(String.Format("parameter {0}", i + 1)); // TODO: why following commented out? // parseStack.Push(String.Format("parameter {0} mapped to type {1}", // i, pis[i].ParameterType.Name)); paramObjs[i] = ParseValue(node, pis[i].ParameterType, parseStack, mappingAction); } else { parseStack.Push(String.Format("parameter {0}", i)); paramObjs[i] = ParseValue(node, null, parseStack, mappingAction); } parseStack.Pop(); } // parse params parameters if (paramsPos != -1) { Type paramsType = pis[paramsPos].ParameterType.GetElementType(); Object[] args = new Object[1]; args[0] = paramNodes.Length - paramsPos; Array varargs = (Array)CreateArrayInstance(pis[paramsPos].ParameterType, args); for (int i = 0; i < varargs.Length; i++) { XmlNode paramNode = paramNodes[i + paramsPos]; XmlNode valueNode = SelectSingleNode(paramNode, "value"); if (valueNode == null) throw new XmlRpcInvalidXmlRpcException("Missing value element."); XmlNode node = SelectValueNode(valueNode); parseStack.Push(String.Format("parameter {0}", i + 1 + paramsPos)); varargs.SetValue(ParseValue(node, paramsType, parseStack, mappingAction), i); parseStack.Pop(); } paramObjs[paramsPos] = varargs; } request.args = paramObjs; return request; }
Object ParseBase64( XmlNode node, Type ValueType, ParseStack parseStack, MappingAction mappingAction) { if (ValueType != null && ValueType != typeof(byte[]) && ValueType != typeof(Object)) { throw new XmlRpcTypeMismatchException(parseStack.ParseType + " contains base64 value where " + XmlRpcServiceInfo.GetXmlRpcTypeString(ValueType) + " expected " + StackDump(parseStack)); } byte[] ret; parseStack.Push("base64"); try { if (node.FirstChild == null) ret = new byte[0]; else { string s = node.FirstChild.Value; try { ret = Convert.FromBase64String(s); } catch (Exception) { throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains invalid base64 value " + StackDump(parseStack)); } } } finally { parseStack.Pop(); } return ret; }
Object ParseDateTime( XmlNode node, Type ValueType, ParseStack parseStack, MappingAction mappingAction) { if (ValueType != null && ValueType != typeof(Object) && ValueType != typeof(System.DateTime) #if !FX1_0 && ValueType != typeof(DateTime?) #endif && ValueType != typeof(XmlRpcDateTime)) { throw new XmlRpcTypeMismatchException(parseStack.ParseType + " contains dateTime.iso8601 value where " + XmlRpcServiceInfo.GetXmlRpcTypeString(ValueType) + " expected " + StackDump(parseStack)); } DateTime retVal; parseStack.Push("dateTime"); try { XmlNode child = node.FirstChild; if (child == null) { if (MapEmptyDateTimeToMinValue) return DateTime.MinValue; else throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains empty dateTime value " + StackDump(parseStack)); } string s = child.Value; // Allow various iso8601 formats, e.g. // XML-RPC spec yyyyMMddThh:mm:ss // WordPress yyyyMMddThh:mm:ssZ // TypePad yyyy-MM-ddThh:mm:ssZ // other yyyy-MM-ddThh:mm:ss if (!DateTime8601.TryParseDateTime8601(s, out retVal)) { if (MapZerosDateTimeToMinValue && s.StartsWith("0000") && (s == "00000000T00:00:00" || s == "0000-00-00T00:00:00Z" || s == "00000000T00:00:00Z" || s == "0000-00-00T00:00:00")) retVal = DateTime.MinValue; else throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains invalid dateTime value " + StackDump(parseStack)); } } finally { parseStack.Pop(); } if (ValueType == typeof(XmlRpcDateTime)) return new XmlRpcDateTime(retVal); else return retVal; }
Object ParseDateTime( XmlNode node, Type ValueType, ParseStack parseStack, MappingAction mappingAction) { if (ValueType != null && ValueType != typeof(Object) && ValueType != typeof(System.DateTime) #if !FX1_0 && ValueType != typeof(DateTime?) #endif && ValueType != typeof(XmlRpcDateTime)) { throw new XmlRpcTypeMismatchException(parseStack.ParseType + " contains dateTime.iso8601 value where " + XmlRpcServiceInfo.GetXmlRpcTypeString(ValueType) + " expected " + StackDump(parseStack)); } DateTime retVal; parseStack.Push("dateTime"); try { XmlNode child = node.FirstChild; if (child == null) { if (MapEmptyDateTimeToMinValue) return DateTime.MinValue; else throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains empty dateTime value " + StackDump(parseStack)); } string s = child.Value; try { // XML-RPC spec yyyyMMddThh:mm:ss string dateTimeFormat = "yyyyMMdd'T'HH':'mm':'ss"; if (AllowNonStandardDateTime) { if (s.IndexOf("T") == 8) { if (s.EndsWith("Z")) { // WordPress yyyyMMddThh:mm:ssZ dateTimeFormat = "yyyyMMdd'T'HH':'mm':'ss'Z'"; } else if (s.EndsWith("-00") || s.EndsWith("-0000") || s.EndsWith("+00") || s.EndsWith("+0000")) { s = s.Substring(0, 17); } } else { if (s.EndsWith("Z")) { // TypePad yyyy-MM-ddThh:mm:ssZ dateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"; } else { // other yyyy-MM-ddThh:mm:ss dateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss"; } } } if (MapZerosDateTimeToMinValue && s.StartsWith("0000") && (s == "00000000T00:00:00" || s == "0000-00-00T00:00:00Z" || s == "00000000T00:00:00Z" || s == "0000-00-00T00:00:00")) retVal = DateTime.MinValue; else retVal = DateTime.ParseExact(s, dateTimeFormat, DateTimeFormatInfo.InvariantInfo); } catch(Exception) { throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType + " contains invalid dateTime value " + StackDump(parseStack)); } } finally { parseStack.Pop(); } if (ValueType == typeof(XmlRpcDateTime)) return new XmlRpcDateTime(retVal); else return retVal; }
public XmlRpcResponse DeserializeResponse(XmlDocument xdoc, Type returnType) { var parser = new XmlParser(Configuration); var methodResponseNode = xdoc.SelectSingleNode("methodResponse"); if (methodResponseNode == null) { throw new XmlRpcInvalidXmlRpcException("Response XML not valid XML-RPC - missing methodResponse element."); } var faultNode = methodResponseNode.SelectSingleNode("fault"); if (faultNode != null) { var parseStack = new ParseStack("fault response"); var faultEx = parser.ParseFault(faultNode, parseStack); throw faultEx; } var paramsNode = methodResponseNode.SelectSingleNode("params"); if (paramsNode == null && returnType != null) { if (returnType == typeof(void)) { return(new XmlRpcResponse(null)); } else { throw new XmlRpcInvalidXmlRpcException("Response XML not valid XML-RPC - missing params element."); } } var paramNode = paramsNode.SelectSingleNode("param"); if (paramNode == null && returnType != null) { if (returnType == typeof(void)) { return(new XmlRpcResponse(null)); } else { throw new XmlRpcInvalidXmlRpcException("Response XML not valid XML-RPC - missing params element."); } } var valueNode = paramNode.SelectSingleNode("value"); if (valueNode == null) { throw new XmlRpcInvalidXmlRpcException("Response XML not valid XML-RPC - missing value element."); } var response = new XmlRpcResponse(null); if (returnType != typeof(void)) { var parseStack = new ParseStack("response"); var node = valueNode.SelectValueNode(); response.ReturnValue = parser.ParseValue(node, returnType, parseStack); } return(response); }