source: cowsclient/trunk/cowsclient/lib/wmc_util.py @ 6335

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/cowsclient/trunk/cowsclient/lib/wmc_util.py@6335
Revision 6335, 7.6 KB checked in by domlowe, 12 years ago (diff)

Fixed bug reported in  http://proj.badc.rl.ac.uk/badc/ticket/21469

Line 
1# Copyright (C) 2007 STFC & NERC (Science and Technology Facilities Council).
2# This software may be distributed under the terms of the
3# Q Public License, version 1.0 or later.
4# http://ndg.nerc.ac.uk/public_docs/QPublic_license.txt
5"""
6Utils to aid use of wmc docs - including interfacing these with the con terra client
7and getting associated legend data
8
9@author: Calum Byrom, modified for NDG Security by Dominic Lowe
10"""
11from cowsclient.lib.base import *
12from cowsclient.model.WMC import WMC
13from cowsclient.lib import exceptions
14import urllib2, urllib
15import os
16import logging
17import urlparse
18log = logging.getLogger(__name__)
19
20
21def getConTerraDoc(wmcURLs):
22    """
23    Construct an aggregated XML file and display this as a temporary webpage; this will automatically be
24    POSTED so that the data is sent via POST to the Con Terra mapClient to visualise (as required by this client)
25    @param wmcURLS: An array of URLs pointing to WMC docs to visualise
26    """
27    # firstly, retrieve each WMC doc
28    wmcDocs = []
29    for wmcURL in wmcURLs:
30        wmcDocs.append(WMC(wmcURL))
31
32    # now create a dictionary of WMS/layer from these docs - to avoid duplicate layers
33    c.wms = {}
34    for wmcDoc in wmcDocs:
35        for layer in wmcDoc.layers:
36            if layer.wmsURL not in c.wms:
37                c.wms[layer.wmsURL] = [layer.name]
38            else:
39                if layer.name not in c.wms[layer.wmsURL]:
40                    c.wms[layer.wmsURL].append(layer.name)
41
42    # now create the form to post this data
43    c.redirectToConterra = True; #TODO, remove?
44    response.write(render('selectedItems'))
45
46
47
48def GetWebMapContext(self):
49    """
50    Lookup a WMC doc and return it in the response
51    """
52    # retrieve context data from the specifiled url
53    wmcDoc = RetrieveWebMapContext(self, self.inputs['ENDPOINT'])
54    log.info('WMC RESPONSE %s'%response)
55    response.headers['Content-Type'] = 'text/xml'
56    response.write(wmcDoc)
57
58def GetLegend(self):
59    """
60    Lookup a legend for a WMS map
61    NB, all required parameters are already included in the endpoint by this stage
62    """
63    endpoint = self.inputs['ENDPOINT']
64
65    if not endpoint:
66        raise exceptions.MissingParameterValue, "ENDPOINT parameter required"
67    try:
68        #req = urllib2.Request(endpoint,urllib.urlencode(request.params),{'Cookie': request.headers.get('Cookie', '')})
69        log.debug("endpoint = %s" % (endpoint,))
70        req = urllib2.Request(endpoint, None, {'Cookie': request.headers.get('Cookie', '')})
71        url = req.get_full_url()
72
73        filehandle = openURL(req)
74    except IOError:
75        raise exceptions.URLUnavailable, "Could not access WMC endpoint: %s" % endpoint
76   
77    return "<img src=\"%s\" />" % (url,)
78#    response.headers['Content-Type'] = 'image/gif'
79#    response.write(filehandle.read())
80
81def RetrieveWebMapContext(self, endpoint):
82    """
83    Get a WMC doc from a specified endpoint
84    @param endpoint: endpoint to retrieve WMC doc from
85    """
86    if not endpoint:
87        raise exceptions.MissingParameterValue, "ENDPOINT parameter required"
88    log.info('Getting WebMapContext from endpoint: ' + endpoint)
89    #urlstring=('%s&request=GetContext'%(str(endpoint)))
90    urlstring=('%s?request=GetContext&service=WMS'%(str(endpoint)))
91#    urlstring = str(endpoint)
92    log.info("urlstring=%s" % (urlstring,))
93    #cookies are passed to enable authorisation mechanisms e.g. ndg security
94    #try:
95
96    req = urllib2.Request(urlstring)
97    req.add_header('Cookie', request.headers.get('Cookie', ''))
98    filehandle = openURL(req)
99    return filehandle.read()
100
101def GetWebMapCapabilities(endpoint):
102   
103    urlstring = parseEndpointString(endpoint, {'REQUEST':'GetCapabilities',
104                                               'SERVICE':'WMS'} )
105    log.debug("urlstring = %s" % (urlstring,))
106    req = urllib2.Request(urlstring)
107    req.add_header('Cookie', request.headers.get('Cookie', ''))
108   
109    try:   
110        filehandle = openURL(req)
111        return filehandle.read()
112    except urllib2.HTTPError, e:           
113        log.exception("exception occurred")
114        if e.code == 401:
115            log.info ('401 unauthorized error in cowsclient')
116            return abort(401) #triggers ndg security framework
117        elif e.code == 403:  #TODO: 403 response is UNTESTED.
118            # User is authenticated but doesn't have the required permissions
119            # or an error occurred in the authorization process
120            # User is authenticated but doesn't have the required permissions
121            # or an error occurred in the authorization process
122            return abort(403)
123        else:
124            raise e
125
126def GetResponse(url):
127    req = urllib2.Request(url)
128    req.add_header('Cookie', request.headers.get('Cookie', ''))
129    filehandle = openURL(req)
130    return filehandle.read()   
131   
132
133noProxyOpener = urllib2.build_opener(urllib2.HTTPHandler(), urllib2.ProxyHandler({}))
134
135def openURL(req):
136    log.info("Making request: %s "%(req.get_full_url(),))
137    if _shouldUseProxy(req.get_full_url()):
138        log.debug("using proxy")
139        fh = urllib2.urlopen(req)
140    else:
141        log.debug("not using proxy")
142        fh = noProxyOpener.open(req)
143       
144    return fh
145
146def _shouldUseProxy(urlstring) :
147    no_proxy   = os.environ.get('no_proxy', '')
148   
149    urlObj = urlparse.urlparse(urlstring)
150    for np in no_proxy.split(','):
151        if urlObj.hostname == urlparse.urlparse(np).hostname:
152            return False
153   
154    return True
155
156def proxyFix(url):
157    oldProxyVal = os.environ.get('http_proxy', None)
158   
159    if oldProxyVal != None:
160        if os.environ['http_proxy'] != "" and not _shouldUseProxy(url):
161            os.environ['http_proxy'] = ""
162            reload(urllib2)
163
164    return oldProxyVal
165
166
167def resetProxy(oldProxyVal):
168   
169    if oldProxyVal == None or oldProxyVal == "":
170        return
171   
172    if os.environ['http_proxy'] != oldProxyVal:
173        os.environ['http_proxy'] = oldProxyVal
174        reload(urllib2)
175
176
177def parseEndpointString(endpointString, requiredParams):
178    """
179    Take an endpoint string and add the required params if they don't already appear
180    on the string.
181    """
182    urlObj = urlparse.urlparse(endpointString)
183   
184    queryParams = _parse_qs(urlObj.query)
185   
186    for k, v in requiredParams.items():
187        queryParams[k.lower()] = v
188   
189    queryString = _build_qs(queryParams)
190   
191    # as urlObj.query isn't writable extract the data to a list
192    # and replace the query data with the new query string
193    res = [x for x in urlObj]
194    res[4] = queryString
195                             
196    return urlparse.urlunparse(res)
197
198def _parse_qs(queryString):
199    """
200    returns a dictionary of key, value pairs from the query string. The keys in
201    the return dictionary are in all lowercase. Empty parameters are ignored.
202    The query string shouln't have a leading '?' character.
203    """
204    queryDict = {}
205   
206    for kvString in queryString.split('&'):
207       
208        if kvString == '':
209            continue
210       
211        key, value = kvString.split('=')
212       
213        if value in ['', None]:
214            continue
215           
216        queryDict[key.lower()] = value
217   
218    return queryDict
219
220def _build_qs(queryDict, upperCaseKeys=True):
221    """
222    Builds a url query string out of a dictionary. doesn't add the initial '?' character.
223   
224    If upperCaseKeys == True then all the dictionary keys will be included as capital letters.
225    """
226   
227    queryStr = ""
228    for k, v in queryDict.items():
229       
230        if upperCaseKeys:
231            k = k.upper()
232       
233        queryStr += "%s=%s&" % (k, v)
234   
235    #remove the last &
236    queryStr = queryStr[:-1]
237    return queryStr
238   
Note: See TracBrowser for help on using the repository browser.