Beispiel #1
0
def addTokenToUrl(url, req=None, manager=None):
    if not url:
        return url
    if req is None:
        req = getRequest()
    if req is None or not url.startswith(req.SERVER_URL):
        # only transforms urls to same site
        return url
    if getattr(req, 'environ', _default) is _default:
        # TestRequests have no environ.
        token = createToken(manager=manager)
    elif '_auth_token' not in req.environ:
        # Let's cache this value since this could be called
        # many times for one request.
        token = createToken(manager=manager)
        req.environ['_auth_token'] = token
    else:
        token = req.environ['_auth_token']

    if '_authenticator' not in url:
        if '?' not in url:
            url += '?'
        else:
            url += '&'
        url += '_authenticator=' + token
    return url
Beispiel #2
0
    def test_force_regenerate_sync_view(self):
        '''
        Test we can regenerate existing previews
        '''
        file1 = api.content.create(self.portal,
                                   id='file1',
                                   type='File',
                                   file=self.get_blob())
        # the time of the original preview generation
        original_ids = self.get_preview_ids_for(file1)

        # Calling the view without the generate parameter will not force
        # The preview regeneration
        view = api.content.get_view(
            'generate-previews-for-contents', self.portal,
            self.get_request({'_authenticator': createToken()}))
        self.assertEqual(
            self.get_preview_ids_for(file1),
            original_ids,
        )

        # Adding a truish regenerate value to the request will
        view = api.content.get_view(
            'generate-previews-for-contents', self.portal,
            self.get_request({
                '_authenticator': createToken(),
                'regenerate': True,
            }))
        view()
        self.assertNotEqual(
            self.get_preview_ids_for(file1),
            original_ids,
        )
Beispiel #3
0
def addTokenToUrl(url, req=None, manager=None):
    if not url:
        return url
    if req is None:
        req = getRequest()
    if req is None or not url.startswith(req.SERVER_URL):
        # only transforms urls to same site
        return url
    if getattr(req, 'environ', _default) is _default:
        # TestRequests have no environ.
        token = createToken(manager=manager)
    elif '_auth_token' not in req.environ:
        # Let's cache this value since this could be called
        # many times for one request.
        token = createToken(manager=manager)
        req.environ['_auth_token'] = token
    else:
        token = req.environ['_auth_token']

    if '_authenticator' not in url:
        if '?' not in url:
            url += '?'
        else:
            url += '&'
        url += '_authenticator=' + token
    return url
Beispiel #4
0
    def setUp(self):
        self.portal = self.layer['portal']
        login(self.portal, TEST_USER_NAME)
        setRoles(self.portal, TEST_USER_ID, ['Manager'])

        self.portal.invokeFactory('Document', id="page", title="page")
        self.portal.page.reindexObject()

        self.request = TestRequest(
            environ={
                'HTTP_ACCEPT_LANGUAGE': 'en',
                'REQUEST_METHOD': 'POST'
            },
            form={
                'selection': '["' + IUUID(self.portal.page) + '"]',
                '_authenticator': createToken(),
                'folder': '/'
            }
        )
        self.request.REQUEST_METHOD = 'POST'
        alsoProvides(self.request, IAttributeAnnotatable)
        self.userList = json.dumps([{
            'id': 'one'
        }, {
            'id': 'two'
        }])
Beispiel #5
0
 def __call__(self, **kw):
     uid = self.request['uid']
     payment = Payments(self.context).get('invoice')
     payment.succeed(self.request, uid)
     url = '{url}/@@invoiced?uid={uid}&_authenticator={token}'.format(
         url=self.context.absolute_url(), uid=uid, token=createToken())
     self.request.response.redirect(url)
Beispiel #6
0
    def get_options(self):
        site_url = success_url = self.context.absolute_url()
        if ISiteRoot.providedBy(self.context):
            success_url += '/@@dashboard'
        if 'came_from' in self.request.form:
            came_from = self.request.form['came_from']
            try:
                url_tool = api.portal.get_tool('portal_url')
            except api.exc.CannotGetPortalError:
                url_tool = None
            if (came_from.startswith(site_url) and (
                    not url_tool or url_tool.isURLInPortal(came_from))):
                success_url = came_from
            if 'login' in success_url or 'logged_out' in success_url:
                success_url = site_url + '/@@dashboard'

        data = {
            'supportedAuthSchemes': self.get_supported_auth_schemes(),
            'twoFactorEnabled': self.two_factor_enabled,
            'apiEndpoint': '{}/@@secure-login'.format(site_url),
            'successUrl': success_url,
            'additionalProviders': []
        }
        try:
            data['authenticator'] = createToken()
        except ConnectionStateError:
            # zope root related issue here...
            pass

        return data
    def setUp(self):
        self.portal = self.layer['portal']
        login(self.portal, TEST_USER_NAME)
        setRoles(self.portal, TEST_USER_ID, ['Manager'])

        self.portal.invokeFactory(
            'Folder',
            id="basefolder",
            title="Folder Base"
        )
        self.bf = self.portal.basefolder
        self.bf.reindexObject()
        for idx in range(0, 5):
            newid = "f{0:}".format(idx)
            self.bf.invokeFactory(
                'Folder',
                id=newid,
                # title in reverse order
                title="Folder {0:}".format(4-idx)
            )
            self.bf[newid].reindexObject()

        self.env = {'HTTP_ACCEPT_LANGUAGE': 'en', 'REQUEST_METHOD': 'POST'}
        self.request = makerequest(self.layer['app']).REQUEST
        self.request.environ.update(self.env)
        self.request.form = {
            'selection': '["' + IUUID(self.bf) + '"]',
            '_authenticator': createToken(),
            'folder': '/basefolder'
        }
        self.request.REQUEST_METHOD = 'POST'
