Example #1
0
class RH(RequestHandlerBase):
    """This class is the base for request handlers of the application. A request
        handler will be instantiated when a web request arrives to mod_python;
        the mp layer will forward the request to the corresponding request
        handler which will know which action has to be performed (displaying a
        web page or performing some operation and redirecting to another page).
        Request handlers will be responsible for parsing the parameters coming
        from a mod_python request, handle the errors which occurred during the
        action to perform, managing the sessions, checking security for each
        operation (thus they implement the access control system of the web
        interface).
        It is important to encapsulate all this here as in case of changing
        the web application framework we'll just need to adapt this layer (the
        rest of the system wouldn't need any change).

        Attributes:
            _uh - (URLHandler) Associated URLHandler which points to the
                current rh.
            _req - (mod_python.Request) mod_python request received for the
                current rh.
            _requestStarted - (bool) Flag which tells whether a DB transaction
                has been started or not.
            _websession - ( webinterface.session.sessionManagement.PSession )
                Web session associated to the HTTP request.
            _aw - (AccessWrapper) Current access information for the rh.
            _target - (Locable) Reference to an object which is the destination
                of the operations needed to carry out the rh. If set it must
                provide (through the standard Locable interface) the methods
                to get the url parameters in order to reproduce the access to
                the rh.
            _reqParams - (dict) Dictionary containing the received HTTP
                 parameters (independently of the method) transformed into
                 python data types. The key is the parameter name while the
                 value should be the received paramter value (or values).
    """
    _tohttps = False # set this value to True for the RH that must be HTTPS when there is a BaseSecureURL
    _doNotSanitizeFields = []

    def __init__( self, req ):
        """Constructor. Initialises the rh setting up basic attributes so it is
            able to process the request.

            Parameters:
                req - (mod_python.Request) mod_python request received for the
                    current rh.
        """
        RequestHandlerBase.__init__(self, req)
        self._requestStarted = False
        self._websession = None
        self._aw = AccessWrapper()  #Fill in the aw instance with the current information
        self._target = None
        self._reqParams = {}
        self._startTime = None
        self._endTime = None
        self._tempFilesToDelete = []
        self._doProcess = True  #Flag which indicates whether the RH process
                                #   must be carried out; this is useful for
                                #   the checkProtection methods when they
                                #   detect that an inmediate redirection is
                                #   needed

    # Methods =============================================================

    def getTarget( self ):
        return self._target

    def _setSession( self ):
        """Sets up a reference to the corresponding web session. It uses the
            session manager to retrieve the session corresponding to the
            received request and makes sure it is a valid one. In case of having
            an invalid session it reset client settings and creates a new one.
       """
        if not self._websession:
            sm = session.getSessionManager()
            try:
                self._websession = sm.get_session( self._req )
            except session.SessionError:
                sm.revoke_session_cookie( self._req )
                self._websession = sm.get_session( self._req )

    def _getSession( self ):
        """Returns the web session associated to the received mod_python
            request.
        """
        if not self._websession:
            self._setSession()
        return self._websession

    def _setSessionUser( self ):
        """
        """
        self._aw.setUser( self._getSession().getUser() )

    def _getRequestParams( self ):
        return self._reqParams

    def getRequestParams( self ):
        return self._getRequestParams()

    def _disableCaching(self):
        """
        Disables caching, i.e. for materials
        """

        # IE doesn't seem to like 'no-cache' Cache-Control headers...
        if (re.match(r'.*MSIE.*', self._req.headers_in.get("User-Agent",""))):
            # actually, the only way to safely disable caching seems to be this one
            self._req.headers_out["Cache-Control"] = "private"
            self._req.headers_out["Expires"] = "-1"
        else:
            self._req.headers_out["Cache-Control"] = "no-store, no-cache, must-revalidate"
            self._req.headers_out["Pragma"] = "no-cache"

    def _redirect( self, targetURL, noCache=False, status=apache.HTTP_SEE_OTHER ):
        """Utility for redirecting the client web browser to the specified
            URL.
            Params:
                newURL - Target URL of the redirection
        """
        #check if there is no \r\n character to avoid http header injection

        if str(targetURL):
            if "\r" in str(targetURL) or "\n" in str(targetURL):
                raise MaKaCError(_("http header CRLF injection detected"))
        self._req.headers_out["Location"] = str(targetURL)

        if noCache:
            self._disableCaching()
        try:
            self._req.status = status
        except NameError:
            pass

    def _checkHttpsRedirect(self):
        """
        If HTTPS must be used but it is not, redirect!
        """
        if self.use_https() and not self._req.is_https():
            self._redirect(self.getRequestURL(secure=True))
            return True
        else:
            return False

    def _normaliseListParam( self, param ):
        if not isinstance(param, list):
                return [ param ]
        return param

    def _processError( self, ex ):
        """
        """
        raise

    def _checkParams( self, params ):
        """
        """
        pass

    def _process( self ):
        """
        """
        pass

    def _processGeneralError(self,e):
        """Treats general errors occured during the process of a RH.
        """

        Logger.get('requestHandler').info('Request %s finished with: "%s"' % (id(self._req), e))

        p=errors.WPGenericError(self)
        return p.display()

    def _processUnexpectedError(self,e):
        """Unexpected errors
        """

        Logger.get('requestHandler').exception('Request %s failed: "%s"' % (id(self._req), e))
        p=errors.WPUnexpectedError(self)
        return p.display()

    def _processHostnameResolveError(self,e):
        """Unexpected errors
        """

        Logger.get('requestHandler').exception('Request %s failed: "%s"' % (id(self._req), e))
        p=errors.WPHostnameResolveError(self)
        return p.display()


    def _processAccessError(self,e):
        """Treats access errors occured during the process of a RH.
        """
        Logger.get('requestHandler').info('Request %s finished with AccessError: "%s"' % (id(self._req), e))

        self._req.status = apache.HTTP_FORBIDDEN
        p=errors.WPAccessError(self)
        return p.display()

    def _processKeyAccessError(self,e):
        """Treats access errors occured during the process of a RH.
        """
        Logger.get('requestHandler').info('Request %s finished with KeyAccessError: "%s"' % (id(self._req), e))

        self._req.status = apache.HTTP_FORBIDDEN
        # We are going to redirect to the page asking for access key
        # and so it must be https if there is a BaseSecureURL. And that's
        # why we set _tohttps to True.
        self._tohttps = True
        if self._checkHttpsRedirect():
            return
        p=errors.WPKeyAccessError(self)
        return p.display()

    def _processModificationError(self,e):
        """Treats modification errors occured during the process of a RH.
        """

        Logger.get('requestHandler').info('Request %s finished with ModificationError: "%s"' % (id(self._req), e))

        p=errors.WPModificationError(self)
        return p.display()

    def _processConferenceClosedError(self,e):
        """Treats access to modification pages for conferences when they are closed.
        """
        p = WPConferenceModificationClosed( self, e._conf )
        return p.display()

    def _processTimingError(self,e):
        """Treats timing errors occured during the process of a RH.
        """

        Logger.get('requestHandler').info('Request %s finished with TimingError: "%s"' % (id(self._req), e))

        p=errors.WPTimingError(self,e)
        return p.display()

    def _processNoReportError(self,e):
        """Process errors without reporting
        """

        Logger.get('requestHandler').info('Request %s finished with NoReportError: "%s"' % (id(self._req), e))

        p=errors.WPNoReportError(self,e)
        return p.display()

    def _processNotFoundError(self,e):
        """Process not found error; uses NoReportError template
        """

        Logger.get('requestHandler').info('Request %s finished with NotFoundError: "%s"' % (id(self._req), e))

        try:
            self._req.status = apache.HTTP_NOT_FOUND
        except NameError:
            pass

        p=errors.WPNoReportError(self,e)
        return p.display()

    def _processParentTimingError(self,e):
        """Treats timing errors occured during the process of a RH.
        """

        Logger.get('requestHandler').info('Request %s finished with ParentTimingError: "%s"' % (id(self._req), e))

        p=errors.WPParentTimingError(self,e)
        return p.display()

    def _processEntryTimingError(self,e):
        """Treats timing errors occured during the process of a RH.
        """

        Logger.get('requestHandler').info('Request %s finished with EntryTimingError: "%s"' % (id(self._req), e))

        p=errors.WPEntryTimingError(self,e)
        return p.display()

    def _processFormValuesError(self,e):
        """Treats user input related errors occured during the process of a RH.
        """

        Logger.get('requestHandler').info('Request %s finished with FormValuesError: "%s"' % (id(self._req), e))

        p=errors.WPFormValuesError(self,e)
        return p.display()

    def _processHtmlScriptError(self, e):

        Logger.get('requestHandler').info('Request %s finished with ProcessHtmlScriptError: "%s"' % (id(self._req), e))

        p=errors.WPHtmlScriptError(self, escape(str(e)))
        return p.display()

    def _processRestrictedHTML(self, e):

        Logger.get('requestHandler').info('Request %s finished with ProcessRestrictedHTMLError: "%s"' % (id(self._req), e))

        p=errors.WPRestrictedHTML(self, escape(str(e)))
        return p.display()

    def process( self, params ):
        """
        """
        profile = Config.getInstance().getProfile()
        proffilename = ""
        res = ""
        MAX_RETRIES = 10
        retry = MAX_RETRIES
        textLog = []
        self._startTime = datetime.now()

        # clear the context
        ContextManager.destroy()
        ContextManager.set('currentRH', self)

        #redirect to https if necessary
        if self._checkHttpsRedirect():
            return


        DBMgr.getInstance().startRequest()
        self._startRequestSpecific2RH()     # I.e. implemented by Room Booking request handlers
        textLog.append("%s : Database request started"%(datetime.now() - self._startTime))
        Logger.get('requestHandler').info('[pid=%s] Request %s started (%s)' % (os.getpid(),id(self._req), self._req.unparsed_uri))

        # notify components that the request has started
        self._notify('requestStarted', self._req)

        forcedConflicts = Config.getInstance().getForceConflicts()
        try:
            while retry>0:

                if retry < MAX_RETRIES:
                    # notify components that the request is being retried
                    self._notify('requestRetry', self._req, MAX_RETRIES - retry)

                try:
                    Logger.get('requestHandler').info('\t[pid=%s] from host %s' % (os.getpid(), self.getHostIP()))
                    try:
                        # clear the fossile cache at the start of each request
                        fossilize.clearCache()
                        # delete all queued emails
                        GenericMailer.flushQueue(False)

                        DBMgr.getInstance().sync()
                        # keep a link to the web session in the access wrapper
                        # this is used for checking access/modification key existence
                        # in the user session
                        self._aw.setIP( self.getHostIP() )
                        self._aw.setSession(self._getSession())
                        #raise(str(dir(self._websession)))
                        self._setSessionUser()
                        self._setLang(params)
                        if self._getAuth():
                            if self._getUser():
                                Logger.get('requestHandler').info('Request %s identified with user %s (%s)' % (id(self._req), self._getUser().getFullName(), self._getUser().getId()))
                            if not self._tohttps and Config.getInstance().getAuthenticatedEnforceSecure():
                                self._tohttps = True
                                if self._checkHttpsRedirect():
                                    return

                        #if self._getUser() != None and self._getUser().getId() == "893":
                        #    profile = True
                        self._reqParams = copy.copy( params )
                        self._checkParams( self._reqParams )

                        self._checkProtection()
                        security.Sanitization.sanitizationCheck(self._target,
                                               self._reqParams,
                                               self._aw, self._doNotSanitizeFields)
                        if self._doProcess:
                            if profile:
                                import profile, pstats
                                proffilename = os.path.join(Config.getInstance().getTempDir(), "stone%s.prof" % str(random.random()))
                                result = [None]
                                profile.runctx("result[0] = self._process()", globals(), locals(), proffilename)
                                res = result[0]
                            else:
                                res = self._process()

                        # Save web session, just when needed
                        sm = session.getSessionManager()
                        sm.maintain_session(self._req, self._websession)

                        # notify components that the request has finished
                        self._notify('requestFinished', self._req)
                        # Raise a conflict error if enabled. This allows detecting conflict-related issues easily.
                        if retry > (MAX_RETRIES - forcedConflicts):
                            raise ConflictError
                        self._endRequestSpecific2RH( True ) # I.e. implemented by Room Booking request handlers
                        DBMgr.getInstance().endRequest( True )

                        Logger.get('requestHandler').info('Request %s successful' % (id(self._req)))
                        #request succesfull, now, doing tas that must be done only once
                        try:
                            GenericMailer.flushQueue(True) # send emails
                            self._deleteTempFiles()
                        except:
                            Logger.get('mail').exception('Mail sending operation failed')
                            pass
                        break
                    except MaKaCError, e:
                        #DBMgr.getInstance().endRequest(False)
                        res = self._processError(e)
                except (ConflictError, POSKeyError):
                    import traceback
                    # only log conflict if it wasn't forced
                    if retry <= (MAX_RETRIES - forcedConflicts):
                        Logger.get('requestHandler').warning('Conflict in Database! (Request %s)\n%s' % (id(self._req), traceback.format_exc()))
                    self._abortSpecific2RH()
                    DBMgr.getInstance().abort()
                    retry -= 1
                    continue
                except ClientDisconnected:
                    Logger.get('requestHandler').warning('Client Disconnected! (Request %s)' % id(self._req) )
                    self._abortSpecific2RH()
                    DBMgr.getInstance().abort()
                    retry -= 1
                    time.sleep(10-retry)
                    continue
        except KeyAccessError, e:
            #Key Access error treatment
            res = self._processKeyAccessError( e )
            self._endRequestSpecific2RH( False )
            DBMgr.getInstance().endRequest(False)
        except AccessError, e:
            #Access error treatment
            res = self._processAccessError( e )
            self._endRequestSpecific2RH( False )
            DBMgr.getInstance().endRequest(False)
