summaryrefslogtreecommitdiffstats
path: root/lib/libUPnP/Platinum/Source/Core/PltAction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libUPnP/Platinum/Source/Core/PltAction.cpp')
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltAction.cpp505
1 files changed, 505 insertions, 0 deletions
diff --git a/lib/libUPnP/Platinum/Source/Core/PltAction.cpp b/lib/libUPnP/Platinum/Source/Core/PltAction.cpp
new file mode 100644
index 0000000..78ff4b2
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltAction.cpp
@@ -0,0 +1,505 @@
+/*****************************************************************
+|
+| Platinum - Service Action
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| licensing@plutinosoft.com
+|
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltAction.h"
+#include "PltService.h"
+#include "PltUtilities.h"
+
+#define REMOVE_WMP_DATATYPE_EXTENSION
+
+NPT_SET_LOCAL_LOGGER("platinum.core.action")
+
+/*----------------------------------------------------------------------
+| PLT_ActionDesc::PLT_ActionDesc
++---------------------------------------------------------------------*/
+PLT_ActionDesc::PLT_ActionDesc(const char* name, PLT_Service* service) :
+ m_Name(name),
+ m_Service(service)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_ActionDesc::~PLT_ActionDesc
++---------------------------------------------------------------------*/
+PLT_ActionDesc::~PLT_ActionDesc()
+{
+ m_ArgumentDescs.Apply(NPT_ObjectDeleter<PLT_ArgumentDesc>());
+}
+
+/*----------------------------------------------------------------------
+| PLT_ActionDesc::GetSCPDXML
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_ActionDesc::GetSCPDXML(NPT_XmlElementNode* node)
+{
+ NPT_XmlElementNode* action = new NPT_XmlElementNode("action");
+ NPT_CHECK_SEVERE(node->AddChild(action));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(action, "name", m_Name));
+
+ NPT_XmlElementNode* argumentList = new NPT_XmlElementNode("argumentList");
+ NPT_CHECK_SEVERE(action->AddChild(argumentList));
+
+ // no arguments is ok
+ if (!m_ArgumentDescs.GetItemCount()) return NPT_SUCCESS;
+
+ return m_ArgumentDescs.ApplyUntil(
+ PLT_GetSCPDXMLIterator<PLT_ArgumentDesc>(argumentList),
+ NPT_UntilResultNotEquals(NPT_SUCCESS));
+}
+
+/*----------------------------------------------------------------------
+| PLT_ActionDesc::GetService
++---------------------------------------------------------------------*/
+PLT_Service*
+PLT_ActionDesc::GetService()
+{
+ return m_Service;
+}
+
+/*----------------------------------------------------------------------
+| PLT_ActionDesc::GetArgumentDesc
++---------------------------------------------------------------------*/
+PLT_ArgumentDesc*
+PLT_ActionDesc::GetArgumentDesc(const char* name)
+{
+ PLT_ArgumentDesc* arg_desc = NULL;
+ NPT_ContainerFind(m_ArgumentDescs, PLT_ArgumentDescNameFinder(name), arg_desc);
+ return arg_desc;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::PLT_Action
++---------------------------------------------------------------------*/
+PLT_Action::PLT_Action(PLT_ActionDesc& action_desc) :
+ m_ActionDesc(action_desc),
+ m_ErrorCode(0)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::PLT_Action
++---------------------------------------------------------------------*/
+PLT_Action::PLT_Action(PLT_ActionDesc& action_desc,
+ PLT_DeviceDataReference& root_device) :
+ m_ActionDesc(action_desc),
+ m_ErrorCode(0),
+ m_RootDevice(root_device)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::~PLT_Action
++---------------------------------------------------------------------*/
+PLT_Action::~PLT_Action()
+{
+ m_Arguments.Apply(NPT_ObjectDeleter<PLT_Argument>());
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::GetArgumentValue
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::GetArgumentValue(const char* name, NPT_String& value)
+{
+ PLT_Argument* arg = GetArgument(name);
+ if (arg == NULL) {
+ return NPT_FAILURE;
+ }
+ value = arg->GetValue();
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::GetArgumentValue
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::GetArgumentValue(const char* name, NPT_UInt32& value)
+{
+ NPT_String tmp_value;
+ NPT_CHECK_WARNING(GetArgumentValue(name, tmp_value));
+ return tmp_value.ToInteger(value);
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::GetArgumentValue
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::GetArgumentValue(const char* name, NPT_Int32& value)
+{
+ NPT_String tmp_value;
+ NPT_CHECK_WARNING(GetArgumentValue(name, tmp_value));
+ return tmp_value.ToInteger(value);
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::GetArgumentValue
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::GetArgumentValue(const char* name, bool& value)
+{
+ NPT_String tmp_value;
+ NPT_CHECK_WARNING(GetArgumentValue(name, tmp_value));
+ if (tmp_value == "1" ||
+ !tmp_value.Compare("TRUE", true) ||
+ !tmp_value.Compare("YES", true)) {
+ value = true;
+ } else if (tmp_value == "0" ||
+ !tmp_value.Compare("FALSE", true) ||
+ !tmp_value.Compare("NO", true)) {
+ value = false;
+ } else {
+ return NPT_FAILURE;
+ }
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::GetArgument
++---------------------------------------------------------------------*/
+PLT_Argument*
+PLT_Action::GetArgument(const char* name)
+{
+ PLT_Argument* argument = NULL;
+ NPT_ContainerFind(m_Arguments, PLT_ArgumentNameFinder(name), argument);
+ return argument;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::SetArgumentValue
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::SetArgumentValue(const char* name,
+ const char* value)
+{
+ // look for this argument in our argument list
+ // and replace the value if we found it
+ PLT_Arguments::Iterator iter = NULL;
+ if (NPT_SUCCEEDED(NPT_ContainerFind(m_Arguments, PLT_ArgumentNameFinder(name), iter))) {
+ NPT_Result res = (*iter)->SetValue(value);
+
+ // remove argument from list if failed
+ // so that when we verify arguments later,
+ // we don't use a previously set value
+ if (NPT_FAILED(res)) m_Arguments.Erase(iter);
+ return res;
+ }
+
+ // since we didn't find it, create a clone
+ PLT_Argument* arg;
+ NPT_CHECK_SEVERE(PLT_Argument::CreateArgument(m_ActionDesc, name, value, arg));
+
+ // insert it at the right position
+ for (NPT_Cardinal i=0;
+ i<m_Arguments.GetItemCount();
+ i++) {
+ iter = m_Arguments.GetItem(i);
+ if ((*iter)->GetPosition() > arg->GetPosition()) {
+ return m_Arguments.Insert(iter, arg);
+ }
+ }
+
+ return m_Arguments.Add(arg);
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::VerifyArgumentValue
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::VerifyArgumentValue(const char* name, const char* value)
+{
+ NPT_String str;
+ NPT_CHECK_SEVERE(GetArgumentValue(name, str));
+
+ return str.Compare(value, true)?NPT_FAILURE:NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::VerifyArguments
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::VerifyArguments(bool input)
+{
+ NPT_Cardinal count = 0;
+
+ // Check we have all the required parameters (in or out)
+ for(unsigned int i=0; i<m_ActionDesc.GetArgumentDescs().GetItemCount(); i++) {
+ PLT_ArgumentDesc* arg_desc = m_ActionDesc.GetArgumentDescs()[i];
+
+ // only input arguments are needed
+ if (arg_desc->GetDirection().Compare(input?"in":"out", true))
+ continue;
+
+ // look for this argument in the list we received
+ PLT_Argument* arg = NULL;
+ if (NPT_FAILED(NPT_ContainerFind(m_Arguments, PLT_ArgumentNameFinder(arg_desc->GetName()), arg))) {
+ NPT_LOG_WARNING_2("Argument %s for action %s not found",
+ (const char*) arg_desc->GetName(),
+ (const char*) m_ActionDesc.GetName());
+ return NPT_FAILURE;
+ }
+ ++count;
+ }
+
+ SetError(0, "");
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::SetArgumentOutFromStateVariable
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::SetArgumentOutFromStateVariable(PLT_ArgumentDesc* arg_desc)
+{
+ // only output arguments can use a state variable
+ if (arg_desc->GetDirection().Compare("out", true)) {
+ return NPT_FAILURE;
+ }
+
+ PLT_StateVariable* variable = arg_desc->GetRelatedStateVariable();
+ if (!variable) return NPT_FAILURE;
+
+ // assign the value to an argument
+ NPT_CHECK_SEVERE(SetArgumentValue(arg_desc->GetName(), variable->GetValue()));
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::SetArgumentOutFromStateVariable
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::SetArgumentOutFromStateVariable(const char* name)
+{
+ // look for this argument in the action list of arguments
+ PLT_ArgumentDesc* arg_desc = NULL;
+ NPT_CHECK_SEVERE(NPT_ContainerFind(m_ActionDesc.GetArgumentDescs(),
+ PLT_ArgumentDescNameFinder(name), arg_desc));
+
+ return SetArgumentOutFromStateVariable(arg_desc);
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::SetArgumentsOutFromStateVariable
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::SetArgumentsOutFromStateVariable()
+{
+ // go through the list of the action output arguments
+ for(unsigned int i=0; i<m_ActionDesc.GetArgumentDescs().GetItemCount(); i++) {
+ PLT_ArgumentDesc* arg_desc = m_ActionDesc.GetArgumentDescs()[i];
+
+ // only output arguments are needed
+ if (arg_desc->GetDirection().Compare("out", true))
+ continue;
+
+ NPT_CHECK_SEVERE(SetArgumentOutFromStateVariable(arg_desc));
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::SetError
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::SetError(unsigned int code, const char* description)
+{
+ m_ErrorCode = code;
+ m_ErrorDescription = description;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::GetError
++---------------------------------------------------------------------*/
+const char*
+PLT_Action::GetError(unsigned int* code /* = NULL */)
+{
+ if (code) *code = m_ErrorCode;
+ return m_ErrorDescription;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::GetErrorCode
++---------------------------------------------------------------------*/
+unsigned int
+PLT_Action::GetErrorCode()
+{
+ return m_ErrorCode;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::FormatSoapRequest
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::FormatSoapRequest(NPT_OutputStream& stream)
+{
+ NPT_String str;
+ NPT_Result res;
+ NPT_XmlElementNode* body = NULL;
+ NPT_XmlElementNode* request = NULL;
+ NPT_XmlElementNode* envelope = new NPT_XmlElementNode("s", "Envelope");
+
+ NPT_CHECK_LABEL_SEVERE(res = envelope->SetNamespaceUri("s", "http://schemas.xmlsoap.org/soap/envelope/"), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = envelope->SetAttribute("s", "encodingStyle", "http://schemas.xmlsoap.org/soap/encoding/"), cleanup);
+
+ body = new NPT_XmlElementNode("s", "Body");
+ NPT_CHECK_LABEL_SEVERE(res = envelope->AddChild(body), cleanup);
+
+ request = new NPT_XmlElementNode("u", m_ActionDesc.GetName());
+ NPT_CHECK_LABEL_SEVERE(res = request->SetNamespaceUri("u", m_ActionDesc.GetService()->GetServiceType()), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = body->AddChild(request), cleanup);
+
+ for(unsigned int i=0; i<m_Arguments.GetItemCount(); i++) {
+ PLT_Argument* argument = m_Arguments[i];
+ if (argument->GetDesc().GetDirection().Compare("in", true) == 0) {
+ NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::AddChildText(
+ request,
+ argument->GetDesc().GetName(),
+ argument->GetValue()), cleanup);
+ }
+ }
+
+ NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::Serialize(*envelope, str), cleanup);
+ delete envelope;
+
+ return stream.Write((const char*)str, str.GetLength());
+
+cleanup:
+ delete envelope;
+ return res;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::FormatSoapResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::FormatSoapResponse(NPT_OutputStream& stream)
+{
+ if (m_ErrorCode) {
+ return FormatSoapError(m_ErrorCode, m_ErrorDescription, stream);
+ }
+
+ NPT_String str;
+ NPT_Result res;
+ NPT_XmlElementNode* body = NULL;
+ NPT_XmlElementNode* response = NULL;
+ NPT_XmlElementNode* node = NULL;
+ NPT_XmlElementNode* envelope = new NPT_XmlElementNode("s", "Envelope");
+
+ NPT_CHECK_LABEL_SEVERE(res = envelope->SetNamespaceUri("s", "http://schemas.xmlsoap.org/soap/envelope/"), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = envelope->SetAttribute("s", "encodingStyle", "http://schemas.xmlsoap.org/soap/encoding/"), cleanup);
+
+ body = new NPT_XmlElementNode("s", "Body");
+ NPT_CHECK_LABEL_SEVERE(res = envelope->AddChild(body), cleanup);
+
+ response = new NPT_XmlElementNode("u", m_ActionDesc.GetName() + "Response");
+ NPT_CHECK_LABEL_SEVERE(response->SetNamespaceUri("u", m_ActionDesc.GetService()->GetServiceType()), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = body->AddChild(response), cleanup);
+
+ for(unsigned int i=0; i<m_Arguments.GetItemCount(); i++) {
+ PLT_Argument* argument = m_Arguments[i];
+ if (argument->GetDesc().GetDirection().Compare("out", true) == 0) {
+ node = new NPT_XmlElementNode(argument->GetDesc().GetName());
+ NPT_CHECK_LABEL_SEVERE(res = node->AddText(argument->GetValue()), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = response->AddChild(node), cleanup);
+
+#ifndef REMOVE_WMP_DATATYPE_EXTENSION
+ PLT_StateVariable* var = argument->GetDesc().GetRelatedStateVariable();
+ if (var) {
+ node->SetNamespaceUri("dt", "urn:schemas-microsoft-com:datatypes");
+ node->SetAttribute("dt", "dt", var->GetDataType());
+ }
+#endif
+ }
+ }
+
+ // this will xmlescape any values that contain xml characters
+ NPT_CHECK_LABEL_SEVERE(PLT_XmlHelper::Serialize(*envelope, str), cleanup);
+ delete envelope;
+
+ return stream.Write((const char*)str, str.GetLength());
+
+cleanup:
+ delete envelope;
+ return res;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::FormatSoapError
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::FormatSoapError(unsigned int code, NPT_String desc, NPT_OutputStream& stream)
+{
+ NPT_String str;
+ NPT_Result res;
+ NPT_XmlElementNode* body = NULL;
+ NPT_XmlElementNode* fault = NULL;
+ NPT_XmlElementNode* detail = NULL;
+ NPT_XmlElementNode* UPnPError = NULL;
+ NPT_XmlElementNode* envelope = new NPT_XmlElementNode("s", "Envelope");
+
+ NPT_CHECK_LABEL_SEVERE(res = envelope->SetNamespaceUri("s", "http://schemas.xmlsoap.org/soap/envelope/"), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = envelope->SetAttribute("s", "encodingStyle", "http://schemas.xmlsoap.org/soap/encoding/"), cleanup);
+
+ body = new NPT_XmlElementNode("s", "Body");
+ NPT_CHECK_LABEL_SEVERE(res = envelope->AddChild(body), cleanup);
+
+ fault = new NPT_XmlElementNode("s", "Fault");
+ NPT_CHECK_LABEL_SEVERE(res = body->AddChild(fault), cleanup);
+
+ NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::AddChildText(fault, "faultcode", "s:Client"), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::AddChildText(fault, "faultstring", "UPnPError"), cleanup);
+
+ detail = new NPT_XmlElementNode("detail");
+ NPT_CHECK_LABEL_SEVERE(res = fault->AddChild(detail), cleanup);
+
+ UPnPError = new NPT_XmlElementNode("UPnPError");
+ NPT_CHECK_LABEL_SEVERE(res = UPnPError->SetNamespaceUri("", "urn:schemas-upnp-org:control-1-0"), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = detail->AddChild(UPnPError), cleanup);
+
+ NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::AddChildText(UPnPError, "errorCode", NPT_String::FromInteger(code)), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::AddChildText(UPnPError, "errorDescription", desc), cleanup);
+
+ NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::Serialize(*envelope, str), cleanup);
+ delete envelope;
+
+ return stream.Write((const char*)str, str.GetLength());
+
+cleanup:
+ delete envelope;
+ return res;
+}