protected override object DoDeserializeValue(XmlReader reader, bool isSimpleValue)
        {
            if (SoapHelper.ReadEmptyStartElement(reader)) // Read start of enclosing element
            {
                return(null);
            }
            if (!reader.MoveToAttribute("type"))
            {
                throw new ArgumentException("Cannot deserialize value, 'type' attribute missing");
            }
            String typeStr = reader.ReadContentAsString();
            Type   type    = Type.GetType(typeStr);

            reader.MoveToElement();
            HomogenousMap result = new HomogenousMap(type, typeof(int));

            if (SoapHelper.ReadEmptyStartElement(reader, "Values"))
            {
                return(result);
            }
            while (reader.NodeType != XmlNodeType.EndElement)
            {
                result.Add(MediaItemAspect.DeserializeValue(reader, type), MediaItemAspect.DeserializeValue(reader, typeof(int)));
            }
            reader.ReadEndElement(); // End of enclosing element
            return(result);
        }
예제 #2
0
        protected static IList <object> ParseResult(TextReader textReader, CpAction action, bool sourceSupportsUPnP11)
        {
            IList <object> outParameterValues = new List <object>();

            using (XmlReader reader = XmlReader.Create(textReader, UPnPConfiguration.DEFAULT_XML_READER_SETTINGS))
            {
                reader.MoveToContent();
                // Parse SOAP envelope
                reader.ReadStartElement("Envelope", UPnPConsts.NS_SOAP_ENVELOPE);
                reader.ReadStartElement("Body", UPnPConsts.NS_SOAP_ENVELOPE);
                // Reader is positioned at the action element
                string serviceTypeVersion_URN = reader.NamespaceURI;
                string type;
                int    version;
                // Parse service and action
                if (!ParserHelper.TryParseTypeVersion_URN(serviceTypeVersion_URN, out type, out version))
                {
                    throw new ArgumentException("Invalid service type or version");
                }
                string actionName = reader.LocalName;
                if (!actionName.EndsWith("Response") ||
                    actionName.Substring(0, actionName.Length - "Response".Length) != action.Name)
                {
                    throw new ArgumentException("Invalid action name in result message");
                }

                IEnumerator <CpArgument> formalArgumentEnumer = action.OutArguments.GetEnumerator();
                if (!SoapHelper.ReadEmptyStartElement(reader))
                {
                    // Parse and check output parameters
                    while (reader.NodeType != XmlNodeType.EndElement)
                    {
                        string argumentName = reader.Name;    // Arguments don't have a namespace, so take full name
                        if (!formalArgumentEnumer.MoveNext()) // Too many arguments
                        {
                            throw new ArgumentException("Invalid out argument count");
                        }
                        if (formalArgumentEnumer.Current.Name != argumentName)
                        {
                            throw new ArgumentException("Invalid argument name");
                        }
                        object value;
                        if (SoapHelper.ReadNull(reader))
                        {
                            value = null;
                        }
                        else
                        {
                            formalArgumentEnumer.Current.SoapParseArgument(reader, !sourceSupportsUPnP11, out value);
                        }
                        outParameterValues.Add(value);
                    }
                }
                if (formalArgumentEnumer.MoveNext()) // Too few arguments
                {
                    throw new ArgumentException("Invalid out argument count");
                }
            }
            return(outParameterValues);
        }