Example #2
0
class ServiceBase(RequestHandlerBase):
    """
    The ServiceBase class is the basic class for services.
    """

    def __init__(self, params, session, req):
        """
        Constructor.  Initializes provate variables
        @param req: HTTP Request provided by the previous layer
        """
        RequestHandlerBase.__init__(self, req)
        self._reqParams = self._params = params
        self._requestStarted = False
        self._websession = session
        # Fill in the aw instance with the current information
        self._aw = AccessWrapper()
        self._aw.setIP(self.getHostIP())
        self._aw.setSession(session)
        self._aw.setUser(session.getUser())
        self._target = None
        self._startTime = None
        self._tohttps = self._req.is_https()
        self._endTime = None
        self._doProcess = True  #Flag which indicates whether the RH process
                                #   must be carried out; this is useful for
                                #   the checkProtection methods
        self._tempFilesToDelete = []

    # Methods =============================================================

    def _getSession( self ):
        """
        Returns the web session associated to the received mod_python
        request.
        """
        return self._websession

    def _checkParams(self):
        """
        Checks the request parameters (normally overloaded)
        """
        pass

    def _checkProtection( self ):
        """
        Checks protection when accessing resources (normally overloaded)
        """
        pass

    def _processError(self):
        """
        Treats errors occured during the process of a RH, returning an error string.
        @param e: the exception
        @type e: An Exception-derived type
        """

        trace = traceback.format_exception(*sys.exc_info())

        return ''.join(trace)

    def _deleteTempFiles( self ):
        if len(self._tempFilesToDelete) > 0:
            for file in self._tempFilesToDelete:
                os.remove(file)

    def process(self):
        """
        Processes the request, analyzing the parameters, and feeding them to the
        _getAnswer() method (implemented by derived classes)
        """

        ContextManager.set('currentRH', self)

        self._setLang()
        self._checkParams()
        self._checkProtection()

        try:
            security.Sanitization.sanitizationCheck(self._target,
                                   self._params,
                                   self._aw)
        except (HtmlScriptError, HtmlForbiddenTag), e:
            raise HTMLSecurityError('ERR-X0','HTML Security problem. %s ' % str(e))

        if self._doProcess:
            if Config.getInstance().getProfile():
                import profile, pstats, random
                proffilename = os.path.join(Config.getInstance().getTempDir(), "service%s.prof" % random.random())
                result = [None]
                profile.runctx("result[0] = self._getAnswer()", globals(), locals(), proffilename)
                answer = result[0]
                rep = Config.getInstance().getTempDir()
                stats = pstats.Stats(proffilename)
                stats.strip_dirs()
                stats.sort_stats('cumulative', 'time', 'calls')
                stats.dump_stats(os.path.join(rep, "IndicoServiceRequestProfile.log"))
                os.remove(proffilename)
            else:
                answer = self._getAnswer()
            self._deleteTempFiles()

            return answer
