コード例 #1
0
ファイル: auto.py プロジェクト: urska19/Plone-test
    def _check(self):
        registered = self._registered_objects()
        if len(registered) > 0 and \
                not IDisableCSRFProtection.providedBy(self.request):
            # Okay, we're writing here, we need to protect!
            try:
                check(self.request)
                return True
            except ComponentLookupError:
                # okay, it's possible we're at the zope root and the KeyManager
                # hasn't been installed yet. Let's check and carry on
                # if this is the case
                if IApplication.providedBy(self.getContext()):
                    LOGGER.info('skipping csrf protection on zope root until '
                                'keymanager gets installed')
                    return True
                raise
            except Forbidden:
                if self.request.REQUEST_METHOD != 'GET':
                    # only try to be "smart" with GET requests
                    raise

                # XXX
                # okay, so right now, we're going to check if the current
                # registered objects to write, are just portlet assignments.
                # I don't know why, but when a site is created, these
                # cause some writes on read. ALL, registered objects
                # need to be portlet assignments. XXX needs to be fixed
                # somehow...
                safe = True
                for obj in registered:
                    if (not IPortletAssignment.providedBy(obj) and
                            not getattr(obj, '_v_safe_write', False)):
                        safe = False
                        break
                if not safe:
                    LOGGER.info('aborting transaction due to no CSRF '
                                'protection on url %s' % self.request.URL)
                    transaction.abort()

                    # conditions for doing the confirm form are:
                    #   1. 301, 302 response code
                    #   2. text/html response
                    #   3. getSite could be none, zope root maybe, carry on
                    # otherwise,
                    #   just abort with a log entry because we tried to
                    #   write on read, without a POST request and we don't
                    #   know what to do with it gracefully.
                    resp = self.request.response
                    ct = resp.headers.get('content-type')
                    if self.site and (
                            resp.status in (301, 302) or 'text/html' in ct):
                        data = self.request.form.copy()
                        data['original_url'] = self.request.URL
                        resp.redirect('%s/@@confirm-action?%s' % (
                            self.site.absolute_url(),
                            urlencode(data)
                        ))
                        return False
        return True
コード例 #2
0
    def _check(self):
        registered = self._registered_objects()
        if len(registered) > 0 and \
                not IDisableCSRFProtection.providedBy(self.request):
            # Okay, we're writing here, we need to protect!
            try:
                check(self.request)
                return True
            except ComponentLookupError:
                # okay, it's possible we're at the zope root and the KeyManager
                # hasn't been installed yet. Let's check and carry on
                # if this is the case
                if IApplication.providedBy(self.getContext()):
                    LOGGER.info('skipping csrf protection on zope root until '
                                'keymanager gets installed')
                    return True
                raise
            except Forbidden:
                if self.request.REQUEST_METHOD != 'GET':
                    # only try to be "smart" with GET requests
                    raise

                # XXX
                # okay, so right now, we're going to check if the current
                # registered objects to write, are just portlet assignments.
                # I don't know why, but when a site is created, these
                # cause some writes on read. ALL, registered objects
                # need to be portlet assignments. XXX needs to be fixed
                # somehow...
                safe = True
                for obj in registered:
                    if (not IPortletAssignment.providedBy(obj)
                            and not getattr(obj, '_v_safe_write', False)):
                        safe = False
                        break
                if not safe:
                    LOGGER.info('aborting transaction due to no CSRF '
                                'protection on url %s' % self.request.URL)
                    transaction.abort()

                    # conditions for doing the confirm form are:
                    #   1. 301, 302 response code
                    #   2. text/html response
                    #   3. getSite could be none, zope root maybe, carry on
                    # otherwise,
                    #   just abort with a log entry because we tried to
                    #   write on read, without a POST request and we don't
                    #   know what to do with it gracefully.
                    resp = self.request.response
                    ct = resp.headers.get('content-type')
                    if self.site and (resp.status in (301, 302)
                                      or 'text/html' in ct):
                        data = self.request.form.copy()
                        data['original_url'] = self.request.URL
                        resp.redirect(
                            '%s/@@confirm-action?%s' %
                            (self.site.absolute_url(), urlencode(data)))
                        return False
        return True