Beispiel #8
0
def get_chat_info():

    try:
        frontpage = api.portal.get_registry_record(
            'castle.rocket_chat_front_page')
        salt = api.portal.get_registry_record('castle.rocket_chat_secret')
    except InvalidParameterError:
        frontpage = None
        salt = ''

    if frontpage is None or salt == '':
        return

    if frontpage[-1] != '/':
        frontpage = frontpage + '/'

    url = frontpage.replace('http://', 'ws://')
    url = url + 'websocket'

    current = api.user.get_current()
    base_url = api.portal.get().absolute_url()

    return {
        'url': url,
        'base_url': base_url,
        'frontpage': frontpage,
        'token': createToken(salt),
        'user': getattr(current, 'id', ''),
        'email': current.getProperty('email')
    }
    def setUp(self):
        self.portal = self.layer['portal']
        login(self.portal, TEST_USER_NAME)
        setRoles(self.portal, TEST_USER_ID, ['Manager'])

        self.portal.invokeFactory('Document', id="page", title="page")
        self.portal.page.reindexObject()

        self.request = TestRequest(environ={
            'HTTP_ACCEPT_LANGUAGE': 'en',
            'REQUEST_METHOD': 'POST'
        },
                                   form={
                                       'selection':
                                       '["' + IUUID(self.portal.page) + '"]',
                                       '_authenticator':
                                       createToken(),
                                       'folder':
                                       '/'
                                   })
        self.request.REQUEST_METHOD = 'POST'
        # Mock physicalPathFromURL
        # NOTE: won't return the right path in virtual hosting environments
        self.request.physicalPathFromURL = lambda url: urlparse(
            url).path.split('/')  # noqa
        alsoProvides(self.request, IAttributeAnnotatable)
        self.userList = 'one,two'
Beispiel #10
0
    def setUp(self):
        self.portal = self.layer['portal']
        login(self.portal, TEST_USER_NAME)
        setRoles(self.portal, TEST_USER_ID, ['Manager'])

        self.portal.invokeFactory('Document', id="page", title="page")
        self.portal.page.reindexObject()

        self.request = TestRequest(
            environ={
                'HTTP_ACCEPT_LANGUAGE': 'en',
                'REQUEST_METHOD': 'POST'
            },
            form={
                'selection': '["' + IUUID(self.portal.page) + '"]',
                '_authenticator': createToken(),
                'folder': '/'
            }
        )
        self.request.REQUEST_METHOD = 'POST'
        # Mock physicalPathFromURL
        # NOTE: won't return the right path in virtual hosting environments
        self.request.physicalPathFromURL = lambda url: urlparse(url).path.split('/')  # noqa
        alsoProvides(self.request, IAttributeAnnotatable)
        self.userList = 'one,two'
Beispiel #11
0
 def query_options(self):
     ''' The query string options for the bookmark action
     '''
     options = {
         '_authenticator': createToken(),
     }
     return options
Beispiel #12
0
    def __call__(self):
        if self.path[0] == 'view':
            # this is neutral, we just return the default content view
            # but it gives the opportunity to create specific pseudo views
            # via our Diazo rules.xml
            return self.context()

        self.request.response.setHeader('X-Theme-Disabled', '1')

        if self.path[-1].startswith('$'):
            # inject Diazo parent request path
            parent_path = self.request.PARENT_REQUEST['URL'].split('/')
            try:
                offset = int(self.path[-1][1:])
            except ValueError:
                return "Bad Rapido url injection %s" % self.path[-1]
            index = parent_path.index('@@rapido')
            self.path = self.path[:-1] + parent_path[index + offset:]

        if len(self.path) == 2 and self.path[1] == '_log':
            messages = self.get_app_messages()
            self.request.response.setHeader('content-type', 'application/json')
            return json.dumps(messages, cls=PythonObjectEncoder)

        if "application/json" in self.request.getHeader('Accept', ''):
            result = self.json()
            if len(self.path) == 1:
                self.request.response.setHeader('X-CSRF-TOKEN', createToken())
            self.request.response.setHeader('content-type', 'application/json')
            return json.dumps(result, cls=PythonObjectEncoder)
        else:
            result = self.content()
            return result
    def test_delete_wrong_object_by_acquisition(self):
        page_id = self.portal.page.id
        f1 = self.portal.invokeFactory('Folder', id="f1", title="folder one")
        # created a nested page with the same id as the one at the site root
        p1 = self.portal[f1].invokeFactory('Document', id=page_id, title="page")
        self.assertEquals(p1, page_id)
        request2 = self.make_request()

        # both pages exist before we delete on
        for location in [self.portal, self.portal[f1]]:
            self.assertTrue(p1 in location)

        # instantiate two different views and delete the same object with each
        from plone.app.content.browser.contents.delete import DeleteActionView
        object_uuid = IUUID(self.portal[f1][p1])
        for req in [self.request, request2]:
            req.form = {
                'selection': '["{}"]'.format(object_uuid),
                '_authenticator': createToken(),
                'folder': '/{}/'.format(f1)
            }
            view = DeleteActionView(self.portal, req)
            view()

        # the root page exists, the nested one is gone
        self.assertTrue(p1 in self.portal)
        self.assertFalse(p1 in self.portal[f1])