예제 #3
0
        public static MediaItemAspect Deserialize(XmlReader reader)
        {
            if (!reader.MoveToAttribute("Id"))
            {
                throw new ArgumentException("Media item aspect cannot be deserialized: 'Id' attribute missing");
            }
            Guid aspectTypeId = new Guid(reader.ReadContentAsString());

            reader.MoveToElement();
            IMediaItemAspectTypeRegistration miatr = ServiceRegistration.Get <IMediaItemAspectTypeRegistration>();
            MediaItemAspectMetadata          miaType;

            if (!miatr.LocallyKnownMediaItemAspectTypes.TryGetValue(aspectTypeId, out miaType))
            {
                throw new ArgumentException(string.Format("Media item aspect cannot be deserialized: Unknown media item aspect type '{0}'",
                                                          aspectTypeId));
            }
            MediaItemAspect result = new MediaItemAspect(miaType);

            if (SoapHelper.ReadEmptyStartElement(reader, "Aspect"))
            {
                return(result);
            }
            while (reader.NodeType != XmlNodeType.EndElement)
            {
                if (!reader.MoveToAttribute("Name"))
                {
                    throw new ArgumentException("Media item aspect attribute cannot be deserialized: 'Name' attribute missing");
                }
                String attributeName = reader.ReadContentAsString();
                reader.MoveToElement();
                if (SoapHelper.ReadEmptyStartElement(reader, "Attr"))
                {
                    continue;
                }
                MediaItemAspectMetadata.AttributeSpecification attributeSpec;
                if (!miaType.AttributeSpecifications.TryGetValue(attributeName, out attributeSpec))
                {
                    throw new ArgumentException(string.Format(
                                                    "Media item aspect attribute cannot be deserialized: Unknown attribute specification '{0}'", attributeName));
                }
                if (attributeSpec.IsCollectionAttribute)
                {
                    IList valuesCollection = attributeSpec.CreateValuesCollection();
                    while (reader.NodeType != XmlNodeType.EndElement)
                    {
                        valuesCollection.Add(DeserializeValue(reader, attributeSpec.AttributeType));
                    }
                    result.SetCollectionAttribute(attributeSpec, valuesCollection);
                }
                else
                {
                    result.SetAttribute(attributeSpec, DeserializeValue(reader, attributeSpec.AttributeType));
                }
                reader.ReadEndElement(); // Attr
            }
            reader.ReadEndElement();     // Aspect
            return(result);
        }
예제 #4
0
        protected override object DoDeserializeValue(XmlReader reader, bool isSimpleValue)
        {
            ICollection <ResourcePathMetadata> result = new List <ResourcePathMetadata>();

            if (SoapHelper.ReadEmptyStartElement(reader)) // Read start of enclosing element
            {
                return(result);
            }
            while (reader.NodeType != XmlNodeType.EndElement)
            {
                result.Add(ResourcePathMetadata.Deserialize(reader));
            }
            reader.ReadEndElement(); // End of enclosing element
            return(result);
        }
예제 #5
0
        protected override object DoDeserializeValue(XmlReader reader, bool isSimpleValue)
        {
            if (SoapHelper.ReadEmptyStartElement(reader)) // Read start of enclosing element
            {
                return(null);
            }

            Schedule result = null;

            while (reader.NodeType != XmlNodeType.EndElement)
            {
                result = Schedule.Deserialize(reader);
            }
            reader.ReadEndElement(); // End of enclosing element
            return(result);
        }
예제 #6
0
        protected override object DoDeserializeValue(XmlReader reader, bool isSimpleValue)
        {
            IDictionary <string, MediaCategory_DTO> result_dtos = new Dictionary <string, MediaCategory_DTO>();

            if (SoapHelper.ReadEmptyStartElement(reader)) // Read start of enclosing element
            {
                return(new List <MediaCategory>());
            }
            while (reader.NodeType != XmlNodeType.EndElement)
            {
                MediaCategory_DTO result_dto = MediaCategory_DTO.Deserialize(reader);
                result_dtos.Add(result_dto.CategoryName, result_dto);
            }
            reader.ReadEndElement(); // End of enclosing element
            return(new List <MediaCategory>(result_dtos.Select(mCatDtoKvp => mCatDtoKvp.Value.GetMediaCategory(result_dtos))));
        }