Example #3
0
class ServiceBase(RequestHandlerBase):
    """
    The ServiceBase class is the basic class for services.
    """
    def __init__(self, params, session, req):
        """
        Constructor.  Initializes provate variables
        @param req: HTTP Request provided by the previous layer
        """
        RequestHandlerBase.__init__(self, req)
        self._reqParams = self._params = params
        self._requestStarted = False
        self._websession = session
        # Fill in the aw instance with the current information
        self._aw = AccessWrapper()
        self._aw.setIP(self.getHostIP())
        self._aw.setSession(session)
        self._aw.setUser(session.getUser())
        self._target = None
        self._startTime = None
        self._tohttps = self._req.is_https()
        self._endTime = None
        self._doProcess = True  #Flag which indicates whether the RH process
        #   must be carried out; this is useful for
        #   the checkProtection methods
        self._tempFilesToDelete = []

    # Methods =============================================================

    def _getSession(self):
        """
        Returns the web session associated to the received mod_python
        request.
        """
        return self._websession

    def _checkParams(self):
        """
        Checks the request parameters (normally overloaded)
        """
        pass

    def _checkProtection(self):
        """
        Checks protection when accessing resources (normally overloaded)
        """
        pass

    def _processError(self):
        """
        Treats errors occured during the process of a RH, returning an error string.
        @param e: the exception
        @type e: An Exception-derived type
        """

        trace = traceback.format_exception(*sys.exc_info())

        return ''.join(trace)

    def _deleteTempFiles(self):
        if len(self._tempFilesToDelete) > 0:
            for file in self._tempFilesToDelete:
                os.remove(file)

    def process(self):
        """
        Processes the request, analyzing the parameters, and feeding them to the
        _getAnswer() method (implemented by derived classes)
        """

        ContextManager.set('currentRH', self)

        self._setLang()
        self._checkParams()
        self._checkProtection()

        try:
            security.Sanitization.sanitizationCheck(self._target, self._params,
                                                    self._aw)
        except (HtmlScriptError, HtmlForbiddenTag), e:
            raise HTMLSecurityError('ERR-X0',
                                    'HTML Security problem. %s ' % str(e))

        if self._doProcess:
            if Config.getInstance().getProfile():
                import profile, pstats, random
                proffilename = os.path.join(Config.getInstance().getTempDir(),
                                            "service%s.prof" % random.random())
                result = [None]
                profile.runctx("result[0] = self._getAnswer()", globals(),
                               locals(), proffilename)
                answer = result[0]
                rep = Config.getInstance().getTempDir()
                stats = pstats.Stats(proffilename)
                stats.strip_dirs()
                stats.sort_stats('cumulative', 'time', 'calls')
                stats.dump_stats(
                    os.path.join(rep, "IndicoServiceRequestProfile.log"))
                os.remove(proffilename)
            else:
                answer = self._getAnswer()
            self._deleteTempFiles()

            return answer
