This file is indexed.

/usr/lib/python2.7/dist-packages/ZSI/ServiceProxy.py is in python-zsi 2.1~a1-4.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.

import weakref, re, os, sys
from ConfigParser import SafeConfigParser as ConfigParser,\
    NoSectionError, NoOptionError
from urlparse import urlparse

from ZSI import TC
from ZSI.client import _Binding
from ZSI.generate import commands,containers
from ZSI.schema import GED, GTD

import wstools


#url_to_mod = re.compile(r'<([^ \t\n\r\f\v:]+:)?include\s+location\s*=\s*"(\S+)"')
def _urn_to_module(urn): return '%s_types' %re.sub(_urn_to_module.regex, '_', urn)
_urn_to_module.regex = re.compile(r'[\W]')
    

class ServiceProxy:
    """A ServiceProxy provides a convenient way to call a remote web
       service that is described with WSDL. The proxy exposes methods
       that reflect the methods of the remote web service."""

    def __init__(self, wsdl, url=None, service=None, port=None,
                 cachedir=os.path.join(os.path.expanduser('~'), '.zsi_service_proxy_dir'), 
                 asdict=True, lazy=False, pyclass=False, force=False, **kw):
        """
        Parameters:
           wsdl -- URL of WSDL.
           url -- override WSDL SOAP address location
           service -- service name or index
           port -- port name or index
           cachedir -- where to store generated files
           asdict -- use dicts, else use generated pyclass
           lazy -- use lazy typecode evaluation
           pyclass -- use pyclass_type metaclass adds properties, "new_", "set_, 
               "get_" methods for schema element and attribute declarations.
           force -- regenerate all WSDL code, write over cache.
           
        NOTE: all other **kw will be passed to the underlying 
        ZSI.client._Binding constructor.
           
        """
        self._asdict = asdict
        
        # client._Binding
        self._url = url
        self._kw = kw
        
        # WSDL
        self._wsdl = wstools.WSDLTools.WSDLReader().loadFromURL(wsdl)
        self._service = self._wsdl.services[service or 0]
        self.__doc__ = self._service.documentation
        self._port = self._service.ports[port or 0]
        self._name = self._service.name
        self._methods = {}
        self._cachedir = cachedir
        self._lazy = lazy
        self._pyclass = pyclass
        self._force = force
        
        # Set up rpc methods for service/port
        port = self._port
        binding = port.getBinding()
        portType = binding.getPortType()
        for port in self._service.ports:
            for item in port.getPortType().operations:
                try:
                    callinfo = wstools.WSDLTools.callInfoFromWSDL(port, item.name)
                except:
                    # ignore non soap-1.1  bindings
                    continue
                
                method = MethodProxy(self, callinfo)
                setattr(self, item.name, method)
                self._methods.setdefault(item.name, []).append(method)
       
        self._mod = self._load(wsdl)
        
    def _load(self, location):
        """
        location -- URL or file location
        isxsd -- is this a xsd file?
        """
        cachedir = self._cachedir
        # wsdl2py: deal with XML Schema
        if not os.path.isdir(cachedir): os.mkdir(cachedir)
    
        file = os.path.join(cachedir, '.cache')
        section = 'TYPES'
        cp = ConfigParser()
        try:
            cp.readfp(open(file, 'r'))
        except IOError:
            del cp;  cp = None
            
        option = location.replace(':', '-') # colons seem to screw up option
        if (not self._force and cp is not None and cp.has_section(section) and 
            cp.has_option(section, option)):
            types = cp.get(section, option)
        else:
            # dont do anything to anames
            if not self._pyclass:
                containers.ContainerBase.func_aname = lambda instnc,n: str(n)
                
            args = ['-o', cachedir, location]
            if self._lazy: args.insert(0, '-l')
            if self._pyclass: args.insert(0, '-b')
            files = commands.wsdl2py(args)

            if cp is None: cp = ConfigParser()
            if not cp.has_section(section): cp.add_section(section)
            types = filter(lambda f: f.endswith('_types.py'), files)[0]
            cp.set(section, option, types)
            cp.write(open(file, 'w'))
            
        if os.path.abspath(cachedir) not in sys.path:
            sys.path.append(os.path.abspath(cachedir))
            
        mod = os.path.split(types)[-1].rstrip('.py')
        return __import__(mod)
    
    def _load_schema(self, location, xml=None):
        """
        location -- location of schema, also used as a key
        xml -- optional string representation of schema
        """
        cachedir = self._cachedir
        # wsdl2py: deal with XML Schema
        if not os.path.isdir(cachedir): os.mkdir(cachedir)
    
        file = os.path.join(cachedir, '.cache')
        section = 'TYPES'
        cp = ConfigParser()
        try:
            cp.readfp(open(file, 'r'))
        except IOError:
            del cp;  cp = None
            
        option = location.replace(':', '-') # colons seem to screw up option
        if (cp is not None and cp.has_section(section) and 
            cp.has_option(section, option)):
            types = cp.get(section, option)
        else:
            # dont do anything to anames
            if not self._pyclass:
                containers.ContainerBase.func_aname = lambda instnc,n: str(n)
                
            from ZSI.wstools import XMLSchema
            reader = XMLSchema.SchemaReader(base_url=location)
            if xml is not None and isinstance(xml, basestring):
                schema = reader.loadFromString(xml)
            elif xml is not None:
                raise RuntimeError, 'Unsupported: XML must be string'
            elif not os.path.isfile(location):
                schema = reader.loadFromURL(location)
            else:
                schema = reader.reader.loadFromFile(location)
                
            # TODO: change this to keyword list
            class options:
                output_dir = cachedir
                schema = True
                simple_naming = False
                address = False
                lazy = self._lazy
                complexType = self._pyclass

            schema.location = location
            files = commands._wsdl2py(options, schema)
            if cp is None: cp = ConfigParser()
            if not cp.has_section(section): cp.add_section(section)
            types = filter(lambda f: f.endswith('_types.py'), files)[0]
            cp.set(section, option, types)
            cp.write(open(file, 'w'))
            
        if os.path.abspath(cachedir) not in sys.path:
            sys.path.append(os.path.abspath(cachedir))
            
        mod = os.path.split(types)[-1].rstrip('.py')
        return __import__(mod)
            
    def _call(self, name, soapheaders):
        """return the Call to the named remote web service method.
        closure used to prevent multiple values for name and soapheaders 
        parameters 
        """
        
        def call_closure(*args, **kwargs):
            """Call the named remote web service method."""
            if len(args) and len(kwargs):
                raise TypeError, 'Use positional or keyword argument only.'
                
            if len(args) > 0:
                raise TypeError, 'Not supporting SOAPENC:Arrays or XSD:List'
            
            if len(kwargs): 
                args = kwargs

            callinfo = getattr(self, name).callinfo
    
            # go through the list of defined methods, and look for the one with
            # the same number of arguments as what was passed.  this is a weak
            # check that should probably be improved in the future to check the
            # types of the arguments to allow for polymorphism
            for method in self._methods[name]:
                if len(method.callinfo.inparams) == len(kwargs):
                    callinfo = method.callinfo
    
            binding = _Binding(url=self._url or callinfo.location,
                              soapaction=callinfo.soapAction,
                              **self._kw)
    
            kw = dict(unique=True)
            if callinfo.use == 'encoded':
                kw['unique'] = False
    
            if callinfo.style == 'rpc':
                request = TC.Struct(None, ofwhat=[], 
                                 pname=(callinfo.namespace, name), **kw)
                
                response = TC.Struct(None, ofwhat=[], 
                                 pname=(callinfo.namespace, name+"Response"), **kw)
                
                if len(callinfo.getInParameters()) != len(args):
                    raise RuntimeError('expecting "%s" parts, got %s' %(
                           str(callinfo.getInParameters(), str(args))))
                
                for msg,pms in ((request,callinfo.getInParameters()), 
                                (response,callinfo.getOutParameters())):
                    msg.ofwhat = []
                    for part in pms:
                        klass = GTD(*part.type)
                        if klass is None:
                            if part.type:
                                klass = filter(lambda gt: part.type==gt.type,TC.TYPES)
                                if len(klass) == 0:
                                    klass = filter(lambda gt: part.type[1]==gt.type[1],TC.TYPES)
                                    if not len(klass):klass = [TC.Any]
                                if len(klass) > 1: #Enumerations, XMLString, etc
                                    klass = filter(lambda i: i.__dict__.has_key('type'), klass)
                                klass = klass[0]
                            else:
                                klass = TC.Any
                    
                        msg.ofwhat.append(klass(part.name))
                        
                    msg.ofwhat = tuple(msg.ofwhat)
                if not args: args = {}
            else:
                # Grab <part element> attribute
                ipart,opart = callinfo.getInParameters(),callinfo.getOutParameters()
                if ( len(ipart) != 1 or not ipart[0].element_type or 
                    ipart[0].type is None ):
                    raise RuntimeError, 'Bad Input Message "%s"' %callinfo.name
        
                if ( len(opart) not in (0,1) or not opart[0].element_type or 
                    opart[0].type is None ):
                    raise RuntimeError, 'Bad Output Message "%s"' %callinfo.name
                