Beispiel #14
0
 def morphVersionDataToHistoryFormat(vdata, version_id):
     meta = vdata["metadata"]["sys_metadata"]
     userid = meta["principal"]
     token = createToken()
     preview_url = \
         "%s/versions_history_form?version_id=%s&_authenticator=%s#version_preview" % (  # noqa
             context_url,
             version_id,
             token
         )
     info = dict(
         type='versioning',
         action=_(u"Edited"),
         transition_title=_(u"Edited"),
         actorid=userid,
         time=meta["timestamp"],
         comments=meta['comment'],
         version_id=version_id,
         preview_url=preview_url,
     )
     if can_diff:
         if version_id > 0:
             info["diff_previous_url"] = (
                 "%s/@@history?one=%s&two=%s&_authenticator=%s" %
                 (context_url, version_id, version_id - 1, token))
         if not rt.isUpToDate(context, version_id):
             info["diff_current_url"] = (
                 "%s/@@history?one=current&two=%s&_authenticator=%s" %
                 (context_url, version_id, token))
     if can_revert:
         info["revert_url"] = "%s/revertversion" % context_url
     else:
         info["revert_url"] = None
     info.update(self.getUserInfo(userid))
     return info
    def test_custom_value_for_height_calculation_method(self, browser):
        """
        Test setting a custom value for the height calculation method.
        """
        block = create(Builder('iframe block')
                       .having(url=u'http://www.google.com')
                       .having(auto_size=True)
                       .within(create(Builder('sl content page'))))

        browser.append_request_header('X-CSRF-TOKEN', createToken())
        browser.login()

        # Edit the block and customize the height calculation method.
        browser.visit(block, view='edit.json')
        response = browser.json
        browser.parse(response['content'])
        browser.fill({
            'Height calculation method': 'documentElementOffset',
        })
        browser.find_button_by_label('Save').click()

        # The value has been set.
        view = block.restrictedTraverse('@@block_view')
        self.assertEqual(
            u'documentElementOffset',
            view.height_calculation_method
        )
    def setUp(self):
        self.portal = self.layer['portal']
        login(self.portal, TEST_USER_NAME)
        setRoles(self.portal, TEST_USER_ID, ['Manager'])

        self.portal.invokeFactory('Folder',
                                  id="basefolder",
                                  title="Folder Base")
        self.bf = self.portal.basefolder
        self.bf.reindexObject()
        for idx in range(0, 5):
            newid = "f{0:}".format(idx)
            self.bf.invokeFactory(
                'Folder',
                id=newid,
                # title in reverse order
                title="Folder {0:}".format(4 - idx))
            self.bf[newid].reindexObject()

        self.env = {'HTTP_ACCEPT_LANGUAGE': 'en', 'REQUEST_METHOD': 'POST'}
        self.request = makerequest(self.layer['app']).REQUEST
        self.request.environ.update(self.env)
        self.request.form = {
            'selection': '["' + IUUID(self.bf) + '"]',
            '_authenticator': createToken(),
            'folder': '/basefolder'
        }
        self.request.REQUEST_METHOD = 'POST'
    def test_delete_wrong_object_by_acquisition(self):
        page_id = self.portal.page.id
        f1 = self.portal.invokeFactory('Folder', id="f1", title="folder one")
        # created a nested page with the same id as the one at the site root
        p1 = self.portal[f1].invokeFactory('Document',
                                           id=page_id,
                                           title="page")
        self.assertEquals(p1, page_id)
        request2 = self.make_request()

        # both pages exist before we delete on
        for location in [self.portal, self.portal[f1]]:
            self.assertTrue(p1 in location)

        # instantiate two different views and delete the same object with each
        from plone.app.content.browser.contents.delete import DeleteActionView
        object_uuid = IUUID(self.portal[f1][p1])
        for req in [self.request, request2]:
            req.form = {
                'selection': '["{}"]'.format(object_uuid),
                '_authenticator': createToken(),
                'folder': '/{}/'.format(f1)
            }
            view = DeleteActionView(self.portal, req)
            view()

        # the root page exists, the nested one is gone
        self.assertTrue(p1 in self.portal)
        self.assertFalse(p1 in self.portal[f1])
Beispiel #18
0
    def transform(self, result, encoding):

        result = self.parseTree(result, encoding)
        if result is None:
            return None
        root = result.tree.getroot()
        url = urlparse(self.request.URL)
        try:
            token = createToken(manager=self.key_manager)
        except ComponentLookupError:
            if self.site is not None:
                logger.warn(
                    'Keyring not found on site. This should not happen',
                    exc_info=True
                )
            return result

        for form in root.cssselect('form'):
            # XXX should we only do POST? If we're logged in and
            # it's an internal form, I'm inclined to say no...
            # method = form.attrib.get('method', 'GET').lower()
            # if method != 'post':
            #    continue

            # some get forms we definitely do not want to protect.
            # for now, we know search we do not want to protect
            method = form.attrib.get('method', 'GET').lower()
            action = form.attrib.get('action', '').strip()
            if method == 'get' and '@@search' in action:
                continue
            action = form.attrib.get('action', '').strip()
            if not self.isActionInSite(action, url):
                continue
            # check if the token is already on the form..
            hidden = form.cssselect('[name="_authenticator"]')
            if len(hidden) == 0:
                hidden = etree.Element("input")
                hidden.attrib['name'] = '_authenticator'
                hidden.attrib['type'] = 'hidden'
                hidden.attrib['value'] = token
                form.append(hidden)

        if self.site is not None and not root.cssselect('#protect-script'):
            # Alternative: add this in the resource registry.
            site_url = self.site.absolute_url()
            elements = root.cssselect('body')
            if len(elements):
                body = elements[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)

        return result
Beispiel #19
0
 def reject_url(self):
     can_review = api.user.has_permission("Review portal content",
                                          obj=self.context)
     if not can_review:
         return ""
     return "{context_url}/content_status_modify?workflow_action=refuse&_authenticator={token}".format(  # noqa
         context_url=self.context.absolute_url(),
         token=createToken())
Beispiel #20
0
 def site_config(self):
     return json.dumps({
         "actionUrl": "%s/++sitelayout++/custom/@@plone.resourceeditor.filemanager-actions" % (  # noqa
             self.context.absolute_url()),
         "uploadUrl": "%s/portal_resources/sitelayout/custom/themeFileUpload?_authenticator=%s" % (  # noqa
             self.context.absolute_url(),
             createToken())
     })
Beispiel #21
0
 def site_config(self):
     return json.dumps({
         'actionUrl': ('{0}/++sitelayout++/custom/'
                       '@@plone.resourceeditor.filemanager-actions'.format(
                           self.context.absolute_url())),
         'uploadUrl': ('{0}/portal_resources/sitelayout/custom/'
                       'themeFileUpload?_authenticator={1}'.format(
                           self.context.absolute_url(), createToken())),
     })
