Ejemplo n.º 1
0
    def to_xml(self, *data):
        if len(self.params):
            if len(data) != len(self.params):
                raise Exception("Parameter number mismatch expected [%s] "
                                "got [%s] for response %s" %
                                (len(self.params), len(data), self.name))

        nsmap = NamespaceLookup(self.ns)
        element = create_xml_element(self.name, nsmap, self.ns)

        for i in range(0, len(self.params)):
            name, serializer = self.params[i]
            d = data[i]
            e = serializer.to_xml(d, name, nsmap)
            if type(e) in (list, tuple):
                elist = e
                for e in elist:
                    element.append(e)
            elif e == None:
                pass
            else:
                element.append(e)

        ElementTree.cleanup_namespaces(element)
        return element
Ejemplo n.º 2
0
    def to_xml(self, *data):
        if len(self.params):
            if len(self.params) >= 2:
                data = data[0]
            if len(data) != len(self.params):
                raise Exception(
                    "Parameter number mismatch expected [%s] "
                    "got [%s] for response %s" % (len(self.params), len(data), self.name)
                )

        nsmap = NamespaceLookup(self.ns)
        element = create_xml_element(self.name, nsmap, self.ns)

        for i in range(0, len(self.params)):
            name, serializer = self.params[i]
            d = data[i]
            e = serializer.to_xml(d, name, nsmap)
            if type(e) in (list, tuple):
                elist = e
                for e in elist:
                    element.append(e)
            elif e == None:
                pass
            else:
                element.append(e)

        ElementTree.cleanup_namespaces(element)
        return element
Ejemplo n.º 3
0
    def index_html(self, REQUEST, RESPONSE):
        """Handle an incoming SOAP request or a non-SOAP WSDL query."""

        if REQUEST.get('SOAPXML', None) == None:  # Not a SOAP Request, return WSDL
            return self.service_description(REQUEST, RESPONSE)

        try:
            # Deserialize the Body of the SOAP Request
            payload, header = from_soap(REQUEST.SOAPXML)
            methodname = payload.tag.split('}')[-1]

            # Look-up the method within our class and obtain its SOAP descriptor
            # specifying its arguments signature and return type.
            try:
                func = getattr(self, methodname)
                descriptor = func(_soap_descriptor=True)
            except AttributeError:
                faultstring = 'No Such SOAP Method: %s' % repr(methodname)
                faultcode = 'Server'

                fault = make_soap_fault(faultstring, faultcode, detail=None)
                resp = ElementTree.tostring(fault, encoding=string_encoding)

                RESPONSE.setStatus('NotImplemented', reason=faultstring)
                RESPONSE.setHeader('Content-Type', 'text/xml')
                return resp
            except TypeError, e:
                if "unexpected keyword argument '_soap_descriptor'" not in str(e):
                    raise

                faultstring = 'Method %s Exists But Not SOAP-Callable' % repr(methodname)
                faultcode = 'Server'

                fault = make_soap_fault(faultstring, faultcode, detail=None)
                resp = ElementTree.tostring(fault, encoding=string_encoding)

                RESPONSE.setStatus('BadRequest', reason=faultstring)
                RESPONSE.setHeader('Content-Type', 'text/xml')
                return resp

            # Run the supplied arguments through the arguments signature and catch
            # any argument type or count mismatches.
            try:
                params = descriptor.inMessage.from_xml(payload)
            except Exception, e:
                faultstring = "%s: Argument Parse Error" % str(e)
                faultcode = '%sFault' % methodname

                fault = make_soap_fault(faultstring, faultcode, detail=None)
                resp = ElementTree.tostring(fault, encoding=string_encoding)

                RESPONSE.setStatus('BadRequest', reason=faultstring)
                RESPONSE.setHeader('Content-Type', 'text/xml')
                return resp
