Exemplo n.º 1
0
    def check_any_nill(self):
        result = ['23', {'a' : None, 'b': 5}]
        soap = str(SoapWriter().serialize(result, TC.Any(pname="NilRequest", nillable=True, aslist=True)))

        ps = ParsedSoap(soap)
        tc = TC.Any(nillable=True)
        pyobj = ps.Parse(tc)
Exemplo n.º 2
0
    def test_local_serialize_schema(self):
        from ZSI import SoapWriter
        from ZSI import _child_elements
        from xml.dom.ext.reader import PyExpat
        msg = self.client_module.DSQueryRegistrySoapOut()
        msg.DSQueryRegistryResult = msg.new_DSQueryRegistryResult()
        msg.DSQueryRegistryResult.Any = 'hi'

        input = open('wsdl/nvo-admin.wsdl').read()
        reader = PyExpat.Reader()
        dom = reader.fromString(input)

        dnode = _child_elements(dom)[0]
        tnode = _child_elements(dnode)[0]
        snode = _child_elements(tnode)[0]

        msg.DSQueryRegistryResult.Schema = snode

        sw = SoapWriter()
        sw.serialize(msg)
        soap = str(sw)
        print(soap)

        ps = ParsedSoap(soap)
        pyobj = ps.Parse(msg.typecode)
        self.assertEqual(pyobj.DSQueryRegistryResult.Any,
                         msg.DSQueryRegistryResult.Any)
        self.assertTrue(_is_element(pyobj.DSQueryRegistryResult.Schema))
        print(_get_element_nsuri_name(pyobj.DSQueryRegistryResult.Schema))
        self.assertEqual(
            _get_element_nsuri_name(pyobj.DSQueryRegistryResult.Schema),
            ('http://www.w3.org/2001/XMLSchema', 'schema'))
Exemplo n.º 3
0
    def test_local_parse_ItemSearch(self):
        msg = self.client_module.ItemSearchResponseMsg()
        ps = ParsedSoap(ItemSearchResponseMsg)
        response = ps.Parse(msg.typecode)
        response.OperationRequest.Arguments
        for i in response.OperationRequest.Arguments.Argument: 
             i.get_attribute_Name()
             i.get_attribute_Value()

        for i in response.OperationRequest.HTTPHeaders.Header or []:
             i.get_attribute_Name()
             i.get_attribute_Value()
             
        response.OperationRequest.RequestId
        response.OperationRequest.RequestProcessingTime
        for its in response.Items:
            self.assertTrue(its.TotalResults == 61, '')
            self.assertTrue(its.TotalPages == 7, '')
            for it in its.Item:
                it.ASIN; 
                it.Accessories; 
                #it.AlternateVersions; 
                it.BrowseNodes
                #it.Collections; 
                it.CustomerReviews ;it.DetailPageURL
                it.EditorialReviews; it.Errors; it.ImageSets; it.ItemAttributes
                it.LargeImage; it.ListmaniaLists; it.MediumImage; it.MerchantItemAttributes
                it.OfferSummary; it.Offers; 
                #it.ParentASIN; 
                it.SalesRank; it.SearchInside
                it.SimilarProducts; it.SmallImage; it.Subjects; it.Tracks;
Exemplo n.º 4
0
 def check_any_untyped_int(self):
     # from zsi developer's guide
     d = dict(value=12)
     d.update(NSDICT)
     xml = """<tns:i %(tns)s>12</tns:i>""" %NSDICT
     ps = ParsedSoap(xml, envelope=False)
     self.assertTrue(int(ps.Parse(TC.Any())) == 12)
Exemplo n.º 5
0
    def test_local_anyType(self):
        """rpc/lit, testing if <any/> lax content handling
        should get back dicts and strings 
        """
        ps = ParsedSoap(MSG)
        pyobj = ps.Parse(self.client_module.EventApproximatesSoapOut.typecode)

        any = {
            'PoolTotals': {
                'Pool': {
                    'Total': u'4117.66',
                    'ENumbers': None,
                    'JackpotNet': None
                }
            },
            'Approximates': {
                'Pool': {
                    'Win':
                    u'3.90,0.00,10.40,11.80,4.70,29.50,29.90,2.40,19.80,0.00',
                    'Place':
                    u'1.04,0.00,2.80,5.90,2.00,5.20,7.40,1.04,4.00,0.00'
                }
            }
        }

        self.failUnless(
            pyobj.EventApproximatesResult.Any == any,
            'Failed match:\n %s\n\n%s' %
            (pyobj.EventApproximatesResult.Any, any))