Beispiel #22
0
    def __call__(self):
        soup = self.context.get_soup()
        columns = self.columns()
        aaData = list()
        length, lazydata = self._query(soup)
        # XXX Todo html from template
        if PLONE_PROTECT:
            token = createToken()
            url = self.context.absolute_url()
            html = '<a href="#" data-iid="%(iid)s" class="pfgsoup-edit">edit</a> '
            html += '<a href="%(url)s/pfgsoupdel?iid=%(iid)s&_authenticator=%(token)s" class="pfgsoup-delete">remove</a> '
            html += (
                '<a href="%(url)s/@@pfgsouplog?iid=%(iid)s&_authenticator=%(token)s" '
                'class="pfgsoup-log">log</a>')
        else:
            url = self.context.absolute_url()
            html = '<a href="#" data-iid="%(iid)s" class="pfgsoup-edit">edit</a> '
            html += '<a href="%(url)s/pfgsoupdel?iid=%(iid)s" class="pfgsoup-delete">remove</a> '
            html += ('<a href="%(url)s/@@pfgsouplog?iid=%(iid)s" '
                     'class="pfgsoup-log">log</a>')

        def record2list(record):
            result = list()
            for colname in columns:
                value = record.attrs.get(colname, '')
                if isinstance(value, list):
                    value = ', '.join(value)
                elif isinstance(value, datetime.datetime):
                    value = value.isoformat()
                elif isinstance(value, dict):
                    value = ', '.join([str(_) for _ in value.items])
                try:
                    json.dumps(value)
                except TypeError:
                    value = str(value)
                result.append(value)
            if PLONE_PROTECT:
                result.append(html % {
                    'iid': record.intid,
                    'url': url,
                    'token': token
                })
            else:
                result.append(html % {'iid': record.intid, 'url': url})
            return result

        for lazyrecord in self._slice(lazydata):
            aaData.append(record2list(lazyrecord()))
        data = {
            "sEcho": int(self.request.form['sEcho']),
            "iTotalRecords": soup.storage.length.value,
            "iTotalDisplayRecords": length,
            "aaData": aaData,
        }
        self.request.response.setHeader("Content-type", "application/json")
        return json.dumps(data)
    def getRequest(self, form={}, authentic=False):
        if authentic:
            form['_authenticator'] = createToken()

        req = TestRequest(form=form, environ={
            'SERVER_URL': 'http://nohost',
            'HTTP_HOST': 'nohost'
        })
        alsoProvides(req, IAttributeAnnotatable)
        return req
def auth(context, request):
    """ Authenticate
    """

    if ploneapi.user.is_anonymous():
        request.response.setStatus(401)
        request.response.setHeader('WWW-Authenticate', 'basic realm="JSONAPI AUTH"', 1)
    else:
        request.response.setHeader('X-CSRF-TOKEN', createToken())
    return {}
 def __call__(self, **kw):
     uid = self.request['uid']
     payment = Payments(self.context).get('invoice')
     payment.succeed(self.request, uid)
     url = '{url}/@@pay_invoice_done?uid={uid}&_authenticator={token}'.format(
         url=self.context.absolute_url(),
         uid=uid,
         token=createToken()
     )
     self.request.response.redirect(url)
 def setUp(self):
     """Custom shared utility setup for tests."""
     self.portal = self.layer["portal"]
     self.request = self.layer["request"]
     setRoles(self.portal, TEST_USER_ID, ["Manager"])
     self.migration_view = api.content.get_view(name="data-migration",
                                                context=self.portal,
                                                request=self.request)
     self.request.form["_authenticator"] = createToken()
     api.content.delete(objects=self.portal.listFolderContents())
Beispiel #27
0
 def testPrepareObjectTabsDefaultView(self):
     self._invalidateRequestMemoizations()
     self.loginAsPortalOwner()
     self.app.REQUEST['ACTUAL_URL'] = '%s/edit?_authenticator=%s' % (
         self.folder.test.absolute_url(), auth.createToken())
     view = ContentViewsViewlet(self.folder.test, self.app.REQUEST, None)
     tabs = view.prepareObjectTabs()
     self.assertEqual(0,
                      len([t for t in tabs if t['id'] == 'folderContents']))
     self.assertEqual(['edit'], [t['id'] for t in tabs if t['selected']])
Beispiel #28
0
 def bulk_upload_url(self):
     params = {
         '_authenticator': createToken(),
     }
     if self.autotag_bulk_uploaded:
         params['groupname'] = self.current_label
     return '{url}/workspaceFileUpload?{qs}'.format(
         url=self.context.absolute_url(),
         qs=urlencode(params),
     )
 def __call__(self):
     base_url = api.portal.get().absolute_url()
     order_uid = self.request['uid']
     logger.info('Start')
     try:
         data = IPaymentData(self.context).data(order_uid)
         dps_parms = DPSConfig()
         req = dps.GenerateRequest()
         req.PxPayUserId = dps_parms.PxPayUserId
         req.PxPayKey = dps_parms.PxPayKey
         req.AmountInput = "%0.2f" % (float(data['amount']) / 100.0)
         req.CurrencyInput = data['currency']
         req.MerchantReference = data['ordernumber']
         req.TxnData1 = 'IPurchaseProcess'
         req.TxnData2 = order_uid
         req.add_txn_parameters(ordernumber=data['ordernumber'])
         if not api.user.is_anonymous():
             req.add_txn_parameters(
                 member_id=api.user.get_current().getMemberId())
         req.TxnType = 'Purchase'
         req.UrlSuccess = '{base_url}/{view}?_authenticator={token}'.format(
                 view='@@pxpay_payment_success',
                 base_url=base_url,
                 token=createToken()
                 )
         req.UrlFail = '%s/@@pxpay_payment_failed' % base_url
         logger.info("Auth: %s" % req)
         result = req.getResponse()
         logger.info(result)
         if not result.valid:
             logger.info("Auth Error: %s" % result)
             raise PxPayError('Problem Initialising Payment')
         redirect_url = result.URI
     except Exception, e:
         logger.error(u"Could not initialize payment: '%s'" % str(e))
         redirect_url = ('{base_url}/{view}?'
                         'uid={order_uid}_authenticator={token}').format(
                         view='@@pxpay_payment_failed',
                         base_url=base_url,
                         order_uid=order_uid,
                         token=createToken()
                         )
Beispiel #30
0
 def site_config(self):
     return json.dumps({
         "actionUrl":
         "%s/++sitelayout++/custom/@@plone.resourceeditor.filemanager-actions"
         % (  # noqa
             self.context.absolute_url()),
         "uploadUrl":
         "%s/portal_resources/sitelayout/custom/themeFileUpload?_authenticator=%s"
         % (  # noqa
             self.context.absolute_url(), createToken())
     })