コード例 #3
0
ファイル: auto.py プロジェクト: FHNW/plone.protect
    def _check(self):
        registered = self._registered_objects()
        if len(registered) > 0 and \
                not IDisableCSRFProtection.providedBy(self.request):
            # Okay, we're writing here, we need to protect!
            try:
                check(self.request, manager=self.key_manager)
                return True
            except ComponentLookupError:
                LOGGER.info('Can not find key manager for CSRF protection. '
                            'This should not happen.')
                raise
            except Forbidden:
                # XXX
                # okay, so right now, we're going to check if the current
                # registered objects to write, are just portlet assignments.
                # I don't know why, but when a site is created, these
                # cause some writes on read. ALL, registered objects
                # need to be portlet assignments. XXX needs to be fixed
                # somehow...
                safe_oids = []
                if SAFE_WRITE_KEY in getattr(self.request, 'environ', {}):
                    safe_oids = self.request.environ[SAFE_WRITE_KEY]
                safe = True
                for obj in registered:
                    if (not IPortletAssignment.providedBy(obj) and
                            getattr(obj, '_p_oid', False) not in safe_oids):
                        safe = False
                        break
                if not safe:
                    if self.request.REQUEST_METHOD != 'GET':
                        # only try to be "smart" with GET requests
                        raise

                    LOGGER.info('%s\naborting transaction due to no CSRF '
                                'protection on url %s'%(traceback.print_stack(), self.request.URL))
                    transaction.abort()

                    # conditions for doing the confirm form are:
                    #   1. 301, 302 response code
                    #   2. text/html response
                    #   3. getSite could be none, zope root maybe, carry on
                    # otherwise,
                    #   just abort with a log entry because we tried to
                    #   write on read, without a POST request and we don't
                    #   know what to do with it gracefully.
                    resp = self.request.response
                    ct = resp.getHeader('Content-Type', '') or ''
                    if self.site and (
                            resp.status in (301, 302) or 'text/html' in ct):
                        data = self.request.form.copy()
                        data['original_url'] = self.request.URL
                        resp.redirect('%s/@@confirm-action?%s' % (
                            self.site.absolute_url(),
                            urlencode(data)
                        ))
                        return False
        return True
コード例 #4
0
ファイル: protect.py プロジェクト: lukasgraf/opengever.core
 def _abort_txn_on_confirm_action_view(self):
     if self._get_current_view() == '@@confirm-action':
         if len(self._registered_objects()) > 0 and \
                 not IDisableCSRFProtection.providedBy(self.request):
             transaction.abort()
             LOG.error(
                 "Error checking for CSRF. Transaction was modified when "
                 "visiting @@confirm-action view. Transaction aborted!)")
             return True
コード例 #5
0
ファイル: protect.py プロジェクト: lukasgraf/opengever.core
 def _abort_txn_on_confirm_action_view(self):
     if self._get_current_view() == '@@confirm-action':
         if len(self._registered_objects()) > 0 and \
                 not IDisableCSRFProtection.providedBy(self.request):
             transaction.abort()
             LOG.error(
                 "Error checking for CSRF. Transaction was modified when "
                 "visiting @@confirm-action view. Transaction aborted!)")
             return True
