Beispiel #1
0
    def resolve_href(self, req, resp, log):
        """Figure out the theme URL given a request and response.

        This calls the pyref, or does URI template substitution on an
        href attribute"""
        substitute = True
        if self.pyref:
            if not execute_pyref(req):
                log.error(
                    self, "Security disallows executing pyref %s" % self.pyref)
                ## FIXME: this isn't very good; fatal exception?:
                href = self.href
            else:
                href = self.pyref(req, resp, log)
                substitute = False
        else:
            href = self.href
        if substitute:
            vars = NestedDict(req.environ, req.headers, 
                              dict(here=posixpath.dirname(self.source_location)))
            new_href = uri_template_substitute(href, vars)
            if new_href != href:
                log.debug(
                    self, 'Rewrote theme href="%s" to "%s"' % (href, new_href))
                href = new_href
        ## FIXME: is this join a good idea?
        if href:
            href = urlparse.urljoin(req.url, href)
        return href
Beispiel #2
0
    def resolve_href(self, req, resp, log):
        """Figure out the theme URL given a request and response.

        This calls the pyref, or does URI template substitution on an
        href attribute"""
        substitute = True
        if self.pyref:
            if not execute_pyref(req):
                log.error(
                    self, "Security disallows executing pyref %s" % self.pyref)
                ## FIXME: this isn't very good; fatal exception?:
                href = self.href
            else:
                href = self.pyref(req, resp, log)
                substitute = False
        else:
            href = self.href
        if substitute:
            vars = NestedDict(req.environ, req.headers, 
                              dict(here=posixpath.dirname(self.source_location)))
            new_href = uri_template_substitute(href, vars)
            if new_href != href:
                log.debug(
                    self, 'Rewrote theme href="%s" to "%s"' % (href, new_href))
                href = new_href
        ## FIXME: is this join a good idea?
        if href:
            href = urllib.parse.urljoin(req.url, href)
        return href
Beispiel #3
0
 def __call__(self, request, log):
     """Determine the destination given the request"""
     assert not self.next
     if self.pyref:
         if not execute_pyref(request):
             log.error(self, "Security disallows executing pyref %s" % self.pyref)
         else:
             return self.pyref(request, log)
     ## FIXME: is this nesting really needed?
     ## we could just use HTTP_header keys...
     vars = NestedDict(request.environ, request.headers, dict(here=posixpath.dirname(self.source_location)))
     return uri_template_substitute(self.href, vars)
Beispiel #4
0
 def __call__(self, request, log):
     """Determine the destination given the request"""
     assert not self.__next__
     if self.pyref:
         if not execute_pyref(request):
             log.error(self,
                       "Security disallows executing pyref %s" % self.pyref)
         else:
             return self.pyref(request, log)
     ## FIXME: is this nesting really needed?
     ## we could just use HTTP_header keys...
     vars = NestedDict(request.environ, request.headers,
                       dict(here=posixpath.dirname(self.source_location)))
     return uri_template_substitute(self.href, vars)
Beispiel #5
0
 def modify_request(self, request, log):
     """Apply the modification to the request"""
     if self.pyref:
         if not execute_pyref(request):
             log.error(self, "Security disallows executing pyref %s" % self.pyref)
         else:
             result = self.pyref(request, log)
             if isinstance(result, dict):
                 request = Request(result)
             elif isinstance(result, Request):
                 request = result
     if self.header:
         request.headers[self.header] = self.content
     return request
Beispiel #6
0
 def modify_request(self, request, log):
     """Apply the modification to the request"""
     if self.pyref:
         if not execute_pyref(request):
             log.error(self,
                       "Security disallows executing pyref %s" % self.pyref)
         else:
             result = self.pyref(request, log)
             if isinstance(result, dict):
                 request = Request(result)
             elif isinstance(result, Request):
                 request = result
     if self.header:
         request.headers[self.header] = self.content
     return request