Exemplo n.º 6
0
 def check_any_typed_xsd_int(self):
     # from zsi developer's guide
     value = 12
     d = dict(value=value)
     d.update(NSDICT)
     xml = """<tns:i xsi:type="xsd:int" %(xsi)s %(soap)s %(tns)s %(xsd)s>%(value)d</tns:i>""" % d
     ps = ParsedSoap(xml, envelope=False)
     self.failUnless(ps.Parse(TC.Any()) == value)
Exemplo n.º 7
0
    def check_type_attribute_qname_in_default_ns(self):
        msg = """
<ns1:test xsi:type="int" xmlns:ns1="urn:vim25" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns="http://www.w3.org/2001/XMLSchema">
100
</ns1:test>"""
        ps = ParsedSoap(msg, envelope=False)
        pyobj = ps.Parse(TC.Integer(pname=("urn:vim25", "test")))
Exemplo n.º 8
0
 def check_any_typed_nonNegativeInteger(self):
     # from zsi developer's guide
     value = 12
     d = dict(value=value)
     d.update(NSDICT)
     xml = """<tns:i xsi:type="xsd:nonNegativeInteger" %(xsi)s %(soap)s %(tns)s %(xsd)s>%(value)d</tns:i>""" % d
     ps = ParsedSoap(xml, envelope=False)
     self.assertTrue(ps.Parse(TC.Any()) == value)
Exemplo n.º 9
0
    def check_element_in_default_ns(self):
        msg = """
<test xsi:type="myInt" xmlns="urn:vim25" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema">
100
</test>"""
        ps = ParsedSoap(msg, envelope=False)
        pyobj = ps.Parse(TC.AnyType(pname=("urn:vim25","test")))
        self.failUnless(pyobj == 100, 'failed to parse element in default ns')
Exemplo n.º 10
0
    def check_type_attribute_qname_in_default_ns(self):
        msg = """
<ns1:test xsi:type="ns1:myInt" xmlns:ns1="urn:vim25" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns="http://www.w3.org/2001/XMLSchema">
100
</ns1:test>"""
        ps = ParsedSoap(msg, envelope=False)
        pyobj = ps.Parse(TC.AnyType(pname=("urn:vim25","test")))
        self.failUnless(pyobj == 100, 'failed to parse type in default ns')
Exemplo n.º 11
0
 def check_parse_empty_string(self):
     # Empty String
     typecodes = list(TC.Any.parsemap.values())
     for tc in [c for c in list(TC.Any.parsemap.values()) if isinstance(c, TC.String)]:
         sw = SoapWriter()
         sw.serialize("", typecode=tc, typed=True)
         soap = str(sw)
         ps = ParsedSoap(soap)
         parsed = ps.Parse(TC.Any())
         self.assertEqual("", parsed)
Exemplo n.º 12
0
    def dispatch(self, req):
        path = req.uri[1:]
        if (path[-1] == "/"):
            path = path[:-1]

        if not configs.has_key(path):
            if req.method == "POST":
                self.send_fault(
                    Fault(Fault.Client,
                          "Unknown Database Path %s" % (repr(configs.keys()))),
                    req)
            else:
                # Construct simple table of contents page
                xml = ['<databases>']
                for k in configs:
                    xml.append("<database><path>%s</path></database>" % k)
                xml.append('</databases>')
                txt = ''.join(xml)
                self.send_xml(txt, req)
        else:
            xreq = None
            config = configs[path]
            if (req.method == "POST"):
                try:
                    data = req.read()
                    dstr = StringIO.StringIO(data)
                    ps = ParsedSoap(dstr, readerclass=reader)
                except Exception, e:
                    try:
                        self.send_fault(FaultFromException(e, 0), req)
                    except Exception, e:
                        self.send_fault(FaultFromException(e, 0), req)
                    return
                callname = ps.body_root.localName
                classname = callname[0].upper() + callname[1:]
                try:
                    try:
                        mod = SRW.protocolModules[ps.body_root.namespaceURI]
                    except KeyError:
                        log("%r -> %r" % (ps.body_root.namespaceURI, data))
                        self.send_fault(Fault(Fault.Client, 'Bad Namespace'),
                                        req)
                        return
                    config = config[ps.body_root.namespaceURI]
                    objType = getattr(mod, classname)
                    xreq = ps.Parse(objType)
                    xreq.configure(config)
                    xreq.calledAt = path
                    result = self.call(xreq)
                except AttributeError, err:
                    # result = self.processUnknownOperation(classname, err, config)
                    self.send_fault(
                        Fault(Fault.Client,
                              'Unknown Operation (%s)' % str(err)), req)
                    return