Ejemplo n.º 4
0
Archivo: soap.py Proyecto: caot/soaplib
def join_attachment(id, envelope, payload, prefix=True):
    '''
    Helper function for swa_to_soap.

    Places the data from an attachment back into a SOAP message, replacing
    its xop:Include element or href.

    @param  id          content-id or content-location of attachment
    @param  prefix      Set this to true if id is content-id or false if
                        it is content-location.  It prefixes a "cid:" to
                        the href value.
    @param  envelope    soap envelope string to be operated on
    @param  payload     attachment data
    @return             tuple of length 2 with the new message and the
                        number of replacements made
    '''

    # grab the XML element of the message in the SOAP body
    soapmsg = StringIO(envelope)
    soaptree = ElementTree.parse(soapmsg)
    soapns = soaptree.getroot().tag.split('}')[0].strip('{')
    soapbody = soaptree.getroot().find("{%s}Body" % soapns)
    message = None
    for child in list(soapbody):
        if child.tag != "%sFault" % (soapns, ):
            message = child
            break

    numreplaces = 0
    idprefix = ''
    if prefix == True:
        idprefix = "cid:"
    id = "%s%s" % (
        idprefix,
        id,
    )

    # Make replacement.
    for param in message:
        # Look for Include subelement.
        for sub in param:
            if sub.tag.split('}')[-1] == 'Include' and \
               sub.attrib.get('href') == id:
                param.remove(sub)
                param.text = payload
                numreplaces += 1
        if numreplaces < 1 and param.attrib.get('href') == id:
            del (param.attrib['href'])
            param.text = payload
            numreplaces += 1

    soapmsg.close()
    soapmsg = StringIO()
    soaptree.write(soapmsg)
    joinedmsg = soapmsg.getvalue()
    soapmsg.close()

    return (joinedmsg, numreplaces)
Ejemplo n.º 5
0
    def __call__(self):
        faultstring = self.request['faultexc'].__class__.__name__
        self.request.response.setStatus('InternalServerError', reason=faultstring)

        faultcode = 'Server'
        fault = make_soap_fault(faultstring, faultcode, detail=None)

        self.request.response.setHeader('Content-Type', 'text/xml')
        return ElementTree.tostring(fault, encoding=string_encoding)
Ejemplo n.º 6
0
def join_attachment(id, envelope, payload, prefix=True):
    '''
    Helper function for swa_to_soap.

    Places the data from an attachment back into a SOAP message, replacing
    its xop:Include element or href.

    @param  id          content-id or content-location of attachment
    @param  prefix      Set this to true if id is content-id or false if
                        it is content-location.  It prefixes a "cid:" to
                        the href value.
    @param  envelope    soap envelope string to be operated on
    @param  payload     attachment data
    @return             tuple of length 2 with the new message and the
                        number of replacements made
    '''

    # grab the XML element of the message in the SOAP body
    soapmsg = StringIO(envelope)
    soaptree = ElementTree.parse(soapmsg)
    soapns = soaptree.getroot().tag.split('}')[0].strip('{')
    soapbody = soaptree.getroot().find("{%s}Body" % soapns)
    message = None
    for child in list(soapbody):
        if child.tag != "%sFault" % (soapns, ):
            message = child
            break

    numreplaces = 0
    idprefix = ''
    if prefix == True:
        idprefix = "cid:"
    id = "%s%s" % (idprefix, id, )

    # Make replacement.
    for param in message:
        # Look for Include subelement.
        for sub in param:
            if sub.tag.split('}')[-1] == 'Include' and \
               sub.attrib.get('href') == id:
                param.remove(sub)
                param.text = payload
                numreplaces += 1
        if numreplaces < 1 and param.attrib.get('href') == id:
            del(param.attrib['href'])
            param.text = payload
            numreplaces += 1

    soapmsg.close()
    soapmsg = StringIO()
    soaptree.write(soapmsg)
    joinedmsg = soapmsg.getvalue()
    soapmsg.close()

    return (joinedmsg, numreplaces)
Ejemplo n.º 7
0
    def test_join_attachment(self):
        id="http://tempuri.org/1/634133419330914808"
        payload="ANJNSLJNDYBC SFDJNIREMX:CMKSAJN"
        envelope = '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><DownloadPartFileResponse xmlns="http://tempuri.org/"><DownloadPartFileResult xmlns:a="http://schemas.datacontract.org/2004/07/KlanApi.Common" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><a:ErrorCode>0</a:ErrorCode><a:ErrorMessage i:nil="true"/><a:Data><xop:Include href="cid:http%3A%2F%2Ftempuri.org%2F1%2F634133419330914808" xmlns:xop="http://www.w3.org/2004/08/xop/include"/></a:Data></DownloadPartFileResult></DownloadPartFileResponse></s:Body></s:Envelope>'
        (joinedmsg, numreplaces) = join_attachment(id, envelope, payload)

        soapmsg = StringIO(joinedmsg)
        soaptree = ElementTree.parse(soapmsg)

        soapns = "http://schemas.xmlsoap.org/soap/envelope/"        
        r = DownloadPartFileResult.from_xml( soaptree.getroot().find("{%s}Body" % soapns).getchildren()[0].getchildren()[0] )

        self.assertEquals(payload, r.Data)        