Beispiel #31
0
 def test_set1(self):
     self._invalidateRequestMemoizations()
     self.loginAsPortalOwner()
     self.app.REQUEST['ACTUAL_URL'] = '%s/edit?_authenticator=%s' % (
         self.folder.test.absolute_url(), auth.createToken())
     view = ContentViewsViewlet(self.folder.test, self.app.REQUEST, None)
     view.update()
     self.assertEqual(
         1, len([t for t in view.tabSet1 if t['id'] == 'folderContents']))
     self.assertEqual(['edit'],
                      [t['id'] for t in view.tabSet1 if t['selected']])
    def getRequest(self, form={}, authentic=False):
        if authentic:
            form['_authenticator'] = createToken()

        req = TestRequest(form=form,
                          environ={
                              'SERVER_URL': 'http://nohost',
                              'HTTP_HOST': 'nohost'
                          })
        alsoProvides(req, IAttributeAnnotatable)
        return req
    def test_renaming_object_via_folder_contents_rename_action(self, browser):

        self.grant('Manager')
        folder = create(Builder('folder').titled(u'Folder'))
        with freeze(datetime(2018, 1, 2, 3, 4, 5)):
            page = create(Builder('page').titled(u'The Page').within(folder))

            self.assertEquals(0, IQueue(self.portal).countJobs())

            form_data = {}
            form_data['_authenticator'] = createToken()
            form_data['UID_1'] = IUUID(page)
            form_data['newid_1'] = 'new_id'
            form_data['newtitle_1'] = u'Ch\xe4nged title'

            browser.login().visit(folder, view='@@fc-rename', data=form_data)

        self.assertEquals(1, IQueue(self.portal).countJobs())

        job, = IQueue(self.portal).getJobs()
        self.assertEquals('move', job.action)
        data = job.getData()
        self.assertTrue(data)

        self.maxDiff = None

        expected = {
            u'utf8:metadata': {
                u'utf8:UID': u'utf8:testrenamingobjectviafolde000002',
                u'utf8:action': u'utf8:move',
                u'utf8:id': u'utf8:new_id',
                u'utf8:modified': u'utf8:2018/01/02 03:04:05 GMT+1',
                u'utf8:physicalPath': u'utf8:/folder/new_id',
                u'utf8:portal_type': u'utf8:Document',
                u'utf8:review_state': u'utf8:',
                u'utf8:sibling_positions': {
                    u'utf8:new_id': 0
                }
            },
            u'utf8:move': {
                u'utf8:newName': u'utf8:new_id',
                u'utf8:newParent': u'utf8:/folder',
                u'utf8:newTitle': u'unicode:Ch\xe4nged title',
                u'utf8:oldName': u'utf8:the-page',
                u'utf8:oldParent': u'utf8:/folder'
            }
        }

        if IS_AT_LEAST_PLONE_5_1:
            expected[u'utf8:metadata'][u'utf8:modified'] = u'utf8:{}'.format(
                str(page.modified()).decode('utf-8'))

        self.assertEquals(expected, json.loads(data))
Beispiel #34
0
    def update(self):
        self.site = api.portal.get()

        self.folder = self.context_state.folder()

        self.user = api.user.get_current()
        self.csrf_token = createToken()
        self.registry = getUtility(IRegistry)
        self.pactions = api.portal.get_tool('portal_actions')

        self.econtext = createExprContext(
            self.folder, self.site, self.real_context)
Beispiel #35
0
 def testSet1(self):
     self._invalidateRequestMemoizations()
     self.loginAsPortalOwner()
     self.app.REQUEST['ACTUAL_URL'] = '%s/edit?_authenticator=%s' % (
         self.folder.test.absolute_url(),
         auth.createToken()
     )
     view = ContentViewsViewlet(self.folder.test, self.app.REQUEST, None)
     view.update()
     self.assertEqual(1, len([t for t in view.tabSet1 if t[
                      'id'] == 'folderContents']))
     self.assertEqual(['edit'], [t['id'] for t in view.tabSet1 if t['selected']])
    def test_store_save_simplelayout_state_thru_view(self, browser):
        payload = {"data": json.dumps(self.payload)}

        if IS_PLONE_5:
            from plone.protect.authenticator import createToken
            payload["_authenticator"] = createToken()

        browser.login().visit(self.container,
                              view='sl-ajax-save-state-view',
                              data=payload)

        browser.visit(self.container)
        self.assertEquals(self.payload, self.page_config.load())
Beispiel #37
0
    def __call__(self):
        soup = self.context.get_soup()
        columns = self.columns()
        aaData = list()
        length, lazydata = self._query(soup)
        # XXX Todo html from template
        if PLONE_PROTECT:
            token = createToken()
            url = self.context.absolute_url()
            html = '<a href="#" data-iid="%(iid)s" class="pfgsoup-edit">edit</a> '
            html += '<a href="%(url)s/pfgsoupdel?iid=%(iid)s&_authenticator=%(token)s" class="pfgsoup-delete">remove</a> '
            html += ('<a href="%(url)s/@@pfgsouplog?iid=%(iid)s&_authenticator=%(token)s" '
                     'class="pfgsoup-log">log</a>')
        else:
            url = self.context.absolute_url()
            html = '<a href="#" data-iid="%(iid)s" class="pfgsoup-edit">edit</a> '
            html += '<a href="%(url)s/pfgsoupdel?iid=%(iid)s" class="pfgsoup-delete">remove</a> '
            html += ('<a href="%(url)s/@@pfgsouplog?iid=%(iid)s" '
                     'class="pfgsoup-log">log</a>')


        def record2list(record):
            result = list()
            for colname in columns:
                value = record.attrs.get(colname, '')
                if isinstance(value, list):
                    value = ', '.join(value)
                elif isinstance(value, datetime.datetime):
                    value = value.isoformat()
                elif isinstance(value, dict):
                    value = ', '.join([str(_) for _ in value.items])
                try:
                    json.dumps(value)
                except TypeError:
                    value = str(value)
                result.append(value)
            if PLONE_PROTECT:
                result.append(html % {'iid': record.intid, 'url': url, 'token': token})
            else:
                result.append(html % {'iid': record.intid, 'url': url})
            return result
        for lazyrecord in self._slice(lazydata):
            aaData.append(record2list(lazyrecord()))
        data = {
          "sEcho": int(self.request.form['sEcho']),
          "iTotalRecords": soup.storage.length.value,
          "iTotalDisplayRecords": length,
          "aaData": aaData,
        }
        self.request.response.setHeader("Content-type", "application/json")
        return json.dumps(data)
 def setUp(self):
     """Custom shared utility setup for tests."""
     self.portal = self.layer['portal']
     setRoles(self.portal, TEST_USER_ID, ['Manager'])
     self.installer = api.portal.get_tool('portal_quickinstaller')
     self.request = self.layer['request']
     # Disable plone.protect for these tests
     self.request.form['_authenticator'] = createToken()
     # Eventuelly you find this also useful
     self.request.environ['REQUEST_METHOD'] = 'POST'
     self.tune = api.content.create(
         type='tune',
         title='tune',
         container=self.portal)