Exemplo n.º 13
0
    def check_any_compound(self):
        # from zsi developer's guide
        xml = """
<tns:foo %(tns)s %(xsi)s %(soap)s>
    <tns:i xsi:type="SOAP-ENC:integer">12</tns:i>
    <tns:name xsi:type="SOAP-ENC:string">Hello world</tns:name>
</tns:foo>""" % NSDICT

        ps = ParsedSoap(xml, envelope=False)
        self.assertTrue(ps.Parse(TC.Any()) == {'i': 12, 'name': 'Hello world'})
        self.assertTrue(ps.Parse(TC.Any(aslist=True)) == [12, 'Hello world'])
Exemplo n.º 14
0
 def check_parse_empty_all(self):
     # None
     skip = [TC.FPEnumeration, TC.Enumeration, TC.IEnumeration, TC.List, TC.Integer]
     for typeclass in [c for c in list(TC.__dict__.values()) if type(c) in [type,type] and not issubclass(c, TC.String) and issubclass(c, TC.SimpleType)]:
         if typeclass in skip: continue
         tc = typeclass()
         sw = SoapWriter()
         sw.serialize(None, typecode=tc, typed=True)
         soap = str(sw)
         ps = ParsedSoap(soap)
         parsed = ps.Parse(TC.Any())
         self.assertEqual(None, parsed)
Exemplo n.º 15
0
def soap_parse_ZSI(xml):
    ''' This function receives an XML SOAP and returns a dictionary. It is
    intended to be used inside a Node, this is why it raises a NodeParserError
    '''

    parsed_obj = None
    parsed_dict = dict()

    try:
        parsed_obj = ParsedSoap(xml)
        parsed_dict = parsed_obj.Parse(TC.Any())

    except Exception, e:
        print e
Exemplo n.º 16
0
 def check_empty_array(self):
     """Empty Array returned as list()
     """
     data = []
     s = str(SoapWriter().serialize(data, TC.Any(aslist=True)))
     p = ParsedSoap(s).Parse(TC.Any())
     self.assertTrue(data == p, 'expecting "%s", got "%s"' % (data, p))
Exemplo n.º 17
0
 def check_any_untyped_int(self):
     # from zsi developer's guide
     d = dict(value=12)
     d.update(NSDICT)
     xml = """<tns:i %(tns)s>12</tns:i>""" % NSDICT
     ps = ParsedSoap(xml, envelope=False)
     self.assertRaises(EvaluateException, ps.Parse, TC.Any())
Exemplo n.º 18
0
    def check_soapfault_faultcode(self):
        """ Typecode QName when default namespace is not declared, should
        specify the empty namespace.
        """
        msg = """<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
  xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<soapenv:Fault>
   <faultcode>ServerFaultCode</faultcode>
   <faultstring>Operation failed since VMware tools are not running in this virtual machine.</faultstring>
   <detail>
     <ToolsUnavailableFault xmlns="urn:vim2"/>
   </detail>
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>"""

        from ZSI import ParsedSoap, FaultFromFaultMessage
        ps = ParsedSoap(msg)
        fault = FaultFromFaultMessage(ps)
        self.failUnless(fault.code == ('', 'ServerFaultCode'),
                        'faultcode should be (namespace,name) tuple')
Exemplo n.º 19
0
 def check_empty_struct(self):
     """Empty Struct is None, maybe dict() makes more sense, but this
     is fairly hard to determine if not typed (which is the norm).
     """
     data = {}
     s = str(SoapWriter().serialize(data, TC.Any()))
     p = ParsedSoap(s).Parse(TC.Any())
     self.assertTrue(p == None, 'expecting "%s", got "%s"' % (None, p))