Ejemplo n.º 8
0
    def test_join_attachment(self):
        id = "http://tempuri.org/1/634133419330914808"
        payload = "ANJNSLJNDYBC SFDJNIREMX:CMKSAJN"
        envelope = '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><DownloadPartFileResponse xmlns="http://tempuri.org/"><DownloadPartFileResult xmlns:a="http://schemas.datacontract.org/2004/07/KlanApi.Common" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><a:ErrorCode>0</a:ErrorCode><a:ErrorMessage i:nil="true"/><a:Data><xop:Include href="cid:http%3A%2F%2Ftempuri.org%2F1%2F634133419330914808" xmlns:xop="http://www.w3.org/2004/08/xop/include"/></a:Data></DownloadPartFileResult></DownloadPartFileResponse></s:Body></s:Envelope>'
        (joinedmsg, numreplaces) = join_attachment(id, envelope, payload)

        soapmsg = StringIO(joinedmsg)
        soaptree = ElementTree.parse(soapmsg)

        soapns = "http://schemas.xmlsoap.org/soap/envelope/"
        r = DownloadPartFileResult.from_xml(soaptree.getroot().find(
            "{%s}Body" % soapns).getchildren()[0].getchildren()[0])

        self.assertEquals(payload, r.Data)
Ejemplo n.º 9
0
Archivo: soap.py Proyecto: caot/soaplib
def from_soap(xml_string):
    '''
    Parses the xml string into the header and payload
    '''
    root, xmlids = ElementTree.XMLID(xml_string)
    if xmlids:
        resolve_hrefs(root, xmlids)
    body = None
    header = None

    # find the body and header elements
    for e in root.getchildren():
        name = e.tag.split('}')[-1].lower()
        if name == 'body':
            body = e
        elif name == 'header':
            header = e
    payload = None
    if len(body.getchildren()):
        payload = body.getchildren()[0]

    return payload, header
Ejemplo n.º 10
0
    def wsdl(self, url):
        '''
        This method generates and caches the wsdl for this object based
        on the soap methods designated by the soapmethod or soapdocument
        descriptors
        @param url the url that this service can be found at.  This must be
        passed in by the caller because this object has no notion of the
        server environment in which it runs.
        @returns the string of the wsdl
        '''
        if not self.__wsdl__ == None:
            # return the cached __wsdl__
            return self.__wsdl__
        url = url.replace('.wsdl', '')
        # otherwise build it
        serviceName = self.__class__.__name__.split('.')[-1]

        tns = self.__tns__
        methods = self.methods()
        hasCallbacks = self._hasCallbacks()

        nsmap = NamespaceLookup(tns, True)
        if hasCallbacks:
            nsmap.set('wsa',
                'http://schemas.xmlsoap.org/ws/2003/03/addressing')

        root = create_xml_element(
            "definitions", nsmap, 'http://schemas.xmlsoap.org/wsdl/')
        root.set('targetNamespace', tns)
        root.set('name', serviceName)

        types = create_xml_subelement(root, "types")

        self._add_schema(types, methods, nsmap)
        self._add_messages_for_methods(root, methods, nsmap)

        # add necessary async headers
        # WS-Addressing -> RelatesTo ReplyTo MessageID
        # callback porttype
        if hasCallbacks:
            wsaSchemaNode = create_xml_subelement(types, "schema")
            wsaSchemaNode.set("targetNamespace", tns+'Callback')
            wsaSchemaNode.set("xmlns", "http://www.w3.org/2001/XMLSchema")
            wsaSchemaNode.set("elementFormDefault", "qualified")

            importNode = create_xml_subelement(wsaSchemaNode, "import")
            importNode.set("namespace",
                "http://schemas.xmlsoap.org/ws/2003/03/addressing")
            importNode.set("schemaLocation",
                "http://schemas.xmlsoap.org/ws/2003/03/addressing/")


            reltMessage = create_xml_subelement(root, 'message')
            reltMessage.set('name', 'RelatesToHeader')
            reltPart = create_xml_subelement(reltMessage, 'part')
            reltPart.set('name', 'RelatesTo')
            reltPart.set('element', 'wsa:RelatesTo')

            replyMessage = create_xml_subelement(root, 'message')
            replyMessage.set('name', 'ReplyToHeader')
            replyPart = create_xml_subelement(replyMessage, 'part')
            replyPart.set('name', 'ReplyTo')
            replyPart.set('element', 'wsa:ReplyTo')

            idHeader = create_xml_subelement(root, 'message')
            idHeader.set('name', 'MessageIDHeader')
            idPart = create_xml_subelement(idHeader, 'part')
            idPart.set('name', 'MessageID')
            idPart.set('element', 'wsa:MessageID')

            # make portTypes
            callbackPortType = create_xml_subelement(root, 'portType')
            callbackPortType.set('name', '%sCallback' % serviceName)

            cbServiceName = '%sCallback' % serviceName
            cbService = create_xml_subelement(root, 'service')
            cbService.set('name', cbServiceName)
            cbWsdlPort = create_xml_subelement(cbService, 'port')
            cbWsdlPort.set('name', cbServiceName)
            cbWsdlPort.set('binding', 'tns:%s' % cbServiceName)
            cbAddr = create_xml_subelement(cbWsdlPort,
                nsmap.get('soap') + 'address')
            cbAddr.set('location', url)


        serviceName = self.__class__.__name__.split('.')[-1]
        portType = create_xml_subelement(root, 'portType')
        portType.set('name', serviceName)
        for method in methods:
            if method.isCallback:
                operation = create_xml_subelement(callbackPortType,
                    'operation')
            else:
                operation = create_xml_subelement(portType, 'operation')

            operation.set('name', method.name)
            params = []
            for name, param in method.inMessage.params:
                params.append(name)

            documentation = create_xml_subelement(operation, 'documentation')
            documentation.text = method.doc
            operation.set('parameterOrder', method.inMessage.typ)
            opInput = create_xml_subelement(operation, 'input')
            opInput.set('name', method.inMessage.typ)
            opInput.set('message', 'tns:%s' % method.inMessage.typ)

            if (len(method.outMessage.params) > 0 and
                not method.isCallback and not method.isAsync):
                opOutput = create_xml_subelement(operation, 'output')
                opOutput.set('name', method.outMessage.typ)
                opOutput.set('message', 'tns:%s' % method.outMessage.typ)

        # make partner link
        plink = create_xml_subelement(root,
            nsmap.get('plnk') + 'partnerLinkType')
        plink.set('name', serviceName)
        role = create_xml_subelement(plink,
            nsmap.get('plnk') + 'role')
        role.set('name', serviceName)
        plinkPortType = create_xml_subelement(role,
            nsmap.get('plnk') + 'portType')
        plinkPortType.set('name', 'tns:%s' % serviceName)

        if hasCallbacks:
            role = create_xml_subelement(plink, nsmap.get('plnk') + 'role')
            role.set('name', '%sCallback' % serviceName)
            plinkPortType = create_xml_subelement(role,
                nsmap.get('plnk') + 'portType')
            plinkPortType.set('name', 'tns:%sCallback' % serviceName)

        self._add_bindings_for_methods(root, serviceName, methods, nsmap)

        service = create_xml_subelement(root, 'service')
        service.set('name', serviceName)
        wsdlPort = create_xml_subelement(service, 'port')
        wsdlPort.set('name', serviceName)
        wsdlPort.set('binding', 'tns:%s' % serviceName)
        addr = create_xml_subelement(wsdlPort, nsmap.get('soap') + 'address')
        addr.set('location', url)

        wsdl = ElementTree.tostring(root)
        wsdl = "<?xml version='1.0' encoding='utf-8' ?>%s" % (wsdl)

        #cache the wsdl for next time
        self.__wsdl__ = wsdl
        return self.__wsdl__