Beispiel #39
0
 def test_password_reset_password_does_not_match(self):
     registry = getUtility(IRegistry)
     registry['plone.two_factor_enabled'] = False
     login(self.portal, TEST_USER_NAME)
     self.request.form.update({
         'apiMethod': 'set_password',
         'username': TEST_USER_NAME,
         'existing_password': '******',
         'new_password': '******',
         '_authenticator': createToken()
     })
     view = SecureLoginView(self.portal, self.request)
     result = json.loads(view())
     self.assertFalse(result['success'])
Beispiel #40
0
        def test_add_to_portal_root_save(self):
            browser = Browser(self.layer['app'])
            browser.handleErrors = False

            # Login
            browser.open(self.portal.absolute_url() + '/login')
            browser.getControl(name='__ac_name').value = TEST_USER_NAME
            browser.getControl(name='__ac_password').value = TEST_USER_PASSWORD
            browser.getControl('Log in').click()

            # Enter the add screen for a temporary
            # portal_factory-managed object
            browser.open(
                '{}/portal_factory/Document/document.2010-02-04.2866363923/edit?_authenticator={}'.format(  # noqa
                    self.portal.absolute_url(),
                    createToken()))

            # We should now have cookies with the drafts information
            cookies = browser.cookies.forURL(browser.url)
            self.assertEqual(
                '"/plone/portal_factory/Document/document.2010-02-04.2866363923"',  # noqa
                cookies['plone.app.drafts.path'],
            )
            self.assertEqual(
                '"0%3ADocument"',
                cookies['plone.app.drafts.targetKey'],
            )
            self.assertNotIn(
                'plone.app.drafts.draftName',
                browser.cookies.forURL(browser.url),
            )

            # We can now fill in the required fields and save.
            # The cookies should expire.

            browser.getControl(name='title').value = u'New document'
            browser.getControl(name='form.button.save').click()
            self.assertNotIn(
                'plone.app.drafts.targetKey',
                browser.cookies.forURL(browser.url),
            )
            self.assertNotIn(
                'plone.app.drafts.path',
                browser.cookies.forURL(browser.url),
            )
            self.assertNotIn(
                'plone.app.drafts.draftName',
                browser.cookies.forURL(browser.url),
            )
Beispiel #41
0
        def test_add_to_portal_root_save(self):
            browser = Browser(self.layer['app'])
            browser.handleErrors = False

            # Login
            browser.open(self.portal.absolute_url() + '/login')
            browser.getControl(name='__ac_name').value = TEST_USER_NAME
            browser.getControl(name='__ac_password').value = TEST_USER_PASSWORD
            browser.getControl('Log in').click()

            # Enter the add screen for a temporary
            # portal_factory-managed object
            browser.open(
                '{}/portal_factory/Document/document.2010-02-04.2866363923/edit?_authenticator={}'
                .format(  # noqa
                    self.portal.absolute_url(), createToken()))

            # We should now have cookies with the drafts information
            cookies = browser.cookies.forURL(browser.url)
            self.assertEqual(
                '"/plone/portal_factory/Document/document.2010-02-04.2866363923"',  # noqa
                cookies['plone.app.drafts.path'],
            )
            self.assertEqual(
                '"0%3ADocument"',
                cookies['plone.app.drafts.targetKey'],
            )
            self.assertNotIn(
                'plone.app.drafts.draftName',
                browser.cookies.forURL(browser.url),
            )

            # We can now fill in the required fields and save.
            # The cookies should expire.

            browser.getControl(name='title').value = u'New document'
            browser.getControl(name='form.button.save').click()
            self.assertNotIn(
                'plone.app.drafts.targetKey',
                browser.cookies.forURL(browser.url),
            )
            self.assertNotIn(
                'plone.app.drafts.path',
                browser.cookies.forURL(browser.url),
            )
            self.assertNotIn(
                'plone.app.drafts.draftName',
                browser.cookies.forURL(browser.url),
            )
Beispiel #42
0
    def update(self):
        self.site = api.portal.get()

        self.context_state = getMultiAdapter(
            (aq_inner(self.real_context), self.request),
            name=u'plone_context_state')
        self.folder = self.context_state.folder()

        self.user = api.user.get_current()
        self.csrf_token = createToken()
        self.registry = getUtility(IRegistry)
        self.pactions = api.portal.get_tool('portal_actions')

        self.econtext = createExprContext(self.folder, self.site,
                                          self.real_context)
Beispiel #43
0
    def setUp(self):
        super(BaseTestCase, self).setUp()
        # Fixing CSRF protection
        # https://github.com/plone/plone.protect/#fixing-csrf-protection-failures-in-tests
        self.request = self.layer["request"]
        # Disable plone.protect for these tests
        self.request.form["_authenticator"] = createToken()
        # Eventuelly you find this also useful
        self.request.environ["REQUEST_METHOD"] = "POST"

        setRoles(self.portal, TEST_USER_ID, ["LabManager", "Manager"])

        # Default skin is set to "Sunburst Theme"!
        # => This causes an `AttributeError` when we want to access
        #    e.g. 'guard_handler' FSPythonScript
        self.portal.changeSkin("Plone Default")