コード例 #6
0
ファイル: auto.py プロジェクト: nilbacardit26/plone_prova
    def _check(self):
        registered = self._registered_objects()
        if len(registered) > 0 and \
                not IDisableCSRFProtection.providedBy(self.request):
            # Okay, we're writing here, we need to protect!
            try:
                check(self.request, manager=self.key_manager)
                return True
            except ComponentLookupError:
                LOGGER.info('Can not find key manager for CSRF protection. '
                            'This should not happen.')
                raise
            except Forbidden:
                # XXX
                # okay, so right now, we're going to check if the current
                # registered objects to write, are just portlet assignments.
                # I don't know why, but when a site is created, these
                # cause some writes on read. ALL, registered objects
                # need to be portlet assignments. XXX needs to be fixed
                # somehow...
                safe_oids = []
                if SAFE_WRITE_KEY in getattr(self.request, 'environ', {}):
                    safe_oids = self.request.environ[SAFE_WRITE_KEY]
                safe = True
                for obj in registered:
                    if (not IPortletAssignment.providedBy(obj) and getattr(
                            obj, '_p_oid', False) not in safe_oids):
                        safe = False
                        break
                if not safe:
                    if self.request.REQUEST_METHOD != 'GET':
                        # only try to be "smart" with GET requests
                        raise
                    LOGGER.info('aborting transaction due to no CSRF '
                                'protection on url %s' % self.request.URL)
                    transaction.abort()

                    # conditions for doing the confirm form are:
                    #   1. 301, 302 response code
                    #   2. text/html response
                    #   3. getSite could be none, zope root maybe, carry on
                    # otherwise,
                    #   just abort with a log entry because we tried to
                    #   write on read, without a POST request and we don't
                    #   know what to do with it gracefully.
                    resp = self.request.response
                    ct = resp.getHeader('Content-Type', '') or ''
                    if self.site and (resp.status in (301, 302)
                                      or 'text/html' in ct):
                        data = self.request.form.copy()
                        data['original_url'] = self.request.URL
                        resp.redirect(
                            '%s/@@confirm-action?%s' %
                            (self.site.absolute_url(), urlencode(data)))
                        return False
        return True
コード例 #7
0
    def test_after_successfully_credentials_authentication_the_request_provides_the_disable_csrf_protection_layer(self):
        ip = '192.168.1.233'
        create(Builder('admin_unit')
               .id('client1')
               .having(title=u'Client1', ip_address=ip))

        self.set_params_for_remote_request(client_ip=ip)

        creds = extract_user(self.portal, self.portal.REQUEST)
        authenticate_credentials(self.portal, creds)

        self.assertTrue(IDisableCSRFProtection.providedBy(self.portal.REQUEST))
コード例 #8
0
    def test_after_successfully_credentials_authentication_the_request_provides_the_disable_csrf_protection_layer(
            self):
        ip = '192.168.1.233'
        create(
            Builder('admin_unit').id('client1').having(title=u'Client1',
                                                       ip_address=ip))

        self.set_params_for_remote_request(client_ip=ip)

        creds = extract_user(self.portal, self.portal.REQUEST)
        authenticate_credentials(self.portal, creds)

        self.assertTrue(IDisableCSRFProtection.providedBy(self.portal.REQUEST))
コード例 #9
0
 def transform(self, result, encoding):
     from plone.protect.interfaces import IDisableCSRFProtection
     # clickjacking protection from plone.protect
     if X_FRAME_OPTIONS:
         if not self.request.response.getHeader('X-Frame-Options'):
             self.request.response.setHeader('X-Frame-Options',
                                             X_FRAME_OPTIONS)
     # drop X-Tile-Url
     if 'x-tile-url' in self.request.response.headers:
         del self.request.response.headers['x-tile-url']
     # ESI requests are always GET request and should not mutate DB
     # unless they provide IDisableCSRFProtection
     if not IDisableCSRFProtection.providedBy(self.request):
         transaction.abort()
     return None
コード例 #10
0
ファイル: esi.py プロジェクト: plone/plone.tiles
 def transform(self, result, encoding):
     from plone.protect.interfaces import IDisableCSRFProtection
     # clickjacking protection from plone.protect
     if X_FRAME_OPTIONS:
         if not self.request.response.getHeader('X-Frame-Options'):
             self.request.response.setHeader(
                 'X-Frame-Options', X_FRAME_OPTIONS)
     # drop X-Tile-Url
     if 'x-tile-url' in self.request.response.headers:
         del self.request.response.headers['x-tile-url']
     # ESI requests are always GET request and should not mutate DB
     # unless they provide IDisableCSRFProtection
     if not IDisableCSRFProtection.providedBy(self.request):
         transaction.abort()
     return None