Ejemplo n.º 11
0
def apply_mtom(headers, envelope, params, paramvals):
    '''
    Apply MTOM to a SOAP envelope, separating attachments into a
    MIME multipart message.

    References:
    XOP     http://www.w3.org/TR/xop10/
    MTOM    http://www.w3.org/TR/soap12-mtom/
            http://www.w3.org/Submission/soap11mtom10/

    @param headers   Headers dictionary of the SOAP message that would
                     originally be sent.
    @param envelope  SOAP envelope string that would have originally been sent.
    @param params    params attribute from the Message object used for the SOAP
    @param paramvals values of the params, passed to Message.to_xml
    @return          tuple of length 2 with dictionary of headers and
                     string of body that can be sent with HTTPConnection
    '''

    # grab the XML element of the message in the SOAP body
    soapmsg = StringIO(envelope)
    soaptree = ElementTree.parse(soapmsg)
    soapns = soaptree.getroot().tag.split('}')[0].strip('{')
    soapbody = soaptree.getroot().find("{%s}Body" % soapns)
    message = None
    for child in list(soapbody):
        if child.tag != "%sFault" % (soapns, ):
            message = child
            break

    # Get additional parameters from original Content-Type
    ctarray = []
    for n, v in headers.items():
        if n.lower() == 'content-type':
            ctarray = v.split(';')
            break
    roottype = ctarray[0].strip()
    rootparams = {}
    for ctparam in ctarray[1:]:
        n, v = ctparam.strip().split('=')
        rootparams[n] = v.strip("\"'")

    # Set up initial MIME parts
    mtompkg = MIMEMultipart('related',
        boundary='?//<><>soaplib_MIME_boundary<>')
    rootpkg = None
    try:
        rootpkg = MIMEApplication(envelope, 'xop+xml', encode_7or8bit)
    except NameError:
        rootpkg = MIMENonMultipart("application", "xop+xml")
        rootpkg.set_payload(envelope)
        encode_7or8bit(rootpkg)

    # Set up multipart headers.
    del(mtompkg['mime-version'])
    mtompkg.set_param('start-info', roottype)
    mtompkg.set_param('start', '<soaplibEnvelope>')
    if 'SOAPAction' in headers:
        mtompkg.add_header('SOAPAction', headers.get('SOAPAction'))

    # Set up root SOAP part headers.
    del(rootpkg['mime-version'])
    rootpkg.add_header('Content-ID', '<soaplibEnvelope>')
    for n, v in rootparams.items():
        rootpkg.set_param(n, v)
    rootpkg.set_param('type', roottype)

    mtompkg.attach(rootpkg)

    # Extract attachments from SOAP envelope.
    for i in range(len(params)):
        name, typ = params[i]
        if typ == Attachment:
            id = "soaplibAttachment_%s" % (len(mtompkg.get_payload()), )
            param = message[i]
            param.text = ""
            incl = create_xml_subelement(param,
                "{http://www.w3.org/2004/08/xop/include}Include")
            incl.attrib["href"] = "cid:%s" % id
            if paramvals[i].fileName and not paramvals[i].data:
                paramvals[i].load_from_file()
            data = paramvals[i].data
            attachment = None
            try:
                attachment = MIMEApplication(data, _encoder=encode_7or8bit)
            except NameError:
                attachment = MIMENonMultipart("application", "octet-stream")
                attachment.set_payload(data)
                encode_7or8bit(attachment)
            del(attachment['mime-version'])
            attachment.add_header('Content-ID', '<%s>' % (id, ))
            mtompkg.attach(attachment)

    # Update SOAP envelope.
    soapmsg.close()
    soapmsg = StringIO()
    soaptree.write(soapmsg)
    rootpkg.set_payload(soapmsg.getvalue())
    soapmsg.close()

    # extract body string from MIMEMultipart message
    bound = '--%s' % (mtompkg.get_boundary(), )
    marray = mtompkg.as_string().split(bound)
    mtombody = bound
    mtombody += bound.join(marray[1:])

    # set Content-Length
    mtompkg.add_header("Content-Length", str(len(mtombody)))

    # extract dictionary of headers from MIMEMultipart message
    mtomheaders = {}
    for name, value in mtompkg.items():
        mtomheaders[name] = value

    if len(mtompkg.get_payload()) <= 1:
        return (headers, envelope)

    return (mtomheaders, mtombody)