#                if ( len(args) > 1 ):
#                    raise RuntimeError, 'Message has only one part:  %s' %str(args)
                
                ipart = ipart[0]
                request,response = GED(*ipart.type),None
                if opart: response = GED(*opart[0].type)
    
            msg = args
            if self._asdict: 
                if not msg: msg = dict()
                self._nullpyclass(request)
            elif request.pyclass is not None:
                if type(args) is dict:
                    msg = request.pyclass()
                    msg.__dict__.update(args)
                elif type(args) is list and len(args) == 1: 
                    msg = request.pyclass(args[0])
                else: 
                    msg = request.pyclass()
                    
            binding.Send(None, None, msg,
                         requesttypecode=request,
                         soapheaders=soapheaders,
                         encodingStyle=callinfo.encodingStyle)
            
            if response is None: 
                return None
            
            if self._asdict: self._nullpyclass(response)
            return binding.Receive(replytype=response,
                         encodingStyle=callinfo.encodingStyle)
            
        return call_closure

    def _nullpyclass(cls, typecode):
        typecode.pyclass = None
        if not hasattr(typecode, 'ofwhat'): return
        if type(typecode.ofwhat) not in (list,tuple): #Array
            cls._nullpyclass(typecode.ofwhat)
        else: #Struct/ComplexType
            for i in typecode.ofwhat: cls._nullpyclass(i)    
    _nullpyclass = classmethod(_nullpyclass)