Exemplo n.º 20
0
    def test_local_anyType(self):
        """rpc/lit, testing if <any/> lax content handling
        should get back dicts and strings 
        """
        ps = ParsedSoap(MSG)
        pyobj = ps.Parse(self.client_module.EventApproximatesSoapOut.typecode)

        any = {
            'PoolTotals': {
                'Pool': {
                    'Total': '4117.66',
                    'ENumbers': None,
                    'JackpotNet': None
                }
            },
            'Approximates': {
                'Pool': {
                    'Win':
                    '3.90,0.00,10.40,11.80,4.70,29.50,29.90,2.40,19.80,0.00',
                    'Place':
                    '1.04,0.00,2.80,5.90,2.00,5.20,7.40,1.04,4.00,0.00'
                }
            }
        }

        self.assertTrue(
            pyobj.EventApproximatesResult.Any == any,
            'Failed match:\n %s\n\n%s' %
            (pyobj.EventApproximatesResult.Any, any))

        pyobj.EventApproximatesResult.Any = dict(
            pyobj.EventApproximatesResult.Any)
        sw = SoapWriter()
        sw.serialize(pyobj)
        print(str(sw))
        ps2 = ParsedSoap(str(sw))
        pyobj2 = ps.Parse(self.client_module.EventApproximatesSoapOut.typecode)
        print("EAR: ", pyobj2.EventApproximatesResult)
        print("Any: ", pyobj2.EventApproximatesResult.Any)

        self.assertTrue(
            pyobj.EventApproximatesResult.Any ==
            pyobj2.EventApproximatesResult.Any,
            'Failed match:\n %s\n\n%s' % (pyobj.EventApproximatesResult.Any,
                                          pyobj2.EventApproximatesResult.Any))
Exemplo n.º 21
0
 def check_any_dict_list_rpcenc(self):
     sw = SoapWriter()
     testObj = [{"a":1,"b":2}, {"d":4,"e":5}, {"f":{"x":9}, "g":[6,7.0]}]
     typecode = TC.Any(aslist=True)
     sw.serialize(testObj, typecode=typecode)
     xml = str(sw)
     ps = ParsedSoap(xml)
     result = TC.Any().parse(ps.body_root, ps)
     self.assertTrue(result == testObj)
Exemplo n.º 22
0
    def ReceiveSOAP(self, readerclass=None, **kw):
        '''Get back a SOAP message.
        '''
        if self.ps: return self.ps
        if not self.IsSOAP():
            raise TypeError('Response is "%s", not "text/xml"' %
                            self.reply_headers.type)
        if len(self.data) == 0:
            raise TypeError('Received empty response')

        self.ps = ParsedSoap(self.data,
                             readerclass=readerclass or self.readerclass,
                             encodingStyle=kw.get('encodingStyle'))

        if self.sig_handler is not None:
            self.sig_handler.verify(self.ps)

        return self.ps
Exemplo n.º 23
0
def AsCGI(nsdict={}, typesmodule=None, rpc=False, modules=None):
    '''Dispatch within a CGI script.
    '''
    if os.environ.get('REQUEST_METHOD') != 'POST':
        _CGISendFault(Fault(Fault.Client, 'Must use POST'))
        return
    ct = os.environ['CONTENT_TYPE']
    try:
        if ct.startswith('multipart/'):
            cid = resolvers.MIMEResolver(ct, sys.stdin)
            xml = cid.GetSOAPPart()
            ps = ParsedSoap(xml, resolver=cid.Resolve)
        else:
            length = int(os.environ['CONTENT_LENGTH'])
            ps = ParsedSoap(sys.stdin.read(length))
    except ParseException as e:
        _CGISendFault(FaultFromZSIException(e))
        return
    _Dispatch(ps, modules, _CGISendXML, _CGISendFault, nsdict=nsdict,
              typesmodule=typesmodule, rpc=rpc)
Exemplo n.º 24
0
    def test_local_NoMessagePart(self):
        ## msg = self.client_module.HelloRequest()
        msg = None
        rsp = self.client_module.HelloResponse()

        # Core functionality required
        s = SoapWriter()
        xml = str(s)

        print xml

        # Core functionality required
        ps = ParsedSoap(xml)

        self.failUnless(ps.body.childNodes == 0, "Empty Body expected: " + ps.body.childNodes)
        self.failUnless(ps.body_root == None, "Body root should be None: " + ps.body_root)

        pyobj = ps.Parse(None)

        self.failUnless(pyobj == None, "pyobj should be None: " + pyobj)
Exemplo n.º 25
0
def AsJonPy(request=None, modules=None, **kw):
    '''Dispatch within a jonpy CGI/FastCGI script.
    '''

    kw['request'] = request
    if request.environ.get('REQUEST_METHOD') != 'POST':
        _JonPySendFault(Fault(Fault.Client, 'Must use POST'), **kw)
        return
    ct = request.environ['CONTENT_TYPE']
    try:
        if ct.startswith('multipart/'):
            cid = resolvers.MIMEResolver(ct, request.stdin)
            xml = cid.GetSOAPPart()
            ps = ParsedSoap(xml, resolver=cid.Resolve)
        else:
            length = int(request.environ['CONTENT_LENGTH'])
            ps = ParsedSoap(request.stdin.read(length))
    except ParseException as e:
        _JonPySendFault(FaultFromZSIException(e), **kw)
        return
    _Dispatch(ps, modules, _JonPySendXML, _JonPySendFault, **kw)
