From 49758fe71669c51bd8a0bf38b813bb3de290197e Mon Sep 17 00:00:00 2001 From: John-Mark Gurney Date: Fri, 23 Nov 2007 15:17:43 -0800 Subject: [PATCH] from: https://coherence.beebits.net/browser/trunk/coherence/upnp/core/soap_lite.py?format=raw [git-p4: depot-paths = "//depot/": change = 1102] --- soap_lite.py | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 soap_lite.py diff --git a/soap_lite.py b/soap_lite.py new file mode 100644 index 0000000..b521c1d --- /dev/null +++ b/soap_lite.py @@ -0,0 +1,111 @@ +# Licensed under the MIT license +# http://opensource.org/licenses/mit-license.php + +# Copyright 2007 - Frank Scholz + +""" SOAP-lite + + some simple functions to implement the SOAP msgs + needed by UPnP with ElementTree + + inspired by ElementSOAP.py +""" + +from coherence.extern.et import ET + +NS_SOAP_ENV = "{http://schemas.xmlsoap.org/soap/envelope/}" +NS_SOAP_ENC = "{http://schemas.xmlsoap.org/soap/encoding/}" +NS_XSI = "{http://www.w3.org/1999/XMLSchema-instance}" +NS_XSD = "{http://www.w3.org/1999/XMLSchema}" + +SOAP_ENCODING = "http://schemas.xmlsoap.org/soap/encoding/" + +UPNPERRORS = {401:'Invalid Action', + 402:'Invalid Args', + 501:'Action Failed', + 600:'Argument Value Invalid', + 601:'Argument Value Out of Range', + 602:'Optional Action Not Implemented', + 603:'Out Of Memory', + 604:'Human Intervention Required', + 605:'String Argument Too Long', + 606:'Action Not Authorized', + 607:'Signature Failure', + 608:'Signature Missing', + 609:'Not Encrypted', + 610:'Invalid Sequence', + 611:'Invalid Control URL', + 612:'No Such Session',} + +def build_soap_error(status,description='without words'): + """ builds an UPnP SOAP error msg + """ + root = ET.Element('s:Fault') + ET.SubElement(root,'faultcode').text='s:Client' + ET.SubElement(root,'faultstring').text='UPnPError' + e = ET.SubElement(root,'detail') + e = ET.SubElement(e, 'UPnPError') + e.attrib['xmlns']='urn:schemas-upnp-org:control-1-0' + ET.SubElement(e,'errorCode').text=str(status) + ET.SubElement(e,'errorDescription').text=UPNPERRORS.get(status,description) + return build_soap_call(None, root, encoding=None) + +def build_soap_call(method, arguments, is_response=False, + encoding=SOAP_ENCODING, + envelope_attrib=None, + typed=None): + """ create a shell for a SOAP request or response element + - set method to none to omitt the method element and + add the arguments directly to the body (for an error msg) + - arguments can be a dict or an ET.Element + """ + envelope = ET.Element("s:Envelope") + if envelope_attrib: + for n in envelope_attrib: + envelope.attrib.update({n[0] : n[1]}) + else: + envelope.attrib.update({'s:encodingStyle' : "http://schemas.xmlsoap.org/soap/encoding/"}) + envelope.attrib.update({'xmlns:s' :"http://schemas.xmlsoap.org/soap/envelope/"}) + + body = ET.SubElement(envelope, "s:Body") + + if method: + # append the method call + if is_response is True: + method += "Response" + re = ET.SubElement(body,method) + if encoding: + re.set(NS_SOAP_ENV + "encodingStyle", encoding) + else: + re = body + + # append the arguments + if isinstance(arguments,dict): + type_map = {str: 'xsd:string', + unicode: 'xsd:string', + int: 'xsd:int', + float: 'xsd:float', + bool: 'xsd:boolean'} + + for arg_name, arg_val in arguments.iteritems(): + arg_type = type_map[type(arg_val)] + if arg_type == 'xsd:string' and type(arg_val) == unicode: + arg_val = arg_val.encode('utf-8') + if arg_type == 'xsd:int' or arg_type == 'xsd:float': + arg_val = str(arg_val) + if arg_type == 'xsd:boolean': + arg_val = arg_val.lower() + + e = ET.SubElement(re, arg_name) + if typed and arg_type: + if not isinstance(type, ET.QName): + arg_type = ET.QName("http://www.w3.org/1999/XMLSchema", arg_type) + e.set(NS_XSI + "type", arg_type) + e.text = arg_val + else: + re.append(arguments) + + + + preamble = """""" + return preamble + ET.tostring(envelope,'utf-8')