Example #4
0
class ServiceBase(RequestHandlerBase):
    """
    The ServiceBase class is the basic class for services.
    """
    def __init__(self, params, remoteHost, session):
        """
        Constructor.  Initializes provate variables
        @param req: HTTP Request provided by the previous layer
        """
        self._params = params
        self._requestStarted = False
        self._websession = session
        # Fill in the aw instance with the current information
        self._aw = AccessWrapper()
        self._aw.setIP(remoteHost)
        self._aw.setSession(session)
        self._aw.setUser(session.getUser())
        self._target = None
        self._startTime = None
        self._endTime = None
        self._doProcess = True  #Flag which indicates whether the RH process
        #   must be carried out; this is useful for
        #   the checkProtection methods
        self._tempFilesToDelete = []

    # Methods =============================================================

    def _getSession(self):
        """
        Returns the web session associated to the received mod_python 
        request.
        """
        return self._websession

    def _checkParams(self):
        """
        Checks the request parameters (normally overloaded)
        """
        pass

    def _checkProtection(self):
        """
        Checks protection when accessing resources (normally overloaded)
        """
        pass

    def _processError(self):
        """
        Treats errors occured during the process of a RH, returning an error string.
        @param e: the exception
        @type e: An Exception-derived type
        """

        trace = traceback.format_exception(*sys.exc_info())

        return ''.join(trace)

    def _sendEmails(self):
        if hasattr(self, "_emailsToBeSent"):
            for email in self._emailsToBeSent:
                GenericMailer.send(GenericNotification(email))

    def _deleteTempFiles(self):
        if len(self._tempFilesToDelete) > 0:
            for file in self._tempFilesToDelete:
                os.remove(file)

    def process(self):
        """
        Processes the request, analyzing the parameters, and feeding them to the
        _getAnswer() method (implemented by derived classes)
        """

        self._setLang()
        self._checkParams()
        self._checkProtection()

        try:
            security.sanitizationCheck(self._target, self._params, self._aw)
        except (htmlScriptError, htmlForbiddenTag), e:
            raise HTMLSecurityError(
                'ERR-X0',
                'HTML Security problem - you might be using forbidden tags: %s '
                % str(e))

        if self._doProcess:
            answer = self._getAnswer()

            self._sendEmails()
            self._deleteTempFiles()

            return answer
