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

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

Hopefully now we will write an NDG security cookie as
well ... if we get to load one ...

  • 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 *
22
23import Cookie
24
25class BrowseSession:
26       
27        ''' Holds the browse and select history '''
28       
29        def __init__(self,cookie,config):
30               
31                '''Instantiate with an unsecured browse session (security only
32                required if a secure resource is the target) '''
33                self.config=config
34                self.rawCookie=cookie
35                self.cookie=Cookie.SimpleCookie(cookie)
36                self.history=RingBuffer(10)
37                self.selected=RingBuffer(5)
38             
39                self.__load()
40                       
41        def __toXML(self):
42                ''' Used to serialise the session into a cookie string '''
43                xml='<ndgCookie><bh>'
44                for uri,name in self.getHistory():
45                        xml+='<i><u>%s</u><n>%s</n></i>'%(uri,name)
46                xml+='</bh><sh>'
47                for uri,name in self.getSelected():
48                    xml+='<i><u>%s</u><n>%s</n></i>'%(uri,name)
49                xml+='</sh></ndgCookie>'
50                return xml
51               
52        def __load(self):
53            ''' get lists of URI values out of a cookie '''
54            try:
55                e=ET.fromstring(self.cookie['history'].value)
56                for se in e:
57                    for item in se:
58                        uri,name=item.find('u'),item.find('n')
59                        self.__addTo(uri.text,name.text,se.tag)
60            except KeyError:
61                pass
62                       
63        def __addTo(self,uri,name,tag,ignore=False):
64            d={'bh':self.history,'sh':self.selected}
65            current=d[tag].tolist()
66            if (uri,name) not in current or ignore:
67                d[tag].append((uri,name))
68                       
69        def addToHistory(self,uri,name,ignore=False):
70           ''' Add a URI to the session history'''
71           self.__addTo(uri,name,'bh',ignore)
72                       
73        def getHistory(self):
74           ''' Return a list of the items in the history '''
75           return self.history.tolist()
76       
77        def addToSelected(self,uri,name,ignore=False):
78            ''' Add a URI to the selected items '''
79            self.__addTo(uri,name,'sh',ignore)
80            self.__addTo(uri,name,'bh',ignore)
81                   
82        def getSelected(self):
83            ''' Return a list of selected items '''     
84            return self.selected.tolist()       
85       
86        def makeCookie(self,ndgSec=None):
87                ''' Create a local cookie '''
88                import md5,time,base64
89                # start by creating a unique session id
90                m=md5.new()
91                m.update('this is a seed string')
92                m.update(str(time.time()))
93                cookie=Cookie.SimpleCookie()
94                cookie['session']=base64.encodestring(m.digest())[:-3].replace("/", "$")
95                cookie['history']=self.__toXML()
96                if ndgSec is not None:
97                    cookie['NDG-ID1']=ndgSec[0]
98                    cookie['NDG-ID2']=ndgSec[1]
99                return cookie
100       
101class CGIcontroller:
102        ''' Currently holds the cgi environment and controls '''
103       
104        def __init__(self,config):
105                ''' Instantiate the CGI environment'''
106                self.env=os.environ
107                self.path=self.env.get('PATH_INFO','/')
108                self.FieldStorage=getURLdict(cgi.FieldStorage())
109                self.config=config
110                self.response=Response()
111                self.requestURL=self.env.get('SCRIPT_NAME')+'?'+self.env.get('QUERY_STRING')
112                self.selector=selector(self.requestURL,config.get('layout','selectI'))
113               
114
115        def makeGateway(self,cookie=None):
116                ''' Make connection to NDG security and load what is necessary for
117                an NDG cookie to be written '''
118                aa=self.config.get('security','localAA',None)
119                if 'NDG-ID1' in self.FieldStorage and 'NDG-ID2' in self.FieldStorage:
120                    #this is a redirect following login ...
121                    cmdLine=(self.FieldStorage['NDG-ID1'],self.FieldStorage['NDG-ID2'])
122                else: cmdLine=None
123                self.ndgGate=gateway2NDGsession(self.requestURL,aa,cookie=cookie,cmdLine=cmdLine)
124                self.ndgSec=cmdLine
125
126        def goforit(self):
127                ''' This method actually responds to the user'''
128               
129                self.ViewTextOnly,self.ViewXML=0,0
130               
131                #Instantiate the Session Environment
132                self.cookie=self.env.get('HTTP_COOKIE',None)
133                self.session=BrowseSession(self.cookie,self.config)
134                if self.config.logfile is not None: self.config.log(self.cookie)
135               
136                #this is where we invoke NDG security setup, even if we don't
137                #need it ...
138                self.makeGateway()
139               
140                #this will do for the moment, although I'd rather the whole
141                #URI was self consistent ...
142               
143                if 'select' in self.FieldStorage:
144                    #need to sort out the name issue ...
145                    self.session.addToSelected(self.FieldStorage['select'],'dif')
146                    #we also need to trim the selector off the current requestURL
147                    self.requestURL=self.requestURL[0:self.requestURL.find('&select')]
148                    self.selector.baseURL=self.requestURL
149               
150                #use name as an error return as well in the following calls ...
151                if 'uri' in self.FieldStorage:
152                    self.uri=self.FieldStorage['uri']
153                    content,name=self.__browse()
154                elif 'search' in self.FieldStorage:
155                    self.searchType=self.FieldStorage['search']
156                    content,name=self.__search()
157                else: 
158                    content,name=self.error('No valid URI'),'Error'
159
160                if not self.ViewTextOnly:
161                    historyHTML='<p>'
162                    for item in self.session.getHistory():
163                        historyHTML+=hyperlink(item[1],item[0])+'<br/>'
164                    historyHTML+='</p>'
165                    selectHTML='<p>'
166                    for item in self.session.getSelected():
167                        selectHTML+=hyperlink(item[1],item[0])+'<br/>'
168                    selectHTML+='</p>'
169                    self.response.content=renderPage(
170                        content,historyHTML,selectHTML,name,self.config)
171                else:
172                    self.response.content=content
173                self.response.cookie=self.session.makeCookie(ndgSec=self.ndgSec)
174                return self.response
175               
176        def __browse(self):
177                ''' Handle orthodox browsing '''
178               
179                if self.FieldStorage.has_key('text'):
180                    self.ViewTextOnly=1
181                elif self.FieldStorage.has_key('xml'):
182                    self.ViewXML=1
183               
184                #get the xml document
185                db=self.config.get('db','exist',None)
186                xml=insecureGetDoc(self.uri,db)
187               
188                #create stub-b instance
189                self.b=stubB(xml,makeHTML=renderEntity)
190               
191                if self.b.xml is None:
192                    content=self.error('Unable to obtain stub-B from database')
193                    return content,0
194                else:
195                    self.session.addToHistory(self.b.Burl,self.b.abbreviation)
196                    if  self.b.constraints.exist:
197                        # we need to evaluate them
198                        result=self.ndgGate.check(self.b.constraints.SimpleCondition)
199                        if result=='AccessGranted': 
200                            access=1
201                        else:
202                            access=0
203                    else:
204                        access=1
205                    if access:
206                        name=self.b.name
207                        if self.ViewTextOnly:
208                            self.response.contentType='text/plain'
209                            content=et2text(self.b.tree)
210                        elif self.ViewXML==1:
211                            content=et2html(self.b.tree)
212                        else:
213                            content=self.b.toHTML()
214                    else:
215                        name='NDG Browse'
216                        content=result
217
218                    return content,name
219               
220        def __search(self):
221            ''' Handle simple searching within the context of the browse '''
222            if 'SEARCHSTRING' in self.FieldStorage:
223                searchString=self.FieldStorage['SEARCHSTRING']
224                try:
225                    ws=DiscoveryWS()
226                except Exception, e:
227                    return self.error('<p>%s<br/>%s'%(e,'Unable to connect to Search BackEnd')),'Error'
228                hits=ws.SearchFullText(searchString)
229                state=DiscoveryState(ws.sessID,self.requestURL,hits,stride=10)
230                results=ws.GetResults(offset=state.offset,number=state.stride)
231                difs=[]
232                for result in results:
233                    difs.append(xmlCleanup(result))
234                html=renderDiscoverySet(difs,state,selector=self.selector,
235                               summary=1,spatial=1,temporal=1,services=1)
236                title='Search for '+searchString
237                return html,title
238            else:
239                return self.error('No valid search option'),'Error'
240             
241        def error(self,message):
242                ''' Construct a nice formal response, but don't throw a 404 ... '''
243                return '<p>Error: %s</p>'%message
244               
Note: See TracBrowser for help on using the repository browser.