Beispiel #7
0
    def modify_response(self, request, response, orig_base, proxied_base,
                        proxied_url, log):
        """
        Modify the response however the user wanted.
        """
        if proxied_base is not None and proxied_url is not None:
            # This might not have a trailing /:
            exact_proxied_base = proxied_base
            if not proxied_base.endswith('/'):
                proxied_base += '/'
            exact_orig_base = orig_base
            if not orig_base.endswith('/'):
                orig_base += '/'
            assert (
                proxied_url.startswith(proxied_base)
                or proxied_url.split('?', 1)[0] == proxied_base[:-1]
            ), ("Unexpected proxied_url %r, doesn't start with proxied_base %r"
                % (proxied_url, proxied_base))
            assert (
                request.url.startswith(orig_base)
                or request.url.split('?', 1)[0] == orig_base[:-1]
            ), ("Unexpected request.url %r, doesn't start with orig_base %r" %
                (request.url, orig_base))

        if self.pyref:
            if not execute_pyref(request):
                log.error(self,
                          "Security disallows executing pyref %s" % self.pyref)
            else:
                result = self.pyref(request, response, orig_base, proxied_base,
                                    proxied_url, log)
                if isinstance(result, Response):
                    response = result
        if self.header:
            response.headers[self.header] = self.content

        if self.rewrite_links:

            def link_repl_func(link):
                """Rewrites a link to point to this proxy"""
                if link == exact_proxied_base:
                    return exact_orig_base
                if not link.startswith(proxied_base):
                    # External link, so we don't rewrite it
                    return link
                new = orig_base + link[len(proxied_base):]
                return new

            if response.content_type != 'text/html':
                log.debug(
                    self,
                    'Not rewriting links in response from %s, because Content-Type is %s'
                    % (proxied_url, response.content_type))
            else:
                if not response.charset:
                    ## FIXME: maybe we should guess the encoding?
                    body = response.body
                else:
                    body = response.unicode_body
                if len(body) > 0:
                    body_doc = document_fromstring(body, base_url=proxied_url)
                    body_doc.make_links_absolute()
                    body_doc.rewrite_links(link_repl_func)
                    response.body = tostring(body_doc)
            if response.location:
                ## FIXME: if you give a proxy like
                ## http://openplans.org, and it redirects to
                ## http://www.openplans.org, it won't be rewritten and
                ## that can be confusing -- it *shouldn't* be
                ## rewritten, but some better log message is required
                loc = urllib.parse.urljoin(proxied_url, response.location)
                loc = link_repl_func(loc)
                response.location = loc
            if 'set-cookie' in response.headers:
                cookies = response.headers.getall('set-cookie')
                del response.headers['set-cookie']
                for cook in cookies:
                    old_domain = urllib.parse.urlsplit(proxied_url)[1].lower()
                    new_domain = request.host.split(':', 1)[0].lower()

                    def rewrite_domain(match):
                        """Rewrites domains to point to this proxy"""
                        domain = match.group(2)
                        if domain == old_domain:
                            ## FIXME: doesn't catch wildcards and the sort
                            return match.group(1) + new_domain + match.group(3)
                        else:
                            return match.group(0)

                    cook = self._cookie_domain_re.sub(rewrite_domain, cook)
                    response.headers.add('set-cookie', cook)
        return response