class MethodProxy:
    """ """
    def __init__(self, parent, callinfo):
        self.__name__ = callinfo.methodName
        self.__doc__ = callinfo.documentation
        self.callinfo = callinfo
        self.parent = weakref.ref(parent)
        self.soapheaders = []

    def __call__(self, *args, **kwargs):
        return self.parent()._call(self.__name__, self.soapheaders)(*args, **kwargs)

    def add_headers(self, **headers):
        """packing dicts into typecode pyclass, may fail if typecodes are
        used in the body (when asdict=True)
        """
        class _holder: pass
        def _remap(pyobj, **d):
            pyobj.__dict__ = d
            for k,v in pyobj.__dict__.items():
                if type(v) is not dict: continue
                pyobj.__dict__[k] = p = _holder()
                _remap(p, **v)
    
        for k,v in headers.items():
            h = filter(lambda i: k in i.type, self.callinfo.inheaders)[0]
            if h.element_type != 1: 
                raise RuntimeError, 'not implemented'

            typecode = GED(*h.type)
            if typecode is None: 
                raise RuntimeError, 'no matching element for %s' %str(h.type)

            pyclass = typecode.pyclass
            if pyclass is None: 
                raise RuntimeError, 'no pyclass for typecode %s' %str(h.type)

            if type(v) is not dict:
                pyobj = pyclass(v)
            else:
                pyobj = pyclass()
                _remap(pyobj, **v)

            self.soapheaders.append(pyobj)