Example #5
0
class RH(RequestHandlerBase):
    """This class is the base for request handlers of the application. A request
        handler will be instantiated when a web request arrives to mod_python;
        the mp layer will forward the request to the corresponding request
        handler which will know which action has to be performed (displaying a
        web page or performing some operation and redirecting to another page).
        Request handlers will be responsible for parsing the parameters coming
        from a mod_python request, handle the errors which occurred during the
        action to perform, managing the sessions, checking security for each
        operation (thus they implement the access control system of the web
        interface).
        It is important to encapsulate all this here as in case of changing
        the web application framework we'll just need to adapt this layer (the
        rest of the system wouldn't need any change).

        Attributes:
            _uh - (URLHandler) Associated URLHandler which points to the
                current rh.
            _req - (mod_python.Request) mod_python request received for the
                current rh.
            _requestStarted - (bool) Flag which tells whether a DB transaction
                has been started or not.
            _websession - ( webinterface.session.sessionManagement.PSession )
                Web session associated to the HTTP request.
            _aw - (AccessWrapper) Current access information for the rh.
            _target - (Locable) Reference to an object which is the destination
                of the operations needed to carry out the rh. If set it must
                provide (through the standard Locable interface) the methods
                to get the url parameters in order to reproduce the access to
                the rh.
            _reqParams - (dict) Dictionary containing the received HTTP
                 parameters (independently of the method) transformed into
                 python data types. The key is the parameter name while the
                 value should be the received paramter value (or values).
    """
    _tohttps = False  # set this value to True for the RH that must be HTTPS when there is a BaseSecureURL
    _doNotSanitizeFields = []

    def __init__(self, req):
        """Constructor. Initialises the rh setting up basic attributes so it is
            able to process the request.

            Parameters:
                req - (mod_python.Request) mod_python request received for the
                    current rh.
        """
        RequestHandlerBase.__init__(self, req)
        self._requestStarted = False
        self._websession = None
        self._aw = AccessWrapper(
        )  #Fill in the aw instance with the current information
        self._target = None
        self._reqParams = {}
        self._startTime = None
        self._endTime = None
        self._tempFilesToDelete = []
        self._doProcess = True  #Flag which indicates whether the RH process
        #   must be carried out; this is useful for
        #   the checkProtection methods when they
        #   detect that an inmediate redirection is
        #   needed

    # Methods =============================================================

    def getTarget(self):
        return self._target

    def _setSession(self):
        """Sets up a reference to the corresponding web session. It uses the
            session manager to retrieve the session corresponding to the
            received request and makes sure it is a valid one. In case of having
            an invalid session it reset client settings and creates a new one.
       """
        if not self._websession:
            sm = session.getSessionManager()
            try:
                self._websession = sm.get_session(self._req)
            except session.SessionError:
                sm.revoke_session_cookie(self._req)
                self._websession = sm.get_session(self._req)

    def _getSession(self):
        """Returns the web session associated to the received mod_python
            request.
        """
        if not self._websession:
            self._setSession()
        return self._websession

    def _setSessionUser(self):
        """
        """
        self._aw.setUser(self._getSession().getUser())

    def _getRequestParams(self):
        return self._reqParams

    def getRequestParams(self):
        return self._getRequestParams()

    def _disableCaching(self):
        """
        Disables caching, i.e. for materials
        """

        # IE doesn't seem to like 'no-cache' Cache-Control headers...
        if (re.match(r'.*MSIE.*', self._req.headers_in.get("User-Agent", ""))):
            # actually, the only way to safely disable caching seems to be this one
            self._req.headers_out["Cache-Control"] = "private"
            self._req.headers_out["Expires"] = "-1"
        else:
            self._req.headers_out[
                "Cache-Control"] = "no-store, no-cache, must-revalidate"
            self._req.headers_out["Pragma"] = "no-cache"

    def _redirect(self,
                  targetURL,
                  noCache=False,
                  status=apache.HTTP_SEE_OTHER):
        """Utility for redirecting the client web browser to the specified
            URL.
            Params:
                newURL - Target URL of the redirection
        """
        #check if there is no \r\n character to avoid http header injection

        if str(targetURL):
            if "\r" in str(targetURL) or "\n" in str(targetURL):
                raise MaKaCError(_("http header CRLF injection detected"))
        self._req.headers_out["Location"] = str(targetURL)

        if noCache:
            self._disableCaching()
        try:
            self._req.status = status
        except NameError:
            pass

    def _checkHttpsRedirect(self):
        """
        If HTTPS must be used but it is not, redirect!
        """
        if self.use_https() and not self._req.is_https():
            self._redirect(self.getRequestURL(secure=True))
            return True
        else:
            return False

    def _normaliseListParam(self, param):
        if not isinstance(param, list):
            return [param]
        return param

    def _processError(self, ex):
        """
        """
        raise

    def _checkParams(self, params):
        """
        """
        pass

    def _process(self):
        """
        """
        pass

    def _processGeneralError(self, e):
        """Treats general errors occured during the process of a RH.
        """

        Logger.get('requestHandler').info('Request %s finished with: "%s"' %
                                          (id(self._req), e))

        p = errors.WPGenericError(self)
        return p.display()

    def _processUnexpectedError(self, e):
        """Unexpected errors
        """

        Logger.get('requestHandler').exception('Request %s failed: "%s"' %
                                               (id(self._req), e))
        p = errors.WPUnexpectedError(self)
        return p.display()

    def _processHostnameResolveError(self, e):
        """Unexpected errors
        """

        Logger.get('requestHandler').exception('Request %s failed: "%s"' %
                                               (id(self._req), e))
        p = errors.WPHostnameResolveError(self)
        return p.display()

    def _processAccessError(self, e):
        """Treats access errors occured during the process of a RH.
        """
        Logger.get('requestHandler').info(
            'Request %s finished with AccessError: "%s"' % (id(self._req), e))

        self._req.status = apache.HTTP_FORBIDDEN
        p = errors.WPAccessError(self)
        return p.display()

    def _processKeyAccessError(self, e):
        """Treats access errors occured during the process of a RH.
        """
        Logger.get('requestHandler').info(
            'Request %s finished with KeyAccessError: "%s"' %
            (id(self._req), e))

        self._req.status = apache.HTTP_FORBIDDEN
        # We are going to redirect to the page asking for access key
        # and so it must be https if there is a BaseSecureURL. And that's
        # why we set _tohttps to True.
        self._tohttps = True
        if self._checkHttpsRedirect():
            return
        p = errors.WPKeyAccessError(self)
        return p.display()

    def _processModificationError(self, e):
        """Treats modification errors occured during the process of a RH.
        """

        Logger.get('requestHandler').info(
            'Request %s finished with ModificationError: "%s"' %
            (id(self._req), e))

        p = errors.WPModificationError(self)
        return p.display()

    def _processConferenceClosedError(self, e):
        """Treats access to modification pages for conferences when they are closed.
        """
        p = WPConferenceModificationClosed(self, e._conf)
        return p.display()

    def _processTimingError(self, e):
        """Treats timing errors occured during the process of a RH.
        """

        Logger.get('requestHandler').info(
            'Request %s finished with TimingError: "%s"' % (id(self._req), e))

        p = errors.WPTimingError(self, e)
        return p.display()

    def _processNoReportError(self, e):
        """Process errors without reporting
        """

        Logger.get('requestHandler').info(
            'Request %s finished with NoReportError: "%s"' %
            (id(self._req), e))

        p = errors.WPNoReportError(self, e)
        return p.display()

    def _processNotFoundError(self, e):
        """Process not found error; uses NoReportError template
        """

        Logger.get('requestHandler').info(
            'Request %s finished with NotFoundError: "%s"' %
            (id(self._req), e))

        try:
            self._req.status = apache.HTTP_NOT_FOUND
        except NameError:
            pass

        p = errors.WPNoReportError(self, e)
        return p.display()

    def _processParentTimingError(self, e):
        """Treats timing errors occured during the process of a RH.
        """

        Logger.get('requestHandler').info(
            'Request %s finished with ParentTimingError: "%s"' %
            (id(self._req), e))

        p = errors.WPParentTimingError(self, e)
        return p.display()

    def _processEntryTimingError(self, e):
        """Treats timing errors occured during the process of a RH.
        """

        Logger.get('requestHandler').info(
            'Request %s finished with EntryTimingError: "%s"' %
            (id(self._req), e))

        p = errors.WPEntryTimingError(self, e)
        return p.display()

    def _processFormValuesError(self, e):
        """Treats user input related errors occured during the process of a RH.
        """

        Logger.get('requestHandler').info(
            'Request %s finished with FormValuesError: "%s"' %
            (id(self._req), e))

        p = errors.WPFormValuesError(self, e)
        return p.display()

    def _processHtmlScriptError(self, e):

        Logger.get('requestHandler').info(
            'Request %s finished with ProcessHtmlScriptError: "%s"' %
            (id(self._req), e))

        p = errors.WPHtmlScriptError(self, escape(str(e)))
        return p.display()

    def _processRestrictedHTML(self, e):

        Logger.get('requestHandler').info(
            'Request %s finished with ProcessRestrictedHTMLError: "%s"' %
            (id(self._req), e))

        p = errors.WPRestrictedHTML(self, escape(str(e)))
        return p.display()

    def process(self, params):
        """
        """
        profile = Config.getInstance().getProfile()
        proffilename = ""
        res = ""
        MAX_RETRIES = 10
        retry = MAX_RETRIES
        textLog = []
        self._startTime = datetime.now()

        # clear the context
        ContextManager.destroy()
        ContextManager.set('currentRH', self)

        #redirect to https if necessary
        if self._checkHttpsRedirect():
            return

        DBMgr.getInstance().startRequest()
        self._startRequestSpecific2RH(
        )  # I.e. implemented by Room Booking request handlers
        textLog.append("%s : Database request started" %
                       (datetime.now() - self._startTime))
        Logger.get('requestHandler').info(
            '[pid=%s] Request %s started (%s)' %
            (os.getpid(), id(self._req), self._req.unparsed_uri))

        # notify components that the request has started
        self._notify('requestStarted', self._req)

        forcedConflicts = Config.getInstance().getForceConflicts()
        try:
            while retry > 0:

                if retry < MAX_RETRIES:
                    # notify components that the request is being retried
                    self._notify('requestRetry', self._req,
                                 MAX_RETRIES - retry)

                try:
                    Logger.get('requestHandler').info(
                        '\t[pid=%s] from host %s' %
                        (os.getpid(), self.getHostIP()))
                    try:
                        # clear the fossile cache at the start of each request
                        fossilize.clearCache()
                        # delete all queued emails
                        GenericMailer.flushQueue(False)

                        DBMgr.getInstance().sync()
                        # keep a link to the web session in the access wrapper
                        # this is used for checking access/modification key existence
                        # in the user session
                        self._aw.setIP(self.getHostIP())
                        self._aw.setSession(self._getSession())
                        #raise(str(dir(self._websession)))
                        self._setSessionUser()
                        self._setLang(params)
                        if self._getAuth():
                            if self._getUser():
                                Logger.get('requestHandler').info(
                                    'Request %s identified with user %s (%s)' %
                                    (id(self._req),
                                     self._getUser().getFullName(),
                                     self._getUser().getId()))
                            if not self._tohttps and Config.getInstance(
                            ).getAuthenticatedEnforceSecure():
                                self._tohttps = True
                                if self._checkHttpsRedirect():
                                    return

                        #if self._getUser() != None and self._getUser().getId() == "893":
                        #    profile = True
                        self._reqParams = copy.copy(params)
                        self._checkParams(self._reqParams)

                        self._checkProtection()
                        security.Sanitization.sanitizationCheck(
                            self._target, self._reqParams, self._aw,
                            self._doNotSanitizeFields)
                        if self._doProcess:
                            if profile:
                                import profile, pstats
                                proffilename = os.path.join(
                                    Config.getInstance().getTempDir(),
                                    "stone%s.prof" % str(random.random()))
                                result = [None]
                                profile.runctx("result[0] = self._process()",
                                               globals(), locals(),
                                               proffilename)
                                res = result[0]
                            else:
                                res = self._process()

                        # Save web session, just when needed
                        sm = session.getSessionManager()
                        sm.maintain_session(self._req, self._websession)

                        # notify components that the request has finished
                        self._notify('requestFinished', self._req)
                        # Raise a conflict error if enabled. This allows detecting conflict-related issues easily.
                        if retry > (MAX_RETRIES - forcedConflicts):
                            raise ConflictError
                        self._endRequestSpecific2RH(
                            True
                        )  # I.e. implemented by Room Booking request handlers
                        DBMgr.getInstance().endRequest(True)

                        Logger.get('requestHandler').info(
                            'Request %s successful' % (id(self._req)))
                        #request succesfull, now, doing tas that must be done only once
                        try:
                            GenericMailer.flushQueue(True)  # send emails
                            self._deleteTempFiles()
                        except:
                            Logger.get('mail').exception(
                                'Mail sending operation failed')
                            pass
                        break
                    except MaKaCError, e:
                        #DBMgr.getInstance().endRequest(False)
                        res = self._processError(e)
                except (ConflictError, POSKeyError):
                    import traceback
                    # only log conflict if it wasn't forced
                    if retry <= (MAX_RETRIES - forcedConflicts):
                        Logger.get('requestHandler').warning(
                            'Conflict in Database! (Request %s)\n%s' %
                            (id(self._req), traceback.format_exc()))
                    self._abortSpecific2RH()
                    DBMgr.getInstance().abort()
                    retry -= 1
                    continue
                except ClientDisconnected:
                    Logger.get('requestHandler').warning(
                        'Client Disconnected! (Request %s)' % id(self._req))
                    self._abortSpecific2RH()
                    DBMgr.getInstance().abort()
                    retry -= 1
                    time.sleep(10 - retry)
                    continue
        except KeyAccessError, e:
            #Key Access error treatment
            res = self._processKeyAccessError(e)
            self._endRequestSpecific2RH(False)
            DBMgr.getInstance().endRequest(False)
        except AccessError, e:
            #Access error treatment
            res = self._processAccessError(e)
            self._endRequestSpecific2RH(False)
            DBMgr.getInstance().endRequest(False)