Beispiel #8
0
    def modify_response(self, request, response, orig_base, proxied_base, proxied_url, log):
        """
        Modify the response however the user wanted.
        """
        # This might not have a trailing /:
        exact_proxied_base = proxied_base
        if not proxied_base.endswith("/"):
            proxied_base += "/"
        exact_orig_base = orig_base
        if not orig_base.endswith("/"):
            orig_base += "/"
        assert (
            proxied_url.startswith(proxied_base) or proxied_url.split("?", 1)[0] == proxied_base[:-1]
        ), "Unexpected proxied_url %r, doesn't start with proxied_base %r" % (proxied_url, proxied_base)
        assert (
            request.url.startswith(orig_base) or request.url.split("?", 1)[0] == orig_base[:-1]
        ), "Unexpected request.url %r, doesn't start with orig_base %r" % (request.url, orig_base)
        if self.pyref:
            if not execute_pyref(request):
                log.error(self, "Security disallows executing pyref %s" % self.pyref)
            else:
                result = self.pyref(request, response, orig_base, proxied_base, proxied_url, log)
                if isinstance(result, Response):
                    response = result
        if self.header:
            response.headers[self.header] = self.content
        if self.rewrite_links:

            def link_repl_func(link):
                """Rewrites a link to point to this proxy"""
                if link == exact_proxied_base:
                    return exact_orig_base
                if not link.startswith(proxied_base):
                    # External link, so we don't rewrite it
                    return link
                new = orig_base + link[len(proxied_base) :]
                return new

            if response.content_type != "text/html":
                log.debug(
                    self,
                    "Not rewriting links in response from %s, because Content-Type is %s"
                    % (proxied_url, response.content_type),
                )
            else:
                if not response.charset:
                    ## FIXME: maybe we should guess the encoding?
                    body = response.body
                else:
                    body = response.unicode_body
                body_doc = document_fromstring(body, base_url=proxied_url)
                body_doc.make_links_absolute()
                body_doc.rewrite_links(link_repl_func)
                response.body = tostring(body_doc)
            if response.location:
                ## FIXME: if you give a proxy like
                ## http://openplans.org, and it redirects to
                ## http://www.openplans.org, it won't be rewritten and
                ## that can be confusing -- it *shouldn't* be
                ## rewritten, but some better log message is required
                loc = urlparse.urljoin(proxied_url, response.location)
                loc = link_repl_func(loc)
                response.location = loc
            if "set-cookie" in response.headers:
                cookies = response.headers.getall("set-cookie")
                del response.headers["set-cookie"]
                for cook in cookies:
                    old_domain = urlparse.urlsplit(proxied_url)[1].lower()
                    new_domain = request.host.split(":", 1)[0].lower()

                    def rewrite_domain(match):
                        """Rewrites domains to point to this proxy"""
                        domain = match.group(2)
                        if domain == old_domain:
                            ## FIXME: doesn't catch wildcards and the sort
                            return match.group(1) + new_domain + match.group(3)
                        else:
                            return match.group(0)

                    cook = self._cookie_domain_re.sub(rewrite_domain, cook)
                    response.headers.add("set-cookie", cook)
        return response
Beispiel #9
0
    def __call__(self, request, resp, response_headers, log):
        """
        Checks this match against the given request and
        response_headers object.

        `response_headers` should be a case-insensitive dictionary.
        `request` should be a :class:webob.Request object.
        """
        result = True
        debug_name = self.debug_description()
        debug_context = self.log_context()
        if self.path:
            if not self.path(request.path):
                log.debug(
                    debug_context,
                    'Skipping %s because request URL (%s) does not '
                    'match path="%s"', debug_name, request.path, self.path)
                return False
        if self.domain:
            host = request.host.split(':', 1)[0]
            if not self.domain(host):
                log.debug(
                    debug_context,
                    'Skipping %s because request domain (%s) does '
                    'not match domain="%s"', debug_name, host, self.domain)
                return False
        if self.request_header:
            result, headers = self.request_header(request.headers)
            if not result:
                log.debug(
                    debug_context,
                    'Skipping %s because request headers %s do not '
                    'match request-header="%s"', debug_name,
                    ', '.join(headers), self.request_header)
                return False
        if self.response_header:
            result, headers = self.response_header(response_headers)
            if not result:
                header_debug = []
                for header in headers:
                    header_debug.append(
                        '%s: %s' %
                        (header, response_headers.get(header, '(empty)')))
                ## FIXME: maybe distinguish <meta> headers and real headers?
                log.debug(
                    debug_context,
                    'Skipping %s because the response headers %s '
                    'do not match response-header="%s"', debug_name,
                    ', '.join(header_debug), self.response_header)
                return False
        if self.response_status:
            result = self.response_status(str(resp.status_int))
            if not result:
                log.debug(
                    debug_context,
                    'Skipping %s because response status %s do not '
                    'match request-header="%s"', debug_name, resp.status_int,
                    self.response_status)
                return False
        if self.environ:
            result, keys = self.environ(request.environ)
            if not result:
                log.debug(
                    debug_context,
                    'Skipping %s because the request environ (keys %s) '
                    'did not match environ="%s"', debug_name, ', '.join(keys),
                    self.environ)
                return False
        if self.pyref:
            if not execute_pyref(request):
                log.error(self, "Security disallows executing pyref %s")
            else:
                result = self.pyref(request, resp, response_headers, log)
                if not result:
                    log.debug(
                        debug_context,
                        'Skipping %s because the reference <%s> returned false',
                        debug_name, self.pyref)
                    return False
                if isinstance(result, str):
                    result = result.split()
                if isinstance(result, (list, tuple)):
                    return getattr(self, 'classes', []) + list(result)
        return getattr(self, 'classes', None) or True
