source: MILK/trunk/milk_server/milk_server/controllers/home.py @ 5214

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/MILK/trunk/milk_server/milk_server/controllers/home.py@5214
Revision 5214, 4.9 KB checked in by cbyrom, 11 years ago (diff)

Add additional error reporting when illegal characters entered.

Line 
1'''
2 Base controller for MILK controllers, providing common functionality - including
3 fall back index method, to render a home page for the service depending on what
4 mode it is running in - NB, if multiple modes are enabled, the order of preference,
5 from highest to lowest, is editor, discovery, browser
6 
7 @author: C Byrom, Tessella Apr 2009
8'''
9import logging, traceback, xmlrpclib
10from formencode import htmlfill
11from milk_server.lib.base import *
12from ndg.common.src.lib.utilities import escapeSpecialCharacters
13from ndg.common.src.models.vocabtermdata import VocabTermData as VTD
14
15class HomeController(BaseController):
16    '''
17    Sets up appropriate home page for fall through urls
18    '''
19    def index(self):
20        '''
21        Redirect to the appropriate home page - or display error
22        '''
23        if g.atomEditorEnabled:
24            h.redirect_to(h.url_for('atomHome'))
25        elif g.discoveryEnabled:
26            h.redirect_to(h.url_for('discovery'))
27        elif g.browseEnabled:
28            h.redirect_to(h.url_for('browseHome'))
29        else:
30            c.title = "No service enabled"
31            c.xml = "The server should be configured to provide one or more of the followings client services: editor, discovery or browse."
32            return render("genshi", 'error')
33           
34
35    def savePageAndRender(self, template, **inputs):
36        '''
37        Save the current path info - to provide a memory function when changing
38        tabs + render the given template with the specified inputs filled in
39        automatically
40        @param template: name of template to render
41        @param inputs: dict of inputs with keynames matching input names in template
42        form 
43        '''
44        logging.debug("Saving current page url (%s) - to keep track of atom editor state" \
45                      %self.pathInfo)
46        session['currentEditor'] = self.pathInfo
47        session.save()
48        logging.debug("Now rendering current template (%s)" %template)
49        try:
50            html = render("genshi", template)
51           
52            # replace any browse links with to links to editor
53            html = html.replace(VTD.BROWSE_SERVER_URL, g.server)
54           
55            # NB, need html in unicode for for htmlfill.render
56            html = unicode(html, 'utf-8', 'xmlcharrefreplace')
57            for key, val in inputs.items():
58                inputs[key] = str(val)
59   
60            return htmlfill.render(html, inputs)
61
62        except Exception, e:
63            c.xml = 'Unexpected error [%s] whilst rendering page' %str(e)
64            if str(e).find('malformed start tag') >-1:
65                c.xml += " - NB, this is probably due to illegal HTML being entered"
66            c.doc = ''
67            response.status_code = 400
68            logging.error(c.xml)
69            return render('error')
70
71
72    def _unpackErrors(self, e):
73        '''
74        Add exception errors to the common error structures - for use
75        in templates
76        @param e: Exception to add
77        @return errors: dict of errors
78        '''
79        if not c.errors:
80            c.errors = {}
81
82        errorMessage = e.message
83        if g.debugModeOn == 'True':
84            errorMessage = traceback.format_exc()
85
86        c.xml = escapeSpecialCharacters('Unexpected error loading page [%s]' \
87                                        %str(errorMessage))
88        c.doc = ''
89       
90        # unpack errors, if possible - NB, the c.errors value is used by the template
91        # function, displayErrors, which is used by most of the editor templates
92        if isinstance(e, xmlrpclib.Fault):
93            # strip out the exception type - NB, this is usually native library code
94            # and is of no real interest - and will just confuse viewers
95            c.errors['Unexpected error'] = e.faultString.split(':')[-1] 
96
97        if hasattr(e, 'unpack_errors'):
98            c.errors.update(e.unpack_errors())
99           
100        else:
101            c.errors['Unexpected error'] = [c.xml]
102
103        # tidy up errors - escaping any xml tags, if necessary
104        for key, errors in c.errors.items():
105            newErrors = []
106            for error in errors:
107                for err in error.split('<br/>'):
108                    newErrors.append(escapeSpecialCharacters(err))
109            c.errors[key] = newErrors
110       
111        return c.errors
112
113
114    def _handleError(self, e, template='error'):
115        '''
116        Handle exceptions thrown; if debug mode on, display full stack trace
117        in output, otherwise just show basic error message in error template
118        @param e: Exception to process
119        @keyword template: template to render - 'error' is the default - NB, if
120        an alternative is specified it should have a div with class set to 'error'
121        containing the variable, c.xml to display properly
122        '''
123        self._unpackErrors(e)
124        logging.error(c.xml)
125        response.status_code = 400
126        return render("genshi", template)
Note: See TracBrowser for help on using the repository browser.