Beispiel #44
0
 def site_config(self):
     return json.dumps({
         'actionUrl': (
             '{0}/++sitelayout++/custom/'
             '@@plone.resourceeditor.filemanager-actions'.format(
                 self.context.absolute_url()
             )
         ),
         'uploadUrl': (
             '{0}/portal_resources/sitelayout/custom/'
             'themeFileUpload?_authenticator={1}'.format(
                 self.context.absolute_url(),
                 createToken()
             )
         ),
     })
    def setUp(self):
        self.portal = self.layer['portal']
        login(self.portal, TEST_USER_NAME)
        setRoles(self.portal, TEST_USER_ID, ['Manager'])

        self.portal.invokeFactory('Document', id="page", title="page")
        self.portal.page.reindexObject()

        self.env = {'HTTP_ACCEPT_LANGUAGE': 'en', 'REQUEST_METHOD': 'POST'}
        self.request = makerequest(self.layer['app']).REQUEST
        self.request.environ.update(self.env)
        self.request.form = {
            'selection': '["' + IUUID(self.portal.page) + '"]',
            '_authenticator': createToken(),
            'folder': '/'
        }
        self.request.REQUEST_METHOD = 'POST'
    def setUp(self):
        """Custom shared utility setup for tests."""
        self.portal = self.layer["portal"]
        self.request = self.layer["request"]
        setRoles(self.portal, TEST_USER_ID, ["Manager"])

        # enable blocks behavior
        fti = queryUtility(IDexterityFTI, name="Document")
        behaviors = [x for x in fti.behaviors]
        behaviors.append("volto.blocks")
        fti.behaviors = tuple(behaviors)

        migration_view = api.content.get_view(name="data-migration",
                                              context=self.portal,
                                              request=self.request)
        self.request.form["_authenticator"] = createToken()
        migration_view.do_migrate()
    def setUp(self):
        self.portal = self.layer['portal']
        login(self.portal, TEST_USER_NAME)
        setRoles(self.portal, TEST_USER_ID, ['Manager'])

        self.portal.invokeFactory('Document', id="page", title="page")
        self.portal.page.reindexObject()

        self.env = {'HTTP_ACCEPT_LANGUAGE': 'en', 'REQUEST_METHOD': 'POST'}
        self.request = makerequest(self.layer['app']).REQUEST
        self.request.environ.update(self.env)
        self.request.form = {
            'selection': '["' + IUUID(self.portal.page) + '"]',
            '_authenticator': createToken(),
            'folder': '/'
        }
        self.request.REQUEST_METHOD = 'POST'
Beispiel #48
0
        def test_add_to_folder(self):
            browser = Browser(self.layer['app'])
            browser.handleErrors = False

            uuid = IUUID(self.folder)

            # Login
            browser.open(self.portal.absolute_url() + '/login')
            browser.getControl(name='__ac_name').value = TEST_USER_NAME
            browser.getControl(name='__ac_password').value = TEST_USER_PASSWORD
            browser.getControl('Log in').click()

            # Enter the add screen for a temporary
            # portal_factory-managed object
            browser.open(
                '{}/portal_factory/Document/document.2010-02-04.2866363923/edit?_authenticator={}'
                .format(  # noqa
                    self.folder.absolute_url(), createToken()))

            # We should now have cookies with the drafts information
            cookies = browser.cookies.forURL(browser.url)
            path = '"{0}/portal_factory/Document/document.2010-02-04.2866363923"'  # noqa
            self.assertEqual(
                path.format(self.folder.absolute_url_path()),
                cookies['plone.app.drafts.path'],
            )
            self.assertEqual(
                '"{0}%3ADocument"'.format(uuid),
                cookies['plone.app.drafts.targetKey'],
            )
            self.assertNotIn(
                'plone.app.drafts.draftName',
                browser.cookies.forURL(browser.url),
            )

            # We can now cancel the edit. The cookies should expire.
            browser.getControl(name='form.button.cancel').click()
            self.assertNotIn(
                'plone.app.drafts.targetKey',
                browser.cookies.forURL(browser.url),
            )
            self.assertNotIn(
                'plone.app.drafts.path',
                browser.cookies.forURL(browser.url),
            )
Beispiel #49
0
        def test_add_to_folder(self):
            browser = Browser(self.layer['app'])
            browser.handleErrors = False

            uuid = IUUID(self.folder)

            # Login
            browser.open(self.portal.absolute_url() + '/login')
            browser.getControl(name='__ac_name').value = TEST_USER_NAME
            browser.getControl(name='__ac_password').value = TEST_USER_PASSWORD
            browser.getControl('Log in').click()

            # Enter the add screen for a temporary
            # portal_factory-managed object
            browser.open(
                '{}/portal_factory/Document/document.2010-02-04.2866363923/edit?_authenticator={}'.format(  # noqa
                    self.folder.absolute_url(),
                    createToken()))

            # We should now have cookies with the drafts information
            cookies = browser.cookies.forURL(browser.url)
            path = '"{0}/portal_factory/Document/document.2010-02-04.2866363923"'  # noqa
            self.assertEqual(
                path.format(self.folder.absolute_url_path()),
                cookies['plone.app.drafts.path'],
            )
            self.assertEqual(
                '"{0}%3ADocument"'.format(uuid),
                cookies['plone.app.drafts.targetKey'],
            )
            self.assertNotIn(
                'plone.app.drafts.draftName',
                browser.cookies.forURL(browser.url),
            )

            # We can now cancel the edit. The cookies should expire.
            browser.getControl(name='form.button.cancel').click()
            self.assertNotIn(
                'plone.app.drafts.targetKey',
                browser.cookies.forURL(browser.url),
            )
            self.assertNotIn(
                'plone.app.drafts.path',
                browser.cookies.forURL(browser.url),
            )
Beispiel #50
0
    def transform(self, result):
        result = self.parseTree(result)
        if result is None:
            return None
        root = result.tree.getroot()
        url = urlparse(self.request.URL)
        try:
            token = createToken()
        except ComponentLookupError:
            context = self.getContext()
            if IApplication.providedBy(context) or \
                    IResource.providedBy(context):
                # skip here, utility not installed yet on zope root
                return
            raise

        for form in root.cssselect('form'):
            # XXX should we only do POST? If we're logged in and
            # it's an internal form, I'm inclined to say no...
            #method = form.attrib.get('method', 'GET').lower()
            #if method != 'post':
            #    continue

            # some get forms we definitely do not want to protect.
            # for now, we know search we do not want to protect
            method = form.attrib.get('method', 'GET').lower()
            action = form.attrib.get('action', '').strip()
            if method == 'get' and '@@search' in action:
                continue
            action = form.attrib.get('action', '').strip()
            if not self.isActionInSite(action, url):
                continue
            # check if the token is already on the form..
            hidden = form.cssselect('[name="_authenticator"]')
            if len(hidden) == 0:
                hidden = etree.Element("input")
                hidden.attrib['name'] = '_authenticator'
                hidden.attrib['type'] = 'hidden'
                hidden.attrib['value'] = token
                form.append(hidden)

        return result
    def setUp(self):
        self.portal = self.layer['portal']
        self.request = self.layer['request']
        # Disable plone.protect for these tests
        self.request.environ['REQUEST_METHOD'] = 'POST'
        self.request.form['_authenticator'] = createToken()
        login(self.portal, TEST_USER_NAME)
        setRoles(self.portal, TEST_USER_ID, ['Manager'])

        # set available languages
        registry = getUtility(IRegistry)
        registry['plone.available_languages'] = ['en', 'de']

        self.portal.invokeFactory('Folder', 'main1')
        self.portal.main1.invokeFactory('Folder', 'sub1')
        self.portal.main1.sub1.invokeFactory('Folder', 'subsub1')
        self.portal.main1.invokeFactory('Document', 'sub2')
        self.portal.invokeFactory('Document', 'main2')

        self.setup_initial()