コード例 #11
0
ファイル: response.py プロジェクト: collective/Products.Poi
    def __call__(self):
        form = self.request.form
        context = aq_inner(self.context)
        request = context.REQUEST
        authenticator = getMultiAdapter((context, request),
                                        name=u"authenticator")
        # CSRF should be disabled during tests
        if (not IDisableCSRFProtection.providedBy(request) and
           not authenticator.verify()):
            raise Unauthorized
        if not self.memship.checkPermission('Poi: Add Response', context):
            raise Unauthorized

        response_text = form.get('response', u'')
        new_response = Response(response_text)
        new_response.mimetype = self.mimetype
        new_response.type = self.determine_response_type(new_response)

        issue_has_changed = False
        transition = form.get('transition', u'')
        if transition and transition in self.available_transitions:
            wftool = getToolByName(context, 'portal_workflow')
            before = wftool.getInfoFor(context, 'review_state')
            before = wftool.getTitleForStateOnType(before, 'PoiIssue')
            wftool.doActionFor(context, transition)
            after = wftool.getInfoFor(context, 'review_state')
            after = wftool.getTitleForStateOnType(after, 'PoiIssue')
            new_response.add_change('review_state', _(u'Issue state'),
                                    before, after)
            issue_has_changed = True

        options = [
            ('severity', _(u'Severity'), 'available_severities'),
            ('current_assignee', _(u'Assignee'),
             'available_assignees'),
            ('targetRelease', _(u'Target release'), 'available_releases'),
        ]
        for option, title, vocab in options:
            new = form.get(option, u'')
            if new and new in self.__getattribute__(vocab):
                current = self.__getattribute__(option)
                if current == new:
                    continue
                new_response.add_change(option, title, current, new)
                issue_has_changed = True
                if option == 'severity':
                    context.severity = new
                elif option == 'targetRelease':
                    context.target_release = new
                elif option == 'current_assignee':
                    context.assignee = new

        if len(response_text) == 0 and not issue_has_changed:
            status = IStatusMessage(self.request)
            msg = _(u"No response text added and no issue changes made.")
            msg = translate(msg, 'Poi', context=self.request)
            status.addStatusMessage(msg, type='error')
        else:
            # Add response
            self.folder.add(new_response)
        redirect_url = "{0}?_authenticator={1}".format(context.absolute_url(),
                                                       authenticator.token())
        self.request.response.redirect(redirect_url)