Ejemplo n.º 12
0
Archivo: soap.py Proyecto: caot/soaplib
def apply_mtom(headers, envelope, params, paramvals):
    '''
    Apply MTOM to a SOAP envelope, separating attachments into a
    MIME multipart message.

    References:
    XOP     http://www.w3.org/TR/xop10/
    MTOM    http://www.w3.org/TR/soap12-mtom/
            http://www.w3.org/Submission/soap11mtom10/

    @param headers   Headers dictionary of the SOAP message that would
                     originally be sent.
    @param envelope  SOAP envelope string that would have originally been sent.
    @param params    params attribute from the Message object used for the SOAP
    @param paramvals values of the params, passed to Message.to_xml
    @return          tuple of length 2 with dictionary of headers and
                     string of body that can be sent with HTTPConnection
    '''

    # grab the XML element of the message in the SOAP body
    soapmsg = StringIO(envelope)
    soaptree = ElementTree.parse(soapmsg)
    soapns = soaptree.getroot().tag.split('}')[0].strip('{')
    soapbody = soaptree.getroot().find("{%s}Body" % soapns)
    message = None
    for child in list(soapbody):
        if child.tag != "%sFault" % (soapns, ):
            message = child
            break

    # Get additional parameters from original Content-Type
    ctarray = []
    for n, v in headers.items():
        if n.lower() == 'content-type':
            ctarray = v.split(';')
            break
    roottype = ctarray[0].strip()
    rootparams = {}
    for ctparam in ctarray[1:]:
        n, v = ctparam.strip().split('=')
        rootparams[n] = v.strip("\"'")

    # Set up initial MIME parts
    mtompkg = MIMEMultipart('related',
                            boundary='?//<><>soaplib_MIME_boundary<>')
    rootpkg = None
    try:
        rootpkg = MIMEApplication(envelope, 'xop+xml', encode_7or8bit)
    except NameError:
        rootpkg = MIMENonMultipart("application", "xop+xml")
        rootpkg.set_payload(envelope)
        encode_7or8bit(rootpkg)

    # Set up multipart headers.
    del (mtompkg['mime-version'])
    mtompkg.set_param('start-info', roottype)
    mtompkg.set_param('start', '<soaplibEnvelope>')
    if 'SOAPAction' in headers:
        mtompkg.add_header('SOAPAction', headers.get('SOAPAction'))

    # Set up root SOAP part headers.
    del (rootpkg['mime-version'])
    rootpkg.add_header('Content-ID', '<soaplibEnvelope>')
    for n, v in rootparams.items():
        rootpkg.set_param(n, v)
    rootpkg.set_param('type', roottype)

    mtompkg.attach(rootpkg)

    # Extract attachments from SOAP envelope.
    for i in range(len(params)):
        name, typ = params[i]
        if typ == Attachment:
            id = "soaplibAttachment_%s" % (len(mtompkg.get_payload()), )
            param = message[i]
            param.text = ""
            incl = create_xml_subelement(
                param, "{http://www.w3.org/2004/08/xop/include}Include")
            incl.attrib["href"] = "cid:%s" % id
            if paramvals[i].fileName and not paramvals[i].data:
                paramvals[i].load_from_file()
            data = paramvals[i].data
            attachment = None
            try:
                attachment = MIMEApplication(data, _encoder=encode_7or8bit)
            except NameError:
                attachment = MIMENonMultipart("application", "octet-stream")
                attachment.set_payload(data)
                encode_7or8bit(attachment)
            del (attachment['mime-version'])
            attachment.add_header('Content-ID', '<%s>' % (id, ))
            mtompkg.attach(attachment)

    # Update SOAP envelope.
    soapmsg.close()
    soapmsg = StringIO()
    soaptree.write(soapmsg)
    rootpkg.set_payload(soapmsg.getvalue())
    soapmsg.close()

    # extract body string from MIMEMultipart message
    bound = '--%s' % (mtompkg.get_boundary(), )
    marray = mtompkg.as_string().split(bound)
    mtombody = bound
    mtombody += bound.join(marray[1:])

    # set Content-Length
    mtompkg.add_header("Content-Length", str(len(mtombody)))

    # extract dictionary of headers from MIMEMultipart message
    mtomheaders = {}
    for name, value in mtompkg.items():
        mtomheaders[name] = value

    if len(mtompkg.get_payload()) <= 1:
        return (headers, envelope)

    return (mtomheaders, mtombody)