Beispiel #10
0
    def __call__(self, request, resp, response_headers, log):
        """
        Checks this match against the given request and
        response_headers object.

        `response_headers` should be a case-insensitive dictionary.
        `request` should be a :class:webob.Request object.
        """
        result = True
        debug_name = self.debug_description()
        debug_context = self.log_context()
        if self.path:
            if not self.path(request.path):
                log.debug(
                    debug_context, 'Skipping %s because request URL (%s) does not '
                    'match path="%s"',
                    debug_name, request.path, self.path)
                return False
        if self.domain:
            host = request.host.split(':', 1)[0]
            if not self.domain(host):
                log.debug(
                    debug_context, 'Skipping %s because request domain (%s) does '
                    'not match domain="%s"',
                    debug_name, host, self.domain)
                return False
        if self.request_header:
            result, headers = self.request_header(request.headers)
            if not result:
                log.debug(
                    debug_context, 'Skipping %s because request headers %s do not '
                    'match request-header="%s"',
                    debug_name, ', '.join(headers), self.request_header)
                return False
        if self.response_header:
            result, headers = self.response_header(response_headers)
            if not result:
                header_debug = []
                for header in headers:
                    header_debug.append('%s: %s' % (header, response_headers.get(header, '(empty)')))
                ## FIXME: maybe distinguish <meta> headers and real headers?
                log.debug(
                    debug_context, 'Skipping %s because the response headers %s '
                    'do not match response-header="%s"',
                    debug_name, ', '.join(header_debug), self.response_header)
                return False
        if self.response_status:
            result = self.response_status(str(resp.status_int))
            if not result:
                log.debug(
                    debug_context, 'Skipping %s because response status %s do not '
                    'match request-header="%s"',
                    debug_name, resp.status_int, self.response_status)
                return False
        if self.environ:
            result, keys = self.environ(request.environ)
            if not result:
                log.debug(
                    debug_context, 'Skipping %s because the request environ (keys %s) '
                    'did not match environ="%s"',
                    debug_name, ', '.join(keys), self.environ)
                return False
        if self.pyref:
            if not execute_pyref(request):
                log.error(
                    self, "Security disallows executing pyref %s")
            else:
                result = self.pyref(request, resp, response_headers, log)
                if not result:
                    log.debug(
                        debug_context, 
                        'Skipping %s because the reference <%s> returned false',
                        debug_name, self.pyref)
                    return False
                if isinstance(result, basestring):
                    result = result.split()
                if isinstance(result, (list, tuple)):
                    return getattr(self, 'classes', []) + list(result)
        return getattr(self, 'classes', None) or True