Beispiel #52
0
def render_ajax_form(context, request, name):
    """Render ajax form on context by view name.

    By default contents of div with id ``content`` gets replaced. If fiddle
    mode or selector needs to get customized, ``bda.plone.ajax.form.mode``
    and ``bda.plone.ajax.form.selector`` must be given as request parameters.
    """
    try:
        key_manager = getUtility(IKeyManager)
    except ComponentLookupError:
        key_manager = getRootKeyManager(getRoot(context))
    token = createToken(manager=key_manager)
    try:
        result = context.restrictedTraverse(name)()
        selector = request.get('bda.plone.ajax.form.selector', '#content')
        mode = request.get('bda.plone.ajax.form.mode', 'inner')
        continuation = request.get('bda.plone.ajax.continuation')
        form_continue = AjaxFormContinue(continuation)
        response = ajax_form_template % {
            'form': result,
            'token': token,
            'selector': selector,
            'mode': mode,
            'next': form_continue.next,
        }
        return response
    except Exception:
        result = '<div>Form rendering error</div>'
        selector = request.get('bda.plone.ajax.form.selector', '#content')
        mode = request.get('bda.plone.ajax.form.mode', 'inner')
        tb = format_traceback()
        continuation = AjaxMessage(tb, 'error', None)
        form_continue = AjaxFormContinue([continuation])
        response = ajax_form_template % {
            'form': result,
            'token': token,
            'selector': selector,
            'mode': mode,
            'next': form_continue.next,
        }
        return response
Beispiel #53
0
def addTokenToUrl(url, req=None, manager=None):
    if not url:
        return url
    if req is None:
        req = getRequest()
    if not url.startswith(req.SERVER_URL):
        # only transforms urls to same site
        return url
    if '_auth_token' not in req.environ:
        # let's cache this value since this could be called
        # many times for one request
        req.environ['_auth_token'] = createToken(manager=manager)
    token = req.environ['_auth_token']

    if '_authenticator' not in url:
        if '?' not in url:
            url += '?'
        else:
            url += '&'
        url += '_authenticator=' + token
    return url
Beispiel #54
0
    def transform(self, result, encoding):
        result = self.parseTree(result, encoding)
        if result is None:
            return None
        root = result.tree.getroot()
        url = urlparse(self.request.URL)
        try:
            token = createToken(manager=self.key_manager)
        except ComponentLookupError:
            if self.site is not None:
                LOGGER.warn('Keyring not found on site. This should not happen', exc_info=True)
            return result

        for form in root.cssselect('form'):
            # XXX should we only do POST? If we're logged in and
            # it's an internal form, I'm inclined to say no...
            # method = form.attrib.get('method', 'GET').lower()
            # if method != 'post':
            #    continue

            # some get forms we definitely do not want to protect.
            # for now, we know search we do not want to protect
            method = form.attrib.get('method', 'GET').lower()
            action = form.attrib.get('action', '').strip()
            if method == 'get' and '@@search' in action:
                continue
            action = form.attrib.get('action', '').strip()
            if not self.isActionInSite(action, url):
                continue
            # check if the token is already on the form..
            hidden = form.cssselect('[name="_authenticator"]')
            if len(hidden) == 0:
                hidden = etree.Element("input")
                hidden.attrib['name'] = '_authenticator'
                hidden.attrib['type'] = 'hidden'
                hidden.attrib['value'] = token
                form.append(hidden)

        return result
Beispiel #55
0
 def morphVersionDataToHistoryFormat(vdata, version_id):
     meta = vdata["metadata"]["sys_metadata"]
     userid = meta["principal"]
     token = createToken()
     preview_url = \
         "%s/versions_history_form?version_id=%s&_authenticator=%s#version_preview" % (  # noqa
             context_url,
             version_id,
             token
         )
     info = dict(
         type='versioning',
         action=_(u"Edited"),
         transition_title=_(u"Edited"),
         actorid=userid,
         time=meta["timestamp"],
         comments=meta['comment'],
         version_id=version_id,
         preview_url=preview_url,
     )
     if can_diff:
         if version_id > 0:
             info["diff_previous_url"] = (
                 "%s/@@history?one=%s&two=%s&_authenticator=%s" %
                 (context_url, version_id, version_id - 1, token)
             )
         if not rt.isUpToDate(context, version_id):
             info["diff_current_url"] = (
                 "%s/@@history?one=current&two=%s&_authenticator=%s" %
                 (context_url, version_id, token)
             )
     if can_revert:
         info["revert_url"] = "%s/revertversion" % context_url
     else:
         info["revert_url"] = None
     info.update(self.getUserInfo(userid))
     return info
    def test_image_tile(self):
        annotations = IAnnotations(self.page)
        annotations['plone.tiles.data.test'] = PersistentDict({
            'image': NamedImage(image(), 'image/png', filename=u'color.png')
        })

        transaction.commit()

        self.browser.open(
            self.pageURL +
            '/@@plone.app.standardtiles.image/test?_authenticator={}'.format(
                createToken()
            )
        )

        # Confirm pass CSRF protection on Plone 5
        try:
            self.browser.getControl(name='form.button.confirm').click()
        except LookupError:
            pass

        root = fromstring(self.browser.contents)
        nodes = root.xpath('//body//img')
        self.assertEqual(len(nodes), 1)
 def _getauth(self, userName):
     self.login(userName)
     return createToken()
 def init_url(self, uid):
     return '{url}/@@pay_invoice?uid={uid}&_authenticator={token}'.format(
         url=self.context.absolute_url(),
         uid=uid,
         token=createToken()
     )
Beispiel #59
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:
                        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