Ejemplo n.º 13
0
    def wsdl(self, url):
        '''
        This method generates and caches the wsdl for this object based
        on the soap methods designated by the soapmethod or soapdocument
        descriptors
        @param url the url that this service can be found at.  This must be
        passed in by the caller because this object has no notion of the
        server environment in which it runs.
        @returns the string of the wsdl
        '''
        if not self.__wsdl__ == None:
            # return the cached __wsdl__
            return self.__wsdl__
        url = url.replace('.wsdl', '')
        # otherwise build it
        serviceName = self.__class__.__name__.split('.')[-1]

        tns = self.__tns__
        methods = self.methods()
        hasCallbacks = self._hasCallbacks()

        nsmap = NamespaceLookup(tns, True)
        if hasCallbacks:
            nsmap.set('wsa',
                'http://schemas.xmlsoap.org/ws/2003/03/addressing')

        root = create_xml_element(
            "definitions", nsmap, 'http://schemas.xmlsoap.org/wsdl/')
        root.set('targetNamespace', tns)
        root.set('name', serviceName)

        types = create_xml_subelement(root, "types")

        self._add_schema(types, methods, nsmap)
        self._add_messages_for_methods(root, methods, nsmap)

        # add necessary async headers
        # WS-Addressing -> RelatesTo ReplyTo MessageID
        # callback porttype
        if hasCallbacks:
            wsaSchemaNode = create_xml_subelement(types, "schema")
            wsaSchemaNode.set("targetNamespace", tns+'Callback')
            wsaSchemaNode.set("xmlns", "http://www.w3.org/2001/XMLSchema")
            wsaSchemaNode.set("elementFormDefault", "qualified")

            importNode = create_xml_subelement(wsaSchemaNode, "import")
            importNode.set("namespace",
                "http://schemas.xmlsoap.org/ws/2003/03/addressing")
            importNode.set("schemaLocation",
                "http://schemas.xmlsoap.org/ws/2003/03/addressing/")


            reltMessage = create_xml_subelement(root, 'message')
            reltMessage.set('name', 'RelatesToHeader')
            reltPart = create_xml_subelement(reltMessage, 'part')
            reltPart.set('name', 'RelatesTo')
            reltPart.set('element', 'wsa:RelatesTo')

            replyMessage = create_xml_subelement(root, 'message')
            replyMessage.set('name', 'ReplyToHeader')
            replyPart = create_xml_subelement(replyMessage, 'part')
            replyPart.set('name', 'ReplyTo')
            replyPart.set('element', 'wsa:ReplyTo')

            idHeader = create_xml_subelement(root, 'message')
            idHeader.set('name', 'MessageIDHeader')
            idPart = create_xml_subelement(idHeader, 'part')
            idPart.set('name', 'MessageID')
            idPart.set('element', 'wsa:MessageID')

            # make portTypes
            callbackPortType = create_xml_subelement(root, 'portType')
            callbackPortType.set('name', '%sCallback' % serviceName)

            cbServiceName = '%sCallback' % serviceName
            cbService = create_xml_subelement(root, 'service')
            cbService.set('name', cbServiceName)
            cbWsdlPort = create_xml_subelement(cbService, 'port')
            cbWsdlPort.set('name', cbServiceName)
            cbWsdlPort.set('binding', 'tns:%s' % cbServiceName)
            cbAddr = create_xml_subelement(cbWsdlPort,
                nsmap.get('soap') + 'address')
            cbAddr.set('location', url)


        serviceName = self.__class__.__name__.split('.')[-1]
        portType = create_xml_subelement(root, 'portType')
        portType.set('name', serviceName)
        for method in methods:
            if method.isCallback:
                operation = create_xml_subelement(callbackPortType,
                    'operation')
            else:
                operation = create_xml_subelement(portType, 'operation')

            operation.set('name', method.name)
            params = []
            for name, param in method.inMessage.params:
                params.append(name)

            documentation = create_xml_subelement(operation, 'documentation')
            documentation.text = method.doc
            operation.set('parameterOrder', method.inMessage.typ)
            opInput = create_xml_subelement(operation, 'input')
            opInput.set('name', method.inMessage.typ)
            opInput.set('message', 'tns:%s' % method.inMessage.typ)

            if (len(method.outMessage.params) > 0 and
                not method.isCallback and not method.isAsync):
                opOutput = create_xml_subelement(operation, 'output')
                opOutput.set('name', method.outMessage.typ)
                opOutput.set('message', 'tns:%s' % method.outMessage.typ)

        self._add_bindings_for_methods(root, serviceName, methods, nsmap)

        service = create_xml_subelement(root, 'service')
        service.set('name', serviceName)
        wsdlPort = create_xml_subelement(service, 'port')
        wsdlPort.set('name', serviceName)
        wsdlPort.set('binding', 'tns:%s' % serviceName)
        addr = create_xml_subelement(wsdlPort, nsmap.get('soap') + 'address')
        addr.set('location', url)

        wsdl = ElementTree.tostring(root)
        wsdl = "<?xml version='1.0' encoding='utf-8' ?>%s" % (wsdl)

        #cache the wsdl for next time
        self.__wsdl__ = wsdl
        return self.__wsdl__
