source: TI07-MOLES/trunk/StubB/XSLT/browse/portal/cgi/browse/browseCGI.py @ 1171

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI07-MOLES/trunk/StubB/XSLT/browse/portal/cgi/browse/browseCGI.py@1171
Revision 1171, 11.1 KB checked in by lawrence, 13 years ago (diff)

More browse/discovery rendering modifications, utilising
Kev's new DIF returning routine ...

  • Property svn:executable set to *
Line 
1#!/usr/bin/env python
2# CGI Script to support prototype NDG MOLES_Portal (Browse) functionality
3# Bryan Lawrence, April, 2006
4
5import cgi
6#import cgitb;ctitb.enable()
7
8import os
9import ElementTree as ET
10
11from insecure import *
12from secure import *
13from stubB import *
14
15from renderEntity import renderEntity
16from renderPage import renderPage
17from renderDiscoverySet import renderDiscoverySet
18from htmlUtilities import selector,hyperlink
19from Utilities import *
20from ETxmlView import *
21from DiscoveryWS import *
22from DIF import DIF
23
24import Cookie
25
26class BrowseSession:
27       
28        ''' Holds the browse and select history '''
29       
30        def __init__(self,cookie,config):
31               
32                '''Instantiate with an unsecured browse session (security only
33                required if a secure resource is the target) '''
34                self.config=config
35                self.rawCookie=cookie
36                self.cookie=Cookie.SimpleCookie(cookie)
37                self.history=RingBuffer(10)
38                self.selected=RingBuffer(5)
39             
40                self.__load()
41                       
42        def __toXML(self):
43                ''' Used to serialise the session into a cookie string '''
44                xml='<ndgCookie><bh>'
45                for uri,name in self.getHistory():
46                        xml+='<i><u>%s</u><n>%s</n></i>'%(uri,name)
47                xml+='</bh><sh>'
48                for uri,name in self.getSelected():
49                    xml+='<i><u>%s</u><n>%s</n></i>'%(uri,name)
50                xml+='</sh></ndgCookie>'
51                return xml
52               
53        def __load(self):
54            ''' get lists of URI values out of a cookie '''
55            try:
56                e=ET.fromstring(self.cookie['history'].value)
57                for se in e:
58                    for item in se:
59                        uri,name=item.find('u'),item.find('n')
60                        self.__addTo(uri.text,name.text,se.tag)
61            except KeyError:
62                pass
63                       
64        def __addTo(self,uri,name,tag,ignore=False):
65            d={'bh':self.history,'sh':self.selected}
66            current=d[tag].tolist()
67            if (uri,name) not in current or ignore:
68                d[tag].append((uri,name))
69                       
70        def addToHistory(self,uri,name,ignore=False):
71           ''' Add a URI to the session history'''
72           self.__addTo(uri,name,'bh',ignore)
73                       
74        def getHistory(self):
75           ''' Return a list of the items in the history '''
76           return self.history.tolist()
77       
78        def addToSelected(self,uri,name,ignore=False):
79            ''' Add a URI to the selected items '''
80            self.__addTo(uri,name,'sh',ignore)
81            self.__addTo(uri,name,'bh',ignore)
82                   
83        def getSelected(self):
84            ''' Return a list of selected items '''     
85            return self.selected.tolist()       
86       
87        def makeCookie(self,ndgSec=None):
88                ''' Create a local cookie '''
89                import md5,time,base64
90                # start by creating a unique session id
91                m=md5.new()
92                m.update('this is a seed string')
93                m.update(str(time.time()))
94                cookie=Cookie.SimpleCookie()
95                cookie['session']=base64.encodestring(m.digest())[:-3].replace("/", "$")
96                cookie['history']=self.__toXML()
97                if ndgSec is not None:
98                    cookie['NDG-ID1']=ndgSec[0]
99                    cookie['NDG-ID2']=ndgSec[1]
100                return cookie
101       
102class Request:
103    ''' Holds the request URL etc '''
104    def __init__(self,env):
105        self.env=env
106        self.URL='http://%s:%s%s'%(env.get('SERVER_NAME'),env.get('SERVER_PORT'),
107        env.get('SCRIPT_NAME'))
108        qs=env.get('QUERY_STRING')
109        if qs!='': self.URL+='?'+qs
110
111class CGIcontroller:
112        ''' Currently holds the cgi environment and controls '''
113       
114        def __init__(self,config):
115                ''' Instantiate the CGI environment'''
116                #
117                # Need to refactor all of this to use the request class and then move
118                # the request class out into the utilities ...
119                #
120                self.env=os.environ
121                self.path=self.env.get('PATH_INFO','/')
122                self.FieldStorage=getURLdict(cgi.FieldStorage())
123                self.config=config
124                self.response=Response()
125                self.request=Request(self.env)
126                self.requestURL=self.request.URL
127                self.selector=selector(self.requestURL,'select',config.get('layout','selectI'))
128                self.serviceFile=self.config.get('services','serviceFile')
129               
130
131        def makeGateway(self,cookie=None):
132                ''' Make connection to NDG security and load what is necessary for
133                an NDG cookie to be written '''
134                aa=self.config.get('security','localAA',None)
135                if 'NDG-ID1' in self.FieldStorage and 'NDG-ID2' in self.FieldStorage:
136                    #this is a redirect following login ...
137                    cmdLine=(self.FieldStorage['NDG-ID1'],self.FieldStorage['NDG-ID2'])
138                else: cmdLine=None
139                self.ndgGate=gateway2NDGsession(self.requestURL,self.config,aa,cookie=self.cookie,cmdLine=cmdLine)
140                self.ndgSec=cmdLine
141
142        def goforit(self):
143                ''' This method actually responds to the user'''
144               
145                self.ViewTextOnly,self.ViewXML=0,0
146               
147                #Instantiate the Session Environment
148                cookie=self.env.get('HTTP_COOKIE',None)
149                self.session=BrowseSession(cookie,self.config)
150                self.cookie=self.session.cookie # now a cookie class object ...
151                if self.config.logfile is not None: self.config.log(self.cookie)
152               
153                #this is where we invoke NDG security setup, even if we don't
154                #need it ...
155                self.makeGateway()
156               
157                #this will do for the moment, although I'd rather the whole
158                #URI was self consistent using the request object.
159               
160                if 'select' in self.FieldStorage:
161                    #need to sort out the name issue ...
162                    self.session.addToSelected(self.FieldStorage['select'],'dif')
163                    #we also need to trim the selector off the current requestURL
164                    self.requestURL=self.requestURL[0:self.requestURL.find('&select')]
165                    self.selector.baseURL=self.requestURL
166               
167                #use name as an error return as well in the following calls ...
168                if 'uri' in self.FieldStorage:
169                    self.uri=self.FieldStorage['uri']
170                    content,name=self.__browse()
171                elif 'search' in self.FieldStorage:
172                    self.searchType=self.FieldStorage['search']
173                    content,name=self.__search()
174                else: 
175                    content,name=self.error('No URI or search string. Begin browsing via search box or pass a specific URI argument.'),'No URI'
176
177                if not self.ViewTextOnly:
178                    historyHTML='<p>'
179                    for item in self.session.getHistory():
180                        historyHTML+=hyperlink(item[1],item[0])+'<br/>'
181                    historyHTML+='</p>'
182                    selectHTML='<p>'
183                    for item in self.session.getSelected():
184                        selectHTML+=hyperlink(item[1],item[0])+'<br/>'
185                    selectHTML+='</p>'
186                    self.response.content=renderPage(
187                        content,historyHTML,selectHTML,name,self.config)
188                else:
189                    self.response.content=content
190                self.response.cookie=self.session.makeCookie(ndgSec=self.ndgSec)
191                return self.response
192               
193        def __browse(self):
194                ''' Handle orthodox browsing '''
195               
196                if self.FieldStorage.has_key('text'):
197                    self.ViewTextOnly=1
198                elif self.FieldStorage.has_key('xml'):
199                    self.ViewXML=1
200               
201                format='NDG-B0'
202                if self.FieldStorage.has_key('D'):format='DIF'
203               
204                #get the xml document
205                db=self.config.get('db','exist',None)
206                jar=self.config.get('services','jarLoc')
207                javabin=self.config.get('services','javaBinary')
208                xml=insecureGetDoc(self.uri,db=db,format=format,jar=jar,javaBin=javabin)
209               
210                #create document instance
211                if format=='NDG-B0':
212                    self.b=stubB(xml,serviceFile=self.serviceFile)
213                elif format=='DIF':
214                    self.b=DIF(xml,serviceFile=self.serviceFile)
215               
216                if self.b.xml is None:
217                    content=self.error('Unable to obtain record from database')
218                    return content,0
219                else:
220                    self.session.addToHistory(self.b.binding.url,self.b.abbreviation)
221                    if  self.b.constraints.exist:
222                        # we need to evaluate them
223                        try:
224                             result=self.ndgGate.check(self.b.constraints.SimpleCondition)
225                             if result=='AccessGranted': 
226                                access=1
227                             else:
228                                access=0
229                        except:
230                             #unable to make ndggate check ... deny
231                             access=0
232                             result=self.error('Unable to connect to security gateway, access to secure resource denied')
233                    else:
234                        access=1
235                    if access:
236                        name=self.b.name
237                        if self.ViewTextOnly:
238                            self.response.contentType='text/plain'
239                            content=et2text(self.b.tree)
240                        elif self.ViewXML==1:
241                            content=et2html(self.b.tree)
242                        else:
243                            content=self.b.toHTML(self.config)
244                    else:
245                        name='NDG Browse'
246                        content=result
247
248                    return content,name
249               
250        def __search(self):
251            ''' Handle simple searching within the context of the browse '''
252            if 'SEARCHSTRING' in self.FieldStorage:
253                searchString=self.FieldStorage['SEARCHSTRING']
254                title='Search for '+searchString
255                try:
256                    ws=DiscoveryWS()
257                except Exception, e:
258                    return self.error('<p>%s<br/>%s'%(e,'Unable to connect to Search BackEnd')),'Error'
259                try:
260                    hits=ws.SearchFullText(searchString)
261                    state=DiscoveryState(ws.sessID,self.requestURL,hits,stride=10)
262                    results=ws.GetResults(offset=state.offset,number=state.stride)
263                except TypeError:
264                    # this is not what these web services should do, they should
265                    # return an empty set or something which matches the argument
266                    # list, but at least I think this traps the empty set.
267                    return self.error('No records found'),title
268                difs=[]
269               
270                for result in results: difs.append(DIF(result,serviceFile=self.serviceFile))
271                html=renderDiscoverySet(difs,state,selector=self.selector,
272                               summary=1,spatial=1,temporal=1,services=1)
273               
274                return html,title
275            else:
276                return self.error('No valid search option'),'Error'
277             
278        def error(self,message):
279                ''' Construct a nice formal response, but don't throw a 404 ... '''
280                return '<p>Error: %s</p>'%message
281               
Note: See TracBrowser for help on using the repository browser.