Skip to content
page_main.py 4.86 KiB
Newer Older
#!/usr/bin/python
# -*- coding: utf-8 -*-
# rdiffweb, A web interface to rdiff-backup repositories
# Copyright (C) 2014 rdiffweb contributors
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
from __future__ import absolute_import
from __future__ import unicode_literals
from builtins import bytes
Patrik Dufresne's avatar
Patrik Dufresne committed
import cherrypy
from future.utils.surrogateescape import encodefilename
Patrik Dufresne's avatar
Patrik Dufresne committed
import logging
from rdiffweb.core import Component
from rdiffweb.librdiff import RdiffRepo, DoesNotExistError
from rdiffweb.rdw_plugin import ITemplateFilterPlugin
Patrik Dufresne's avatar
Patrik Dufresne committed
# Define the logger
logger = logging.getLogger(__name__)
SEP = b'/'


def normpath(val):
    "Normalize path value"
    if not val.endswith(SEP):
        val += SEP
    if val.startswith(SEP):
        val = val[1:]
    return val


class MainPage(Component):
    def assertTrue(self, value, message=None):
        """Raise HTTP error if value is not true."""
        if not value:
            raise cherrypy.HTTPError(400, message)

    def assertIsInt(self, value, message=None):
        """Raise HTTP Error if the value is not an integer"""
        try:
            int(value)
        except:
            raise cherrypy.HTTPError(400, message)

    def assertIsInstance(self, value, cls, message=None):
        """Raise HTTP error if value is not cls."""
        if not isinstance(value, cls):
            raise cherrypy.HTTPError(400, message)

    # TODO Should be moved to different location. e.g.: user.py
Patrik Dufresne's avatar
Patrik Dufresne committed
    def validate_user_path(self, path_b):
        '''
        Takes a path relative to the user's root dir and validates that it
        is valid and within the user's root.

        Uses bytes path to avoid any data lost in encoding/decoding.
        '''
        assert isinstance(path_b, bytes)
Patrik Dufresne's avatar
Patrik Dufresne committed

        # Add a ending slash (/) to avoid matching wrong repo. Ref #56
        path_b = normpath(path_b)
Patrik Dufresne's avatar
Patrik Dufresne committed

        # NOTE: a blank path is allowed, since the user root directory might be
        logger.debug("checking user access to path %r", path_b)
Patrik Dufresne's avatar
Patrik Dufresne committed

        # Get reference to user repos (as bytes)
        user_repos = [
            normpath(encodefilename(r))
            for r in self.app.currentuser.repos]
Patrik Dufresne's avatar
Patrik Dufresne committed

        # Check if any of the repos matches the given path.
        repo_b = next((
            user_repo
Patrik Dufresne's avatar
Patrik Dufresne committed
            for user_repo in user_repos
            if path_b.startswith(user_repo)), None)
Patrik Dufresne's avatar
Patrik Dufresne committed
            # No repo matches
            logger.error("user doesn't have access to [%r]", path_b)
Patrik Dufresne's avatar
Patrik Dufresne committed

        # Get reference to user_root
        user_root_b = encodefilename(self.app.currentuser.user_root)
Patrik Dufresne's avatar
Patrik Dufresne committed

        # Get reference to the repository (this ensure the repository does
        # exists and is valid.)
        repo_obj = RdiffRepo(user_root_b, repo_b)

        # Get reference to the path.
        path_b = path_b[len(repo_b):]
        path_obj = repo_obj.get_path(path_b)

        return (repo_obj, path_obj)
        """
        Check if the cherrypy request is a POST.
        """
        return cherrypy.request.method == "POST"

    def _compile_template(self, template_name, **kwargs):
        """
        Used to generate a standard HTML page using the given template.
        This method should be used by subclasses to provide default template
        loc = cherrypy.response.i18n.locale
            "lang": loc.language,
            "version": self.app.get_version(),
            "extra_head_templates": [],
            parms.update({
                "is_login": False,
                'username': self.app.currentuser.username,
                'is_admin': self.app.currentuser.is_admin,
            })
        if hasattr(self.app.root, "header_logo"):
            parms["header_logo"] = '/header_logo'
        header_name = self.app.cfg.get_config("HeaderName")
        if header_name:
            parms["header_name"] = header_name

        # Append template parameters.

        # Filter params using plugins
        self.app.plugins.run(
            lambda x: x.filter_data(template_name, parms),
            category=ITemplateFilterPlugin.CATEGORY)

        return self.app.templates.compile_template(template_name, **parms)