Ejemplo n.º 14
0
    def wsdl(self, url):
        """
        This method generates and caches the wsdl for this object based
        on the soap methods designated by the soapmethod or soapdocument
        descriptors
        @param url the url that this service can be found at.  This must be
        passed in by the caller because this object has no notion of the
        server environment in which it runs.
        @returns the string of the wsdl
        """
        if not self.__wsdl__ == None:
            # return the cached __wsdl__
            return self.__wsdl__
        url = url.replace(".wsdl", "")
        # otherwise build it
        serviceName = self.__class__.__name__.split(".")[-1]

        tns = self.__tns__
        methods = self.methods()
        hasCallbacks = self._hasCallbacks()

        nsmap = NamespaceLookup(tns, True)
        if hasCallbacks:
            nsmap.set("wsa", "http://schemas.xmlsoap.org/ws/2003/03/addressing")

        root = create_xml_element("definitions", nsmap, "http://schemas.xmlsoap.org/wsdl/")
        root.set("targetNamespace", tns)
        root.set("name", serviceName)

        types = create_xml_subelement(root, "types")

        self._add_schema(types, methods, nsmap)
        self._add_messages_for_methods(root, methods, nsmap)

        # add necessary async headers
        # WS-Addressing -> RelatesTo ReplyTo MessageID
        # callback porttype
        if hasCallbacks:
            wsaSchemaNode = create_xml_subelement(types, "schema")
            wsaSchemaNode.set("targetNamespace", tns + "Callback")
            wsaSchemaNode.set("xmlns", "http://www.w3.org/2001/XMLSchema")

            importNode = create_xml_subelement(wsaSchemaNode, "import")
            importNode.set("namespace", "http://schemas.xmlsoap.org/ws/2003/03/addressing")
            importNode.set("schemaLocation", "http://schemas.xmlsoap.org/ws/2003/03/addressing/")

            reltMessage = create_xml_subelement(root, "message")
            reltMessage.set("name", "RelatesToHeader")
            reltPart = create_xml_subelement(reltMessage, "part")
            reltPart.set("name", "RelatesTo")
            reltPart.set("element", "wsa:RelatesTo")

            replyMessage = create_xml_subelement(root, "message")
            replyMessage.set("name", "ReplyToHeader")
            replyPart = create_xml_subelement(replyMessage, "part")
            replyPart.set("name", "ReplyTo")
            replyPart.set("element", "wsa:ReplyTo")

            idHeader = create_xml_subelement(root, "message")
            idHeader.set("name", "MessageIDHeader")
            idPart = create_xml_subelement(idHeader, "part")
            idPart.set("name", "MessageID")
            idPart.set("element", "wsa:MessageID")

            # make portTypes
            callbackPortType = create_xml_subelement(root, "portType")
            callbackPortType.set("name", "%sCallback" % serviceName)

            cbServiceName = "%sCallback" % serviceName
            cbService = create_xml_subelement(root, "service")
            cbService.set("name", cbServiceName)
            cbWsdlPort = create_xml_subelement(cbService, "port")
            cbWsdlPort.set("name", cbServiceName)
            cbWsdlPort.set("binding", "tns:%s" % cbServiceName)
            cbAddr = create_xml_subelement(cbWsdlPort, nsmap.get("soap") + "address")
            cbAddr.set("location", url)

        serviceName = self.__class__.__name__.split(".")[-1]
        portType = create_xml_subelement(root, "portType")
        portType.set("name", serviceName)
        for method in methods:
            if method.isCallback:
                operation = create_xml_subelement(callbackPortType, "operation")
            else:
                operation = create_xml_subelement(portType, "operation")

            operation.set("name", method.name)
            params = []
            for name, param in method.inMessage.params:
                params.append(name)

            documentation = create_xml_subelement(operation, "documentation")
            documentation.text = method.doc
            operation.set("parameterOrder", method.inMessage.typ)
            opInput = create_xml_subelement(operation, "input")
            opInput.set("name", method.inMessage.typ)
            opInput.set("message", "tns:%s" % method.inMessage.typ)

            if method.outMessage.params != None and not method.isCallback and not method.isAsync:
                opOutput = create_xml_subelement(operation, "output")
                opOutput.set("name", method.outMessage.typ)
                opOutput.set("message", "tns:%s" % method.outMessage.typ)

        # make partner link
        plink = create_xml_subelement(root, nsmap.get("plnk") + "partnerLinkType")
        plink.set("name", serviceName)
        role = create_xml_subelement(plink, nsmap.get("plnk") + "role")
        role.set("name", serviceName)
        plinkPortType = create_xml_subelement(role, nsmap.get("plnk") + "portType")
        plinkPortType.set("name", "tns:%s" % serviceName)

        if hasCallbacks:
            role = create_xml_subelement(plink, nsmap.get("plnk") + "role")
            role.set("name", "%sCallback" % serviceName)
            plinkPortType = create_xml_subelement(role, nsmap.get("plnk") + "portType")
            plinkPortType.set("name", "tns:%sCallback" % serviceName)

        self._add_bindings_for_methods(root, serviceName, methods, nsmap)

        service = create_xml_subelement(root, "service")
        service.set("name", serviceName)
        wsdlPort = create_xml_subelement(service, "port")
        wsdlPort.set("name", serviceName)
        wsdlPort.set("binding", "tns:%s" % serviceName)
        addr = create_xml_subelement(wsdlPort, nsmap.get("soap") + "address")
        addr.set("location", url)

        wsdl = ElementTree.tostring(root)
        wsdl = "<?xml version='1.0' encoding='utf-8' ?>%s" % (wsdl)

        # cache the wsdl for next time
        self.__wsdl__ = wsdl
        return self.__wsdl__
Ejemplo n.º 15
0
            envelope = make_soap_envelope(results, tns=self.__tns__)
            resp = ElementTree.tostring(envelope, encoding=string_encoding)

            RESPONSE.setHeader('Content-Type', 'text/xml')
            return resp

        except Exception, e:
            faultstring = str(e)
            if methodname:
                faultcode = '%sFault' % methodname
            else:
                faultcode = 'Server'

            fault = make_soap_fault(faultstring, faultcode, detail=None)
            resp = ElementTree.tostring(fault, encoding=string_encoding)

            RESPONSE.setStatus('InternalServerError', reason=faultstring)
            RESPONSE.setHeader('Content-Type', 'text/xml')
            return resp


class ISOAPException(IException):
    pass


class SOAPException(Exception):
    """Base exception class for all derived exceptions for SOAP"""

    implements(ISOAPException)