Beispiel #11
0
    def modify_response(self, request, response, orig_base, proxied_base, 
                        proxied_url, log):
        """
        Modify the response however the user wanted.
        """
        # This might not have a trailing /:
        exact_proxied_base = proxied_base
        if not proxied_base.endswith('/'):
            proxied_base += '/'
        exact_orig_base = orig_base
        if not orig_base.endswith('/'):
            orig_base += '/'
        assert (proxied_url.startswith(proxied_base) 
                or proxied_url.split('?', 1)[0] == proxied_base[:-1]), (
            "Unexpected proxied_url %r, doesn't start with proxied_base %r"
            % (proxied_url, proxied_base))
        assert (request.url.startswith(orig_base) 
                or request.url.split('?', 1)[0] == orig_base[:-1]), (
            "Unexpected request.url %r, doesn't start with orig_base %r"
            % (request.url, orig_base))
        #j import pdb; pdb.set_trace()                
        if self.pyref:
            if not execute_pyref(request):
                log.error(
                    self, "Security disallows executing pyref %s" % self.pyref)
            else:
                result = self.pyref(request, response, orig_base, proxied_base, 
                                    proxied_url, log)
                if isinstance(result, Response):
                    response = result
        if self.header:
            response.headers[self.header] = self.content
        if self.rewrite_links:
            def link_repl_func(link):
                """Rewrites a link to point to this proxy"""
                if link == exact_proxied_base:
                    return exact_orig_base
                if not link.startswith(proxied_base):
                    # External link, so we don't rewrite it
                    return link
                new = orig_base + link[len(proxied_base):]
                return new
            if response.content_type != 'text/html':
                log.debug(
                    self, 
                    'Not rewriting links in response from %s, because Content-Type is %s'
                    % (proxied_url, response.content_type))
            elif not response.location:
                if not response.charset:
                    ## FIXME: maybe we should guess the encoding?
                    body = response.body
                else:
                    body = response.unicode_body
                body_doc = document_fromstring(body, base_url=proxied_url)
                body_doc.make_links_absolute()
                body_doc.rewrite_links(link_repl_func)
                response.body = tostring(body_doc)
                
            if response.location:
                ## FIXME: if you give a proxy like
                ## http://openplans.org, and it redirects to
                ## http://www.openplans.org, it won't be rewritten and
                ## that can be confusing -- it *shouldn't* be
                ## rewritten, but some better log message is required
                #import pdb; pdb.set_trace()
                loc = urlparse.urljoin(proxied_url, response.location)

                #XXX here might be a good point to clean the location of 
                #unwanted '//'                
                loc = link_repl_func(loc)

                response.location = loc
            if 'set-cookie' in response.headers:
                cookies = response.headers.getall('set-cookie')
                del response.headers['set-cookie']
               
                #stuff we need for cookie path rewriting further down
                _cookie_path_re = re.compile(r'(path="?)(\S*?)("?; )', re.I)
                orig_parts = urlparse.urlsplit(orig_base)
                orig_path = orig_parts[2]
                def rewrite_path(match):
                    """Rewrite the path of the cookie"""
                    old_path = match.group(2)
                    new_path = orig_path + old_path
                    new_path = new_path.replace('//','/')
                    return match.group(1) + new_path + match.group(3)
               
                for cook in cookies:
                    old_domain = urlparse.urlsplit(proxied_url)[1].lower()
                    new_domain = request.host.split(':', 1)[0].lower()
                    def rewrite_domain(match):
                        """Rewrites domains to point to this proxy"""
                        domain = match.group(2)
                        #import pdb; pdb.set_trace()
                        if old_domain.endswith(domain) or domain.endswith(old_domain):
                            ## FIXME: doesn't catch wildcards and the sort
                            return match.group(1) + new_domain + match.group(3)
                        else:
                            return match.group(0)
                    cook = self._cookie_domain_re.sub(rewrite_domain, cook)
                    cook = _cookie_path_re.sub(rewrite_path,cook)

                    response.headers.add('Set-Cookie', cook)
        return response