예제 #7
0
        protected static IList <object> ParseResult(TextReader textReader, CpAction action, bool sourceSupportsUPnP11)
        {
            object[] outParameterValues = new object[action.OutArguments.Count];
            using (XmlReader reader = XmlReader.Create(textReader, UPnPConfiguration.DEFAULT_XML_READER_SETTINGS))
            {
                reader.MoveToContent();
                // Parse SOAP envelope
                reader.ReadStartElement("Envelope", UPnPConsts.NS_SOAP_ENVELOPE);
                reader.ReadStartElement("Body", UPnPConsts.NS_SOAP_ENVELOPE);
                // Reader is positioned at the action element
                string serviceTypeVersion_URN = reader.NamespaceURI;
                string type;
                int    version;
                // Parse service and action
                if (!ParserHelper.TryParseTypeVersion_URN(serviceTypeVersion_URN, out type, out version))
                {
                    throw new ArgumentException("Invalid service type or version");
                }
                string actionName = reader.LocalName;
                if (!actionName.EndsWith("Response") ||
                    actionName.Substring(0, actionName.Length - "Response".Length) != action.Name)
                {
                    throw new ArgumentException("Invalid action name in result message");
                }

                // UPnP spec says we have to be able to handle return values being out
                // of order to support UPnP 1.0 devices. See UPnP-arch-DeviceArchitecture-v1.1
                // section 2.5.4. We need a dictionary to make this easy.
                IDictionary <string, int> formalArgIdxDictionary = new Dictionary <string, int>();
                for (int i = 0; i < action.OutArguments.Count; i++)
                {
                    formalArgIdxDictionary.Add(action.OutArguments[i].Name, i);
                }

                int outArgCount = 0;
                if (!SoapHelper.ReadEmptyStartElement(reader))
                {
                    // Parse and check output parameters
                    while (reader.NodeType != XmlNodeType.EndElement)
                    {
                        string argumentName = reader.Name; // Arguments don't have a namespace, so take full name
                        int    formalArgumentIndex;
                        if (!formalArgIdxDictionary.TryGetValue(argumentName, out formalArgumentIndex))
                        {
                            throw new ArgumentException("Invalid argument name");
                        }
                        CpArgument formalArgument = action.OutArguments[formalArgumentIndex];

                        // Get the argument value and store it in the correct position in the return list.
                        object value = null;
                        if (!SoapHelper.ReadNull(reader))
                        {
                            formalArgument.SoapParseArgument(reader, !sourceSupportsUPnP11, out value);
                        }
                        outParameterValues[formalArgumentIndex] = value;
                        outArgCount++;

                        // Don't allow duplicates of the same argument.
                        formalArgIdxDictionary.Remove(formalArgument.Name);
                    }
                }
                if (outArgCount != action.OutArguments.Count) // Too few arguments
                {
                    throw new ArgumentException("Invalid out argument count");
                }
            }
            return(outParameterValues);
        }