コード例 #12
0
    def transform(self, result, encoding):

        site_url = 'foobar'
        if self.site:
            site_url = self.site.absolute_url()

        registered = self._registered_objects()
        if len(registered) > 0 and \
                not IDisableCSRFProtection.providedBy(self.request):
            # in plone 4, we need to do some more trickery to
            # prevent write on read errors
            annotation_keys = ('plone.contentrules.localassignments',
                               'syndication_settings',
                               'plone.portlets.contextassignments')
            for obj in registered:
                if isinstance(obj, OOBTree):
                    safe = False
                    for key in annotation_keys:
                        if key in obj:
                            safe = True
                            break
                    if safe:
                        safeWrite(obj)
                elif isinstance(obj, ATBlob):
                    # writing scales is fine
                    safeWrite(obj)

            # check referrer/origin header as a backstop to check
            # against false positives for write on read errors
            referrer = self.request.environ.get('HTTP_REFERER')
            if referrer:
                if referrer.startswith(site_url):
                    alsoProvides(self.request, IDisableCSRFProtection)
            else:
                origin = self.request.environ.get('HTTP_ORIGIN')
                if origin and origin == site_url:
                    alsoProvides(self.request, IDisableCSRFProtection)

        result = self.parseTree(result, encoding)
        if result is None:
            return None

        root = result.tree.getroot()
        try:
            token = createToken(manager=self.key_manager)
        except ComponentLookupError:
            return

        if self.site is not None:
            body = root.cssselect('body')[0]
            protect_script = etree.Element("script")
            protect_script.attrib.update({
                'type': "text/javascript",
                'src': "%s/++resource++protect.js" % site_url,
                'data-site-url': site_url,
                'data-token': token,
                'id': 'protect-script'
            })
            body.append(protect_script)

        # guess zmi, if it is, rewrite all links
        last_path = self.request.URL.split('/')[-1]
        if last_path == 'manage' or last_path.startswith('manage_'):
            root.make_links_absolute(self.request.URL)

            def rewrite_func(url):
                return addTokenToUrl(url,
                                     self.request,
                                     manager=self.key_manager)

            root.rewrite_links(rewrite_func)

        # Links to add token to so we don't trigger the csrf
        # warnings
        for anchor in root.cssselect(_add_rule_token_selector):
            url = anchor.attrib.get('href')
            # addTokenToUrl only converts urls on the same site
            anchor.attrib['href'] = addTokenToUrl(url,
                                                  self.request,
                                                  manager=self.key_manager)

        return result
コード例 #13
0
            if exception_handler is not None:
                exception_handler(response, e)
            else:
                response.exception()
        return response
    finally:
        if SAFE_WRITE_KEY in request.environ:
            # append this list of safe oids to parent request
            if SAFE_WRITE_KEY not in parent_request.environ:
                parent_request.environ[SAFE_WRITE_KEY] = []
            new_keys = (
                set(request.environ[SAFE_WRITE_KEY]) -
                set(parent_request.environ[SAFE_WRITE_KEY])
            )
            parent_request.environ[SAFE_WRITE_KEY].extend(new_keys)
        if IDisableCSRFProtection.providedBy(request):
            alsoProvides(parent_request, IDisableCSRFProtection)
        request.clear()
        setRequest(parent_request)
        setSite(parent_site)
        setSecurityManager(security_manager)


def unauthorized_exception_handler(response, exception):
    """exception handler for subrequests delegating Unauthorized to a 401,
    but raising all other exceptions (resulting later in a 500).
    """
    if not isinstance(exception, Unauthorized):
        return response.exception()
    response.setStatus = 401