Exemplo n.º 26
0
    def do_POST(self):
        '''The POST command.
        '''
        try:
            ct = self.headers['content-type']
            if ct.startswith('multipart/'):
                cid = resolvers.MIMEResolver(ct, self.rfile)
                xml = cid.GetSOAPPart()
                ps = ParsedSoap(xml, resolver=cid.Resolve)
            else:
                length = int(self.headers['content-length'])
                ps = ParsedSoap(self.rfile.read(length))
        except ParseException as e:
            self.send_fault(FaultFromZSIException(e))
            return
        except Exception as e:
            # Faulted while processing; assume it's in the header.
            self.send_fault(FaultFromException(e, 1, sys.exc_info()[2]))
            return

        _Dispatch(ps, self.server.modules, self.send_xml, self.send_fault,
                  docstyle=self.server.docstyle, nsdict=self.server.nsdict,
                  typesmodule=self.server.typesmodule, rpc=self.server.rpc)
    def do_POST(self):
        soapAction = self.headers.getheader('SOAPAction')
        post = self.path
        if not post:
            raise PostNotSpecified('HTTP POST not specified in request')
        if soapAction:
            soapAction = soapAction.strip('\'"')
            #Forzado porque SAP no lo envía bien.
            soapAction = "http://PdfUtils.csi.org/merge2Pdfs"
        post = post.strip('\'"')
        try:
            ct = self.headers['content-type']
            if ct.startswith('multipart/'):
                cid = resolvers.MIMEResolver(ct, self.rfile)
                xml = cid.GetSOAPPart()
                ps = ParsedSoap(xml, resolver=cid.Resolve)
            else:
                length = int(self.headers['content-length'])
                xml = self.rfile.read(length)
                ps = ParsedSoap(xml)

        except ParseException, e:
            self.send_fault(FaultFromZSIException(e))
Exemplo n.º 28
0
    def check_builtins(self):
        myInt,myLong,myStr,myDate,myFloat = 123,2147483648,\
            "hello", time.gmtime(), 1.0001
        orig = [myInt, myLong, myStr, myDate, myFloat]

        sw = SoapWriter()
        sw.serialize(orig, typecode=TC.Any(pname="builtins", aslist=True))

        ps = ParsedSoap(str(sw))
        parsed = ps.Parse(TC.Any())
        self.assertEqual(len(orig), len(parsed))

        self.assertEqual(myInt, parsed[0])
        self.assertEqual(myLong, parsed[1])
        self.assertEqual(myStr, parsed[2])
        self.assertEqual(myDate[0:6], parsed[3][0:6])
        self.assertEqual(myFloat, parsed[4])

        self.assertEqual(type(myInt), type(parsed[0]))
        self.assertEqual(type(myLong), type(parsed[1]))
        self.assertEqual(type(myStr), type(parsed[2]))
        self.assertEqual(tuple, type(parsed[3]))
        self.assertEqual(type(myFloat), type(parsed[4]))
Exemplo n.º 29
0
    def checkt7(self):
        ps = ParsedSoap(text)

        tcdict = TC.Apache.Map('c-gensym1')
        tclist = TC.Apache.Map('c-gensym1', aslist=1)

        d = tcdict.parse(ps.body_root, ps)
        self.assertEqual(d, {u'a': 123, '\x00\x01': 456})
        #print 'as dictionary\n', d

        l = tclist.parse(ps.body_root, ps)
        self.assertEqual(l, [('\x00\x01', 456), (u'a', 123)])
        #print '\n', '=' * 30
        #print 'as list\n', l

        #print '\n', '=' * 30
        sw = SoapWriter()
        sw.serialize(d, tcdict)
        #print >>sys.stdout, sw

        #print '\n', '=' * 30
        sw = SoapWriter()
        sw.serialize(l, tclist)