예제 #8
0
        /// <summary>
        /// Handler method for SOAP control requests.
        /// </summary>
        /// <param name="service">The service whose action was called.</param>
        /// <param name="messageStream">The stream which contains the HTTP message body with the SOAP envelope.</param>
        /// <param name="streamEncoding">Encoding of the <paramref name="messageStream"/>.</param>
        /// <param name="subscriberSupportsUPnP11">Should be set if the requester sent a user agent header which denotes a UPnP
        /// version of 1.1. If set to <c>false</c>, in- and out-parameters with extended data type will be deserialized/serialized
        /// using the string-equivalent of the values.</param>
        /// <param name="context">Context object holding data for the current action call.</param>
        /// <param name="result">SOAP result - may be an action result, a SOAP fault or <c>null</c> if no body should
        /// be sent in the HTTP response.</param>
        /// <returns>HTTP status code to be sent. Should be
        /// <list>
        /// <item><see cref="HttpStatusCode.OK"/> If the action could be evaluated correctly and produced a SOAP result.</item>
        /// <item><see cref="HttpStatusCode.InternalServerError"/> If the result is a SOAP fault.</item>
        /// <item><see cref="HttpStatusCode.BadRequest"/> If the message stream was malformed.</item>
        /// </list>
        /// </returns>
        public static HttpStatusCode HandleRequest(DvService service, Stream messageStream, Encoding streamEncoding,
                                                   bool subscriberSupportsUPnP11, CallContext context, out string result)
        {
            UPnPError res;

            try
            {
                IList <object> inParameterValues = null; // Default to null if there aren't parameters, will be lazily initialized later
                DvAction       action;
                using (StreamReader streamReader = new StreamReader(messageStream, streamEncoding))
                    using (XmlReader reader = XmlReader.Create(streamReader, UPnPConfiguration.DEFAULT_XML_READER_SETTINGS))
                    {
                        reader.MoveToContent();
                        // Parse SOAP envelope
                        reader.ReadStartElement("Envelope", UPnPConsts.NS_SOAP_ENVELOPE);
                        reader.ReadStartElement("Body", UPnPConsts.NS_SOAP_ENVELOPE);
                        // Reader is positioned at the action element
                        string serviceTypeVersion_URN = reader.NamespaceURI;
                        string type;
                        int    version;
                        // Parse service and action
                        if (!ParserHelper.TryParseTypeVersion_URN(serviceTypeVersion_URN, out type, out version))
                        {
                            throw new MediaPortal.Utilities.Exceptions.InvalidDataException("Unable to parse service type and version URN '{0}'", serviceTypeVersion_URN);
                        }
                        string actionName = reader.LocalName;
                        if (!service.Actions.TryGetValue(actionName, out action))
                        {
                            result = CreateFaultDocument(401, "Invalid Action");
                            return(HttpStatusCode.InternalServerError);
                        }
                        IEnumerator <DvArgument> formalArgumentEnumer = action.InArguments.GetEnumerator();
                        if (!SoapHelper.ReadEmptyStartElement(reader)) // Action name
                        {
                            while (reader.NodeType != XmlNodeType.EndElement)
                            {
                                string argumentName = reader.Name; // Arguments don't have a namespace, so take full name
                                if (!formalArgumentEnumer.MoveNext() || formalArgumentEnumer.Current.Name != argumentName)
                                {                                  // Too many arguments
                                    result = CreateFaultDocument(402, "Invalid Args");
                                    return(HttpStatusCode.InternalServerError);
                                }
                                object value;
                                if (SoapHelper.ReadNull(reader))
                                {
                                    value = null;
                                }
                                else
                                {
                                    res = formalArgumentEnumer.Current.SoapParseArgument(reader, !subscriberSupportsUPnP11, out value);
                                    if (res != null)
                                    {
                                        result = CreateFaultDocument(res.ErrorCode, res.ErrorDescription);
                                        return(HttpStatusCode.InternalServerError);
                                    }
                                }
                                if (inParameterValues == null)
                                {
                                    inParameterValues = new List <object>();
                                }
                                inParameterValues.Add(value);
                            }
                        }
                        if (formalArgumentEnumer.MoveNext())
                        { // Too few arguments
                            result = CreateFaultDocument(402, "Invalid Args");
                            return(HttpStatusCode.InternalServerError);
                        }
                    }
                IList <object> outParameterValues;
                // Invoke action
                try
                {
                    res = action.InvokeAction(inParameterValues, out outParameterValues, false, context);
                    // outParameterValues can be null if the action has no output parameters. Setting it to an empty list makes
                    // it easier to check parameter count later.
                    if (outParameterValues == null)
                    {
                        outParameterValues = EMPTY_OBJECT_LIST;
                    }
                }
                catch (Exception e)
                {
                    UPnPConfiguration.LOGGER.Warn("SOAPHandler: Error invoking UPnP action '{0}'", e, action.Name);
                    result = CreateFaultDocument(501, "Action Failed");
                    return(HttpStatusCode.InternalServerError);
                }
                if (res != null)
                {
                    result = CreateFaultDocument(res.ErrorCode, res.ErrorDescription);
                    return(HttpStatusCode.InternalServerError);
                }
                // Check output parameters
                IList <DvArgument> formalArguments = action.OutArguments;
                if (outParameterValues.Count != formalArguments.Count)
                {
                    result = CreateFaultDocument(501, "Action Failed");
                    return(HttpStatusCode.InternalServerError);
                }
                IList <OutParameter> outParams = formalArguments.Select((t, i) => new OutParameter(t, outParameterValues[i])).ToList();
                result = CreateResultDocument(action, outParams, !subscriberSupportsUPnP11);
                return(HttpStatusCode.OK);
            }
            catch (Exception e)
            {
                string message = "Error handling SOAP request: " + e.Message;
                UPnPConfiguration.LOGGER.Warn(message);     // Don't log the whole exception; it's only a communication error with a client

                result = CreateFaultDocument(500, message); // Also send message to client
                return(HttpStatusCode.InternalServerError);
            }
        }