Exemple #1
0
        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();
            }
        }
Exemple #2
0
        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();
            }
        }
Exemple #3
0
        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());
        }
Exemple #4
0
        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();
            }
        }
Exemple #5
0
        public XmlRpcRequest DeserializeRequest(Stream inputStream, Type serviceType)
        {
            _parseStack = new ParseStack("request");

            var xdoc = XmlDocumentLoader.LoadXmlDocument(inputStream);

            return(DeserializeRequest(xdoc, serviceType));
        }
Exemple #6
0
        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();
            }
        }
Exemple #7
0
        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();
            }
        }
Exemple #8
0
        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);
        }
Exemple #9
0
        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();
            }
        }
Exemple #10
0
        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));
        }
Exemple #11
0
        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;
   }
Exemple #14
0
        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;
   }
Exemple #19
0
        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);
        }
Exemple #20
0
        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);
        }
Exemple #21
0
 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;
   }
Exemple #24
0
        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;
   }
Exemple #38
0
        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);
        }