Exemplo n.º 30
0
class _Binding:
    '''Object that represents a binding (connection) to a SOAP server.
    Once the binding is created, various ways of sending and
    receiving SOAP messages are available.
    '''
    defaultHttpTransport = httplib.HTTPConnection
    defaultHttpsTransport = httplib.HTTPSConnection
    logger = _GetLogger('ZSI.client.Binding')

    def __init__(self,
                 nsdict=None,
                 transport=None,
                 url=None,
                 tracefile=None,
                 readerclass=None,
                 writerclass=None,
                 soapaction='',
                 wsAddressURI=None,
                 sig_handler=None,
                 transdict=None,
                 **kw):
        '''Initialize.
        Keyword arguments include:
            transport -- default use HTTPConnection. 
            transdict -- dict of values to pass to transport.
            url -- URL of resource, POST is path 
            soapaction -- value of SOAPAction header
            auth -- (type, name, password) triplet; default is unauth
            nsdict -- namespace entries to add
            tracefile -- file to dump packet traces
            cert_file, key_file -- SSL data (q.v.)
            readerclass -- DOM reader class
            writerclass -- DOM writer class, implements MessageInterface
            wsAddressURI -- namespaceURI of WS-Address to use.  By default 
            it's not used.
            sig_handler -- XML Signature handler, must sign and verify.
            endPointReference -- optional Endpoint Reference.
        '''
        self.data = None
        self.ps = None
        self.user_headers = []
        self.nsdict = nsdict or {}
        self.transport = transport
        self.transdict = transdict or {}
        self.url = url
        self.trace = tracefile
        self.readerclass = readerclass
        self.writerclass = writerclass
        self.soapaction = soapaction
        self.wsAddressURI = wsAddressURI
        self.sig_handler = sig_handler
        self.address = None
        self.endPointReference = kw.get('endPointReference', None)
        self.cookies = Cookie.SimpleCookie()
        self.http_callbacks = {}

        if kw.has_key('auth'):
            self.SetAuth(*kw['auth'])
        else:
            self.SetAuth(AUTH.none)

    def SetAuth(self, style, user=None, password=None):
        '''Change auth style, return object to user.
        '''
        self.auth_style, self.auth_user, self.auth_pass = \
            style, user, password
        return self

    def SetURL(self, url):
        '''Set the URL we post to.
        '''
        self.url = url
        return self

    def ResetHeaders(self):
        '''Empty the list of additional headers.
        '''
        self.user_headers = []
        return self

    def ResetCookies(self):
        '''Empty the list of cookies.
        '''
        self.cookies = Cookie.SimpleCookie()

    def AddHeader(self, header, value):
        '''Add a header to send.
        '''
        self.user_headers.append((header, value))
        return self

    def __addcookies(self):
        '''Add cookies from self.cookies to request in self.h
        '''
        for cname, morsel in self.cookies.items():
            attrs = []
            value = morsel.get('version', '')
            if value != '' and value != '0':
                attrs.append('$Version=%s' % value)
            attrs.append('%s=%s' % (cname, morsel.coded_value))
            value = morsel.get('path')
            if value:
                attrs.append('$Path=%s' % value)
            value = morsel.get('domain')
            if value:
                attrs.append('$Domain=%s' % value)
            self.h.putheader('Cookie', "; ".join(attrs))

    def RPC(self, url, opname, obj, replytype=None, **kw):
        '''Send a request, return the reply.  See Send() and Recieve()
        docstrings for details.
        '''
        self.Send(url, opname, obj, **kw)
        return self.Receive(replytype, **kw)

    def Send(self,
             url,
             opname,
             obj,
             nsdict={},
             soapaction=None,
             wsaction=None,
             endPointReference=None,
             soapheaders=(),
             **kw):
        '''Send a message.  If url is None, use the value from the
        constructor (else error). obj is the object (data) to send.
        Data may be described with a requesttypecode keyword, the default 
        is the class's typecode (if there is one), else Any.

        Try to serialize as a Struct, if this is not possible serialize an Array.  If 
        data is a sequence of built-in python data types, it will be serialized as an
        Array, unless requesttypecode is specified.

        arguments:
            url -- 
            opname -- struct wrapper
            obj -- python instance

        key word arguments:
            nsdict -- 
            soapaction --
            wsaction -- WS-Address Action, goes in SOAP Header.
            endPointReference --  set by calling party, must be an 
                EndPointReference type instance.
            soapheaders -- list of pyobj, typically w/typecode attribute.
                serialized in the SOAP:Header.
            requesttypecode -- 

        '''
        url = url or self.url
        endPointReference = endPointReference or self.endPointReference

        # Serialize the object.
        d = {}
        d.update(self.nsdict)
        d.update(nsdict)

        sw = SoapWriter(
            nsdict=d,
            header=True,
            outputclass=self.writerclass,
            encodingStyle=kw.get('encodingStyle'),
        )

        requesttypecode = kw.get('requesttypecode')
        if kw.has_key('_args'):  #NamedParamBinding
            tc = requesttypecode or TC.Any(pname=opname, aslist=False)
            sw.serialize(kw['_args'], tc)
        elif not requesttypecode:
            tc = getattr(obj, 'typecode', None) or TC.Any(pname=opname,
                                                          aslist=False)
            try:
                if type(obj) in _seqtypes:
                    obj = dict(map(lambda i: (i.typecode.pname, i), obj))
            except AttributeError:
                # can't do anything but serialize this in a SOAP:Array
                tc = TC.Any(pname=opname, aslist=True)
            else:
                tc = TC.Any(pname=opname, aslist=False)

            sw.serialize(obj, tc)
        else:
            sw.serialize(obj, requesttypecode)

        for i in soapheaders:
            sw.serialize_header(i)

        #
        # Determine the SOAP auth element.  SOAP:Header element
        if self.auth_style & AUTH.zsibasic:
            sw.serialize_header(_AuthHeader(self.auth_user, self.auth_pass),
                                _AuthHeader.typecode)

        #
        # Serialize WS-Address
        if self.wsAddressURI is not None:
            if self.soapaction and wsaction.strip('\'"') != self.soapaction:
                raise WSActionException, 'soapAction(%s) and WS-Action(%s) must match'\
                    %(self.soapaction,wsaction)

            self.address = Address(url, self.wsAddressURI)
            self.address.setRequest(endPointReference, wsaction)
            self.address.serialize(sw)

        #
        # WS-Security Signature Handler
        if self.sig_handler is not None:
            self.sig_handler.sign(sw)

        scheme, netloc, path, nil, nil, nil = urlparse.urlparse(url)
        transport = self.transport
        if transport is None and url is not None:
            if scheme == 'https':
                transport = self.defaultHttpsTransport
            elif scheme == 'http':
                transport = self.defaultHttpTransport
            else:
                raise RuntimeError, 'must specify transport or url startswith https/http'

        # Send the request.
        if issubclass(transport, httplib.HTTPConnection) is False:
            raise TypeError, 'transport must be a HTTPConnection'

        soapdata = str(sw)
        self.h = transport(netloc, None, **self.transdict)
        self.h.connect()
        self.SendSOAPData(soapdata, url, soapaction, **kw)

    def SendSOAPData(self, soapdata, url, soapaction, headers={}, **kw):
        # Tracing?
        if self.trace:
            print >> self.trace, "_" * 33, time.ctime(time.time()), "REQUEST:"
            print >> self.trace, soapdata

        url = url or self.url
        request_uri = _get_postvalue_from_absoluteURI(url)
        self.h.putrequest("POST", request_uri)
        self.h.putheader("Content-Length", "%d" % len(soapdata))
        self.h.putheader("Content-Type",
                         'text/xml; charset="%s"' % UNICODE_ENCODING)
        self.__addcookies()

        for header, value in headers.items():
            self.h.putheader(header, value)

        SOAPActionValue = '"%s"' % (soapaction or self.soapaction)
        self.h.putheader("SOAPAction", SOAPActionValue)
        if self.auth_style & AUTH.httpbasic:
            val = _b64_encode(self.auth_user + ':' + self.auth_pass) \
                        .replace("\012", "")
            self.h.putheader('Authorization', 'Basic ' + val)
        elif self.auth_style == AUTH.httpdigest and not headers.has_key('Authorization') \
            and not headers.has_key('Expect'):

            def digest_auth_cb(response):
                self.SendSOAPDataHTTPDigestAuth(response, soapdata, url,
                                                request_uri, soapaction, **kw)
                self.http_callbacks[401] = None

            self.http_callbacks[401] = digest_auth_cb

        for header, value in self.user_headers:
            self.h.putheader(header, value)
        self.h.endheaders()
        self.h.send(soapdata)

        # Clear prior receive state.
        self.data, self.ps = None, None

    def SendSOAPDataHTTPDigestAuth(self, response, soapdata, url, request_uri,
                                   soapaction, **kw):
        '''Resend the initial request w/http digest authorization headers.
        The SOAP server has requested authorization.  Fetch the challenge, 
        generate the authdict for building a response.
        '''
        if self.trace:
            print >> self.trace, "------ Digest Auth Header"
        url = url or self.url
        if response.status != 401:
            raise RuntimeError, 'Expecting HTTP 401 response.'
        if self.auth_style != AUTH.httpdigest:
            raise RuntimeError,\
                'Auth style(%d) does not support requested digest authorization.' %self.auth_style

        from ZSI.digest_auth import fetch_challenge,\
            generate_response,\
            build_authorization_arg,\
            dict_fetch

        chaldict = fetch_challenge(response.getheader('www-authenticate'))
        if dict_fetch(chaldict,'challenge','').lower() == 'digest' and \
            dict_fetch(chaldict,'nonce',None) and \
            dict_fetch(chaldict,'realm',None) and \
            dict_fetch(chaldict,'qop',None):
            authdict = generate_response(chaldict,
                                         request_uri,
                                         self.auth_user,
                                         self.auth_pass,
                                         method='POST')
            headers = {\
                'Authorization':build_authorization_arg(authdict),
                'Expect':'100-continue',
            }
            self.SendSOAPData(soapdata, url, soapaction, headers, **kw)
            return

        raise RuntimeError,\
            'Client expecting digest authorization challenge.'

    def ReceiveRaw(self, **kw):
        '''Read a server reply, unconverted to any format and return it.
        '''
        if self.data: return self.data
        trace = self.trace
        while 1:
            response = self.h.getresponse()
            self.reply_code, self.reply_msg, self.reply_headers, self.data = \
                response.status, response.reason, response.msg, response.read()
            if trace:
                print >> trace, "_" * 33, time.ctime(time.time()), "RESPONSE:"
                for i in (
                        self.reply_code,
                        self.reply_msg,
                ):
                    print >> trace, str(i)
                print >> trace, "-------"
                print >> trace, str(self.reply_headers)
                print >> trace, self.data
            saved = None
            for d in response.msg.getallmatchingheaders('set-cookie'):
                if d[0] in [' ', '\t']:
                    saved += d.strip()
                else:
                    if saved: self.cookies.load(saved)
                    saved = d.strip()
            if saved: self.cookies.load(saved)
            if response.status == 401:
                if not callable(self.http_callbacks.get(response.status,
                                                        None)):
                    raise RuntimeError, 'HTTP Digest Authorization Failed'
                self.http_callbacks[response.status](response)
                continue
            if response.status != 100: break

            # The httplib doesn't understand the HTTP continuation header.
            # Horrible internals hack to patch things up.
            self.h._HTTPConnection__state = httplib._CS_REQ_SENT
            self.h._HTTPConnection__response = None
        return self.data

    def IsSOAP(self):
        if self.ps: return 1
        self.ReceiveRaw()
        mimetype = self.reply_headers.type
        return mimetype == 'text/xml'

    def ReceiveSOAP(self, readerclass=None, **kw):
        '''Get back a SOAP message.
        '''
        if self.ps: return self.ps
        if not self.IsSOAP():
            raise TypeError('Response is "%s", not "text/xml"' %
                            self.reply_headers.type)
        if len(self.data) == 0:
            raise TypeError('Received empty response')

        self.ps = ParsedSoap(self.data,
                             readerclass=readerclass or self.readerclass,
                             encodingStyle=kw.get('encodingStyle'))

        if self.sig_handler is not None:
            self.sig_handler.verify(self.ps)

        return self.ps

    def IsAFault(self):
        '''Get a SOAP message, see if it has a fault.
        '''
        self.ReceiveSOAP()
        return self.ps.IsAFault()

    def ReceiveFault(self, **kw):
        '''Parse incoming message as a fault. Raise TypeError if no
        fault found.
        '''
        self.ReceiveSOAP(**kw)
        if not self.ps.IsAFault():
            raise TypeError("Expected SOAP Fault not found")
        return FaultFromFaultMessage(self.ps)

    def Receive(self, replytype, **kw):
        '''Parse message, create Python object.

        KeyWord data:
            faults   -- list of WSDL operation.fault typecodes
            wsaction -- If using WS-Address, must specify Action value we expect to
                receive.
        '''
        self.ReceiveSOAP(**kw)
        if self.ps.IsAFault():
            msg = FaultFromFaultMessage(self.ps)
            raise FaultException(msg)

        tc = replytype
        if hasattr(replytype, 'typecode'):
            tc = replytype.typecode

        reply = self.ps.Parse(tc)
        if self.address is not None:
            self.address.checkResponse(self.ps, kw.get('wsaction'))
        return reply

    def __repr__(self):
        return "<%s instance %s>" % (self.__class__.__name__, _get_idstr(self))