Example #6
0
class ServiceBase(RequestHandlerBase):    
    """
    The ServiceBase class is the basic class for services.
    """    
    
    def __init__(self, params, remoteHost, session):
        """
        Constructor.  Initializes provate variables
        @param req: HTTP Request provided by the previous layer
        """
        self._params = params
        self._requestStarted = False
        self._websession = session
        # Fill in the aw instance with the current information
        self._aw = AccessWrapper()
        self._aw.setIP(remoteHost)
        self._aw.setSession(session)
        self._aw.setUser(session.getUser())
        self._target = None
        self._startTime = None
        self._endTime = None
        self._doProcess = True  #Flag which indicates whether the RH process
                                #   must be carried out; this is useful for
                                #   the checkProtection methods
        self._tempFilesToDelete = []
    
    # Methods =============================================================
        
    def _getSession( self ):
        """
        Returns the web session associated to the received mod_python 
        request.
        """
        return self._websession
    
    def _checkParams(self):
        """
        Checks the request parameters (normally overloaded)
        """
        pass
    
    def _checkProtection( self ):
        """
        Checks protection when accessing resources (normally overloaded)
        """
        pass

    def _processError(self):
        """
        Treats errors occured during the process of a RH, returning an error string.
        @param e: the exception
        @type e: An Exception-derived type
        """
        
        trace = traceback.format_exception(*sys.exc_info())
        
        return ''.join(trace)

    def _sendEmails( self ):
        if hasattr( self, "_emailsToBeSent" ):
            for email in self._emailsToBeSent:
                GenericMailer.send(GenericNotification(email))

    def _deleteTempFiles( self ):
        if len(self._tempFilesToDelete) > 0:
            for file in self._tempFilesToDelete:
                os.remove(file)
      
    def process(self):
        """
        Processes the request, analyzing the parameters, and feeding them to the
        _getAnswer() method (implemented by derived classes)
        """

        self._setLang()
        self._checkParams()
        self._checkProtection()

        try:
            security.sanitizationCheck(self._target,
                                   self._params,
                                   self._aw)
        except (htmlScriptError, htmlForbiddenTag), e:
            raise HTMLSecurityError('ERR-X0','HTML Security problem - you might be using forbidden tags: %s ' % str(e))
            
        if self._doProcess:
            answer = self._getAnswer()

            self._sendEmails()
            self._deleteTempFiles()
            
            return answer