コード例 #14
0
ファイル: __init__.py プロジェクト: plone/plone.subrequest
def subrequest(url, root=None, stdout=None, exception_handler=None):
    assert url is not None, 'You must pass a url'
    if six.PY2 and isinstance(url, six.text_type):
        url = url.encode('utf-8')
    _, _, path, query, _ = urlsplit(url)
    parent_request = getRequest()
    assert parent_request is not None, \
        'Unable to get request, perhaps zope.globalrequest is not configured.'
    parent_site = getSite()
    security_manager = getSecurityManager()
    parent_app = parent_request.PARENTS[-1]
    if path.startswith('/'):
        path = normpath(path)
        vurl_parts = parent_request.get('VIRTUAL_URL_PARTS')
        if vurl_parts is not None:
            # Use the virtual host root
            path_past_root = unquote(vurl_parts[-1])
            root_path = normpath(
                parent_request['PATH_INFO']
            ).rstrip('/')[:-len(path_past_root) or None]
            if root is None:
                path = root_path + path
            else:
                path = '{0}/{1}{2}'.format(
                    root_path,
                    root.virtual_url_path(),
                    path
                )
        elif root is not None:
            path = '/{0}{1}'.format(root.virtual_url_path(), path)
    else:
        try:
            parent_url = parent_request['URL']
            if isinstance(parent_url, six.binary_type):
                parent_url = parent_url.encode('utf-8')
            # extra is the hidden part of the url, e.g. a default view
            extra = unquote(
                parent_url[len(parent_request['ACTUAL_URL']):]
            )
        except KeyError:
            extra = ''
        here = parent_request['PATH_INFO'] + extra
        path = urljoin(here, path)
        path = normpath(path)
    request = parent_request.clone()
    for name, parent_value in parent_request.other.items():
        if name in OTHER_IGNORE \
           or OTHER_IGNORE_RE.match(name) \
           or name.startswith('_'):
            continue
        request.other[name] = parent_value
    for key, value in parent_request.response.cookies.items():
        request.cookies[key] = value['value']
    request['PARENT_REQUEST'] = parent_request
    alsoProvides(request, ISubRequest)
    try:
        setRequest(request)
        request_container = RequestContainer(REQUEST=request)
        app = aq_base(parent_app).__of__(request_container)
        request['PARENTS'] = [app]
        response = request.response
        response.__class__ = SubResponse
        response.stderr = None  # only used on retry it seems
        if stdout is None:
            stdout = StringIO()  # It might be possible to optimize this
        response.stdout = stdout
        environ = request.environ
        environ['PATH_INFO'] = path
        environ['QUERY_STRING'] = query
        # Clean up the request.
        for header in CONDITIONAL_HEADERS:
            environ.pop(header, None)
        try:
            request.processInputs()
            traversed = request.traverse(path)
            result = mapply(
                traversed,
                positional=request.args,
                keyword=request,
                debug=None,
                maybe=1,
                missing_name=missing_name,
                handle_class=dont_publish_class,
                context=request,
                bind=1
            )
            if result is not response:
                response.setBody(result)
            for key, value in request.response.cookies.items():
                parent_request.response.cookies[key] = value
        except Exception as e:
            logger.exception(u'Error handling subrequest to {0}'.format(url))
            if exception_handler is not None:
                exception_handler(response, e)
            else:
                view = queryMultiAdapter((e, request), name=u'index.html')
                if view is not None:
                    v = view()
                    response.setBody(v)
                else:
                    response.exception()
        return response
    finally:
        if SAFE_WRITE_KEY in request.environ:
            # append this list of safe oids to parent request
            if SAFE_WRITE_KEY not in parent_request.environ:
                parent_request.environ[SAFE_WRITE_KEY] = []
            new_keys = (
                set(request.environ[SAFE_WRITE_KEY]) -
                set(parent_request.environ[SAFE_WRITE_KEY])
            )
            parent_request.environ[SAFE_WRITE_KEY].extend(new_keys)
        if IDisableCSRFProtection.providedBy(request):
            alsoProvides(parent_request, IDisableCSRFProtection)
        request.clear()
        setRequest(parent_request)
        setSite(parent_site)
        setSecurityManager(security_manager)
コード例 #15
0
ファイル: transform.py プロジェクト: ale-rt/plone4.csrffixes
    def transform(self, result, encoding):

        site_url = 'foobar'
        if self.site:
            site_url = self.site.absolute_url()

        registered = self._registered_objects()
        if len(registered) > 0 and \
                not IDisableCSRFProtection.providedBy(self.request):
            # in plone 4, we need to do some more trickery to
            # prevent write on read errors
            annotation_keys = (
                'plone.contentrules.localassignments',
                'syndication_settings',
                'plone.portlets.contextassignments')
            for obj in registered:
                if isinstance(obj, OOBTree):
                    safe = False
                    for key in annotation_keys:
                        try:
                            if key in obj:
                                safe = True
                                break
                        except TypeError:
                            pass
                    if safe:
                        safeWrite(obj)
                elif isinstance(obj, ATBlob):
                    # writing scales is fine
                    safeWrite(obj)

            # check referrer/origin header as a backstop to check
            # against false positives for write on read errors
            referrer = self.request.environ.get('HTTP_REFERER')
            if referrer:
                if referrer.startswith(site_url + '/'):
                    alsoProvides(self.request, IDisableCSRFProtection)
            else:
                origin = self.request.environ.get('HTTP_ORIGIN')
                if origin and origin == site_url:
                    alsoProvides(self.request, IDisableCSRFProtection)

        result = self.parseTree(result, encoding)
        if result is None:
            return None

        root = result.tree.getroot()
        try:
            token = createToken(manager=self.key_manager)
        except ComponentLookupError:
            return

        if self.site is not None:
            body = root.cssselect('body')[0]
            protect_script = etree.Element("script")
            protect_script.attrib.update({
                'type': "application/javascript",
                'src': "%s/++resource++protect.js" % site_url,
                'data-site-url': site_url,
                'data-token': token,
                'id': 'protect-script'
            })
            body.append(protect_script)

        # guess zmi, if it is, rewrite all links
        last_path = self.request.URL.split('/')[-1]
        if last_path == 'manage' or last_path.startswith('manage_'):
            root.make_links_absolute(self.request.URL)
            def rewrite_func(url):
                return addTokenToUrl(
                    url, self.request, manager=self.key_manager)
            root.rewrite_links(rewrite_func)

        # Links to add token to so we don't trigger the csrf
        # warnings
        for anchor in root.cssselect(_add_rule_token_selector):
            url = anchor.attrib.get('href')
            # addTokenToUrl only converts urls on the same site
            anchor.attrib['href'] = addTokenToUrl(
                url, self.request, manager=self.key_manager)

        return result
コード例 #16
0
ファイル: __init__.py プロジェクト: vedantc98/Plone-test
def subrequest(url, root=None, stdout=None, exception_handler=None):
    assert url is not None, 'You must pass a url'
    if isinstance(url, six.text_type):
        url = url.encode('utf-8')
    _, _, path, query, _ = urlsplit(url)
    parent_request = getRequest()
    assert parent_request is not None, \
        'Unable to get request, perhaps zope.globalrequest is not configured.'
    parent_site = getSite()
    security_manager = getSecurityManager()
    parent_app = parent_request.PARENTS[-1]
    if path.startswith('/'):
        path = normpath(path)
        vurl_parts = parent_request.get('VIRTUAL_URL_PARTS')
        if vurl_parts is not None:
            # Use the virtual host root
            path_past_root = unquote(vurl_parts[-1])
            root_path = normpath(parent_request['PATH_INFO']).rstrip(
                '/')[:-len(path_past_root) or None]
            if root is None:
                path = root_path + path
            else:
                path = '{0}/{1}{2}'.format(root_path, root.virtual_url_path(),
                                           path)
        elif root is not None:
            path = '/{0}{1}'.format(root.virtual_url_path(), path)
    else:
        try:
            parent_url = parent_request['URL']
            if isinstance(parent_url, six.text_type):
                parent_url = parent_url.encode('utf-8')
            # extra is the hidden part of the url, e.g. a default view
            extra = unquote(parent_url[len(parent_request['ACTUAL_URL']):])
        except KeyError:
            extra = ''
        here = parent_request['PATH_INFO'] + extra
        path = urljoin(here, path)
        path = normpath(path)
    request = parent_request.clone()
    for name, parent_value in parent_request.other.items():
        if name in OTHER_IGNORE \
           or OTHER_IGNORE_RE.match(name) \
           or name.startswith('_'):
            continue
        request.other[name] = parent_value
    for key, value in parent_request.response.cookies.items():
        request.cookies[key] = value['value']
    request['PARENT_REQUEST'] = parent_request
    alsoProvides(request, ISubRequest)
    try:
        setRequest(request)
        request_container = RequestContainer(REQUEST=request)
        app = aq_base(parent_app).__of__(request_container)
        request['PARENTS'] = [app]
        response = request.response
        response.__class__ = SubResponse
        response.stderr = None  # only used on retry it seems
        if stdout is None:
            stdout = StringIO()  # It might be possible to optimize this
        response.stdout = stdout
        environ = request.environ
        environ['PATH_INFO'] = path
        environ['QUERY_STRING'] = query
        # Clean up the request.
        for header in CONDITIONAL_HEADERS:
            environ.pop(header, None)
        try:
            request.processInputs()
            traversed = request.traverse(path)
            result = mapply(traversed,
                            positional=request.args,
                            keyword=request,
                            debug=None,
                            maybe=1,
                            missing_name=missing_name,
                            handle_class=dont_publish_class,
                            context=request,
                            bind=1)
            if result is not response:
                response.setBody(result)
            for key, value in request.response.cookies.items():
                parent_request.response.cookies[key] = value
        except Exception as e:
            logger.exception('Error handling subrequest to {0}'.format(url))
            if exception_handler is not None:
                exception_handler(response, e)
            else:
                view = queryMultiAdapter((e, request), name=u'index.html')
                if view is not None:
                    v = view()
                    response.setBody(v)
                else:
                    response.exception()
        return response
    finally:
        if SAFE_WRITE_KEY in request.environ:
            # append this list of safe oids to parent request
            if SAFE_WRITE_KEY not in parent_request.environ:
                parent_request.environ[SAFE_WRITE_KEY] = []
            new_keys = (set(request.environ[SAFE_WRITE_KEY]) -
                        set(parent_request.environ[SAFE_WRITE_KEY]))
            parent_request.environ[SAFE_WRITE_KEY].extend(new_keys)
        if IDisableCSRFProtection.providedBy(request):
            alsoProvides(parent_request, IDisableCSRFProtection)
        request.clear()
        setRequest(parent_request)
        setSite(parent_site)
        setSecurityManager(security_manager)
コード例 #17
0
    def __call__(self):
        form = self.request.form
        context = aq_inner(self.context)
        request = context.REQUEST
        authenticator = getMultiAdapter((context, request),
                                        name=u"authenticator")
        # CSRF should be disabled during tests
        if (not IDisableCSRFProtection.providedBy(request)
                and not authenticator.verify()):
            raise Unauthorized
        if not self.memship.checkPermission('Poi: Add Response', context):
            raise Unauthorized

        response_text = form.get('response', u'')
        new_response = Response(response_text)
        new_response.mimetype = self.mimetype
        new_response.type = self.determine_response_type(new_response)

        issue_has_changed = False
        transition = form.get('transition', u'')
        if transition and transition in self.available_transitions:
            wftool = getToolByName(context, 'portal_workflow')
            before = wftool.getInfoFor(context, 'review_state')
            before = wftool.getTitleForStateOnType(before, 'PoiIssue')
            wftool.doActionFor(context, transition)
            after = wftool.getInfoFor(context, 'review_state')
            after = wftool.getTitleForStateOnType(after, 'PoiIssue')
            new_response.add_change('review_state', _(u'Issue state'), before,
                                    after)
            issue_has_changed = True

        options = [
            ('severity', _(u'Severity'), 'available_severities'),
            ('current_assignee', _(u'Assignee'), 'available_assignees'),
            ('targetRelease', _(u'Target release'), 'available_releases'),
        ]
        for option, title, vocab in options:
            new = form.get(option, u'')
            if new and new in self.__getattribute__(vocab):
                current = self.__getattribute__(option)
                if current == new:
                    continue
                new_response.add_change(option, title, current, new)
                issue_has_changed = True
                if option == 'severity':
                    context.severity = new
                elif option == 'targetRelease':
                    context.target_release = new
                elif option == 'current_assignee':
                    context.assignee = new

        if len(response_text) == 0 and not issue_has_changed:
            status = IStatusMessage(self.request)
            msg = _(u"No response text added and no issue changes made.")
            msg = translate(msg, 'Poi', context=self.request)
            status.addStatusMessage(msg, type='error')
        else:
            # Add response
            self.folder.add(new_response)
            context.reindexObject()
        redirect_url = "{0}?_authenticator={1}".format(context.absolute_url(),
                                                       authenticator.token())
        self.request.response.redirect(redirect_url)