Example #1
0
    def traverseRelativeURL(self, request, ob, path):
        ob = self.traversePath(request, ob, path)

        while True:
            adapter = IBrowserPublisher(ob, None)
            if adapter is None:
                return ob
            ob, path = adapter.browserDefault(request)
            ob = ProxyFactory(ob)
            if not path:
                return ob

            ob = self.traversePath(request, ob, path)
Example #2
0
    def traverseRelativeURL(self, request, ob, path):
        ob = self.traversePath(request, ob, path)

        while True:
            adapter = IBrowserPublisher(ob, None)
            if adapter is None:
                return ob
            ob, path = adapter.browserDefault(request)
            ob = ProxyFactory(ob)
            if not path:
                return ob

            ob = self.traversePath(request, ob, path)
Example #3
0
    def traverseRelativeURL(self, request, ob, path):
        """Path traversal that includes browserDefault paths"""
        ob = self.traversePath(request, ob, path)

        while True:
            adapter = IBrowserPublisher(ob, None)
            if adapter is None:
                return ob
            ob, path = adapter.browserDefault(request)
            ob = self.proxy(ob)
            if not path:
                return ob

            ob = self.traversePath(request, ob, path)
Example #4
0
    def traverseRelativeURL(self, request, ob, path):
        """Path traversal that includes browserDefault paths"""
        ob = self.traversePath(request, ob, path)

        while True:
            adapter = IBrowserPublisher(ob, None)
            if adapter is None:
                return ob
            ob, path = adapter.browserDefault(request)
            ob = self.proxy(ob)
            if not path:
                return ob

            ob = self.traversePath(request, ob, path)
 def add_src_from_id(self, items):
     results = []
     develmode = self.getDevelMode()
     portal = self.portal_state.portal()
     for info in items:
         item = copy(info)
         itemid = item["id"]
         if itemid.startswith('http'):
             info['src'] = itemid
             results.append(info)
         else:
             if '.min.' in itemid and develmode:
                 try:
                     id = itemid.replace(".min.", ".")
                     content = portal.restrictedTraverse(id)
                     itemid = id
                 except KeyError:
                     content = portal.restrictedTraverse(itemid)
             else:
                 content = portal.restrictedTraverse(itemid)
             if content and IBrowserPublisher.providedBy(content):
                 path = content.context.path
                 time = str(os.path.getmtime(path))
                 info["src"] = "%s/%s?time%s" % (self.site_url,
                                                 itemid,
                                                 time)
                 results.append(info)
             elif content:
                 info["src"] = "%s/%s" % (self.site_url, info["id"])
                 results.append(info)
     return results
Example #6
0
    def publish(self, origin):
        path = self.path
        request = origin.request
        del request.PARENTS[-1] # Remove the current item and traverse
        if self.clear:
            request.form.clear()
        component = lookupREST(origin.context, request, path.pop())

        while path:
            while path:
                part = path.pop()
                component = request.traverseName(component, part)

            adapter = None
            if IBrowserPublisher.providedBy(component):
                adapter = component
            else:
                adapter = queryMultiAdapter(
                    (component, request), IBrowserPublisher)

            if adapter is not None:
                component, default_path = adapter.browserDefault(request)
                if default_path:
                    path.extend(reversed(default_path))

        return component()
Example #7
0
    def getDefaultTraversal(self, request, obj):
        if IBrowserPublisher.providedBy(obj):
            return obj.browserDefault(request)

        adapter = zope.component.queryMultiAdapter((obj, request),
                                                   IBrowserPublisher)
        if adapter is not None:
            return adapter.browserDefault(request)
        return obj, None
Example #8
0
 def getDefaultTraversal(self, request, ob):
     if IBrowserPublisher.providedBy(ob):
         return ob.browserDefault(request)
     else:
         adapter = queryMultiAdapter((ob, request), IBrowserPublisher)
         if adapter is not None:
             ob, path = adapter.browserDefault(request)
             return ob, path
         else:
             return ob, None
    def _generateIncludes(self, libraries):
        # generate the HTML that will be included in the response
        site = zope.component.hooks.getSite()
        if site is None:
            return

        resources = queryMultiAdapter((site, self._request),
                                      interface.Interface,
                                      name='')

        if not IBrowserPublisher.providedBy(resources):
            # a setup with no resources factory is supported; in this
            # case, we manually craft a URL to the resource publisher
            # (see ``zope.browserresource.resource``).
            resources = None
            base = queryMultiAdapter((site, self._request),
                                     IAbsoluteURL,
                                     name="resource")
            if base is None:
                baseURL = str(
                    getMultiAdapter((site, self._request), IAbsoluteURL))
            else:
                baseURL = str(base)

        html = []
        for lib in libraries:
            if resources is not None:
                library_resources = resources[lib]

            included = zc.resourcelibrary.getIncluded(lib)
            for file_name in included:
                if resources is not None:
                    url = library_resources[file_name]()
                else:
                    url = "%s/@@/%s/%s" % (baseURL, lib, file_name)
                if file_name.endswith('.js'):
                    html.append('<script src="%s" ' % url)
                    html.append('    type="text/javascript">')
                    html.append('</script>')
                elif file_name.endswith('.css'):
                    html.append('<style type="text/css" media="all">')
                    html.append('  <!--')
                    html.append('    @import url("%s");' % url)
                    html.append('  -->')
                    html.append('</style>')
                elif file_name.endswith('.kss'):
                    html.append(
                        '<link type="text/kss" href="%s" rel="kinetic-stylesheet" />'
                        % url)
                else:
                    # shouldn't get here; zcml.py is supposed to check includes
                    raise RuntimeError('Resource library doesn\'t know how to '
                                       'include this file: "%s"' % file_name)

        return '\n    '.join(html)
Example #10
0
 def getDefaultTraversal(self, request, ob):
     if IBrowserPublisher.providedBy(ob):
         # ob is already proxied, so the result of calling a method will be
         return ob.browserDefault(request)
     else:
         adapter = zapi.queryMultiAdapter((ob, request), IBrowserPublisher)
         if adapter is not None:
             ob, path = adapter.browserDefault(request)
             ob = ProxyFactory(ob)
             return ob, path
         else:
             # ob is already proxied
             return ob, None
Example #11
0
 def getDefaultTraversal(self, request, ob):
     if IBrowserPublisher.providedBy(ob):
         # ob is already proxied, so the result of calling a method will be
         return ob.browserDefault(request)
     else:
         adapter = queryMultiAdapter((ob, request), IBrowserPublisher)
         if adapter is not None:
             ob, path = adapter.browserDefault(request)
             ob = ProxyFactory(ob)
             return ob, path
         else:
             # ob is already proxied
             return ob, None
Example #12
0
    def _generateIncludes(self, libraries):
        # generate the HTML that will be included in the response
        site = zope.component.hooks.getSite()
        if site is None:
            return

        resources = queryMultiAdapter(
            (site, self._request), interface.Interface, name='')

        if not IBrowserPublisher.providedBy(resources):
            # a setup with no resources factory is supported; in this
            # case, we manually craft a URL to the resource publisher
            # (see ``zope.browserresource.resource``).
            resources = None
            base = queryMultiAdapter(
                (site, self._request), IAbsoluteURL, name="resource")
            if base is None:
                baseURL = str(getMultiAdapter(
                    (site, self._request), IAbsoluteURL))
            else:
                baseURL = str(base)

        html = []
        for lib in libraries:
            if resources is not None:
                library_resources = resources[lib]

            included = zc.resourcelibrary.getIncluded(lib)
            for file_name in included:
                if resources is not None:
                    url = library_resources[file_name]()
                else:
                    url = "%s/@@/%s/%s" % (baseURL, lib, file_name)
                if file_name.endswith('.js'):
                    html.append('<script src="%s" ' % url)
                    html.append('    type="text/javascript">')
                    html.append('</script>')
                elif file_name.endswith('.css'):
                    html.append('<style type="text/css" media="all">')
                    html.append('  <!--')
                    html.append('    @import url("%s");' % url)
                    html.append('  -->')
                    html.append('</style>')
                elif file_name.endswith('.kss'):
                    html.append('<link type="text/kss" href="%s" rel="kinetic-stylesheet" />' % url)
                else:
                    # shouldn't get here; zcml.py is supposed to check includes
                    raise RuntimeError('Resource library doesn\'t know how to '
                                       'include this file: "%s"' % file_name)

        return '\n    '.join(html)
Example #13
0
 def __call__(self):
     """Return the JSON cache."""
     if IBrowserPublisher.providedBy(self.context):
         view = self.context
     else:
         defaultviewname = getDefaultViewName(self.context, self.request)
         view = getMultiAdapter((self.context, self.request),
                                name=defaultviewname)
     if view is None:
         return
     naked_view = removeSecurityProxy(view)
     naked_view.initialize()
     cache = naked_view.getCacheJSON()
     self.request.response.setHeader('content-type', 'application/json')
     return cache
Example #14
0
    def test_class_w_implements(self):
        xmlconfig(
            StringIO(template % '''
            <browser:page
                name="test"
                class="
             zope.app.publisher.browser.tests.test_directives.C_w_implements"
                for="zope.app.component.tests.views.IC"
                attribute="index"
                permission="zope.Public"
                />
            '''))

        v = component.getMultiAdapter((ob, request), name='test')
        self.assertEqual(v.index(), v)
        self.assert_(IBrowserPublisher.providedBy(v))
Example #15
0
 def __call__(self):
     """Return the JSON cache."""
     if IBrowserPublisher.providedBy(self.context):
         view = self.context
     else:
         defaultviewname = getDefaultViewName(
             self.context, self.request)
         view = getMultiAdapter(
             (self.context, self.request), name=defaultviewname)
     if view is None:
         return
     naked_view = removeSecurityProxy(view)
     naked_view.initialize()
     cache = naked_view.getCacheJSON()
     self.request.response.setHeader('content-type', 'application/json')
     return cache
Example #16
0
    def test_class_w_implements(self):
        xmlconfig(
            StringIO(template % u'''
            <browser:page
                name="test"
                class="
             zope.browserpage.tests.test_page.C_w_implements"
                for="zope.browserpage.tests.test_page.IC"
                attribute="index"
                permission="zope.Public"
                />
            '''))

        v = component.getMultiAdapter((ob, self.request), name='test')
        self.assertEqual(v.index(), v)
        self.assertTrue(IBrowserPublisher.providedBy(v))
Example #17
0
    def test_class_w_implements(self):
        xmlconfig(StringIO(template %
            '''
            <browser:page
                name="test"
                class="
             zope.app.publisher.browser.tests.test_directives.C_w_implements"
                for="zope.app.component.tests.views.IC"
                attribute="index"
                permission="zope.Public"
                />
            '''
            ))

        v = zapi.getMultiAdapter((ob, request), name='test')
        self.assertEqual(v.index(), v)
        self.assert_(IBrowserPublisher.providedBy(v))
    def test_class_w_implements(self):
        xmlconfig(StringIO(
            template %
            u'''
            <browser:page
                name="test"
                class="
             zope.browserpage.tests.test_page.C_w_implements"
                for="zope.browserpage.tests.test_page.IC"
                attribute="index"
                permission="zope.Public"
                />
            '''
        ))

        v = component.getMultiAdapter((ob, self.request), name='test')
        self.assertEqual(v.index(), v)
        self.assertTrue(IBrowserPublisher.providedBy(v))
Example #19
0
    def render_error(self, error, last_known_obj):
        """Render and log an error.
        """
        if IBrowserPage.providedBy(last_known_obj):
            #of the last obj is a view, use it's context (which should be
            # an IAcquirer)
            last_known_obj = last_known_obj.context
        if not IAcquirer.providedBy(last_known_obj):
            last_known_site = getSite()
            if last_known_site is not None:
                last_known_obj = last_known_site
        context = DefaultError(error)
        if IAcquirer.providedBy(last_known_obj):
            context = context.__of__(last_known_obj)
        error_view = queryMultiAdapter(
            (context, self.request), name='error.html')
        if IBrowserPublisher.providedBy(error_view):
            error_view, error_path = error_view.browserDefault(self.request)
            if error_path:
                raise NotImplementedError(
                    u'Error browserDefault retuned an path. '
                    u'This is not implemented.')

        if error_view is not None:
            notify(interfaces.PublicationBeforeError(
                    self.request, last_known_obj))
            try:
                error_result = error_view()
                if error_result is not None:
                    self.response.setBody(error_result)

                notify(interfaces.PublicationAfterRender(
                        self.request, error_view))

            except Exception:
                log_last_error(
                    self.request, self.response, obj=last_known_obj,
                    extra=u"Error while rendering error message")
                self.response.setStatus(500)
                self.response.setBody(ERROR_WHILE_RENDERING_ERROR_TEMPLATE)
        else:
            logger.error('No action defined for last exception')
            self.response.setStatus(500)
            self.response.setBody(DEFAULT_ERROR_TEMPLATE)
Example #20
0
    def get(self, name, default=_marker):
        value = super(SkinDirectory, self).get(name, None)
        if value is not None:
            return value

        wrapper = RequestWrapper(self.request)

        # lookup through the layer stack to find other directory
        # resources that might contain the requested resource.
        for layer in self.layers:
            interface.directlyProvides(wrapper, layer)
            resource_dir = component.queryAdapter(wrapper, name=self.__name__)
            if not ( IResource.providedBy( resource_dir ) \
                and IBrowserPublisher.providedBy( resource_dir ) ):
                continue
            resource = resource_dir.get(name)
            if resource is not None:
                return resource
        raise NotFound(name)
Example #21
0
def register_help_folder(context, folder, name):
    """Create a help folder subclass and register it with the ZCA."""

    help_folder = type(
        str('%s for %s' % (name, folder)), (HelpFolder, ),
        {'folder': folder, '__name__': name})

    defineChecker(
        help_folder,
        NamesChecker(list(IBrowserPublisher.names(True)) + ['__call__']))

    context.action(
        discriminator=(
            'view', (ILaunchpadApplication, IBrowserRequest), name),
        callable=handler,
        args=('registerAdapter',
              help_folder, (ILaunchpadApplication, IBrowserRequest),
              Interface, name, context.info),
        )
Example #22
0
def register_help_folder(context, folder, name):
    """Create a help folder subclass and register it with the ZCA."""

    help_folder = type(str('%s for %s' % (name, folder)), (HelpFolder, ), {
        'folder': folder,
        '__name__': name
    })

    defineChecker(
        help_folder,
        NamesChecker(list(IBrowserPublisher.names(True)) + ['__call__']))

    context.action(
        discriminator=('view', (ILaunchpadApplication, IBrowserRequest), name),
        callable=handler,
        args=('registerAdapter', help_folder, (ILaunchpadApplication,
                                               IBrowserRequest), Interface,
              name, context.info),
    )
 def get(self, name, default=_marker):
     value = super( SkinDirectory, self ).get( name, None)
     if value is not None:
         return value
     
     wrapper = RequestWrapper( self.request )
     
     # lookup through the layer stack to find other directory
     # resources that might contain the requested resource.
     for layer in self.layers:
         interface.directlyProvides( wrapper, layer )
         resource_dir = component.queryAdapter(wrapper, name=self.__name__)
         if not ( IResource.providedBy( resource_dir ) \
             and IBrowserPublisher.providedBy( resource_dir ) ):
             continue
         resource = resource_dir.get( name )
         if resource is not None:
             return resource
     raise NotFound( name )
Example #24
0
    def get_default_traversal(self, request, ob):
        """Get the default traversal steps for an object.

        Returns (next_object, steps).
        """
        if request.form_action:
            # Do not follow default traversal when a form action was
            # provided.
            return ob, None

        if IBrowserPublisher.providedBy(ob):
            # ob is already proxied, so the result of calling a method
            # will be too.
            return ob.browserDefault(request)

        adapter = queryMultiAdapter((ob, request), IBrowserPublisher)
        if adapter is not None:
            ob, path = adapter.browserDefault(request)
            ob = self.proxy_factory(ob)
            return ob, path

        # ob is already proxied
        return ob, None
Example #25
0
    def traverse(self, path, response=None, validated_hook=None):
        """Traverse the object space

        The REQUEST must already have a PARENTS item with at least one
        object in it.  This is typically the root object.
        """
        request=self
        request_get=request.get
        if response is None: response=self.response

        # remember path for later use
        browser_path = path

        # Cleanup the path list
        if path[:1]=='/':  path=path[1:]
        if path[-1:]=='/': path=path[:-1]
        clean=[]
        for item in path.split('/'):
            # Make sure that certain things that dont make sense
            # cannot be traversed.
            if item in ('REQUEST', 'aq_self', 'aq_base'):
                return response.notFoundError(path)
            if not item or item=='.':
                continue
            elif item == '..':
                del clean[-1]
            else: clean.append(item)
        path=clean

        # How did this request come in? (HTTP GET, PUT, POST, etc.)
        method = request_get('REQUEST_METHOD', 'GET').upper()

        if method=='GET' or method=='POST' and not isinstance(response,
                                                              xmlrpc.Response):
            # Probably a browser
            no_acquire_flag=0
            # index_html is still the default method, only any object can
            # override it by implementing its own __browser_default__ method
            method = 'index_html'
        elif self.maybe_webdav_client:
            # Probably a WebDAV client.
            no_acquire_flag=1
        else:
            no_acquire_flag=0

        URL=request['URL']
        parents=request['PARENTS']
        object=parents[-1]
        del parents[:]

        self.roles = getRoles(None, None, object, UNSPECIFIED_ROLES)

        # if the top object has a __bobo_traverse__ method, then use it
        # to possibly traverse to an alternate top-level object.
        if hasattr(object,'__bobo_traverse__'):
            try:
                object=object.__bobo_traverse__(request)
                self.roles = getRoles(None, None, object, UNSPECIFIED_ROLES)
            except: pass

        if not path and not method:
            return response.forbiddenError(self['URL'])

        # Traverse the URL to find the object:
        if hasattr(object, '__of__'):
            # Try to bind the top-level object to the request
            # This is how you get 'self.REQUEST'
            object=object.__of__(RequestContainer(REQUEST=request))
        parents.append(object)

        steps=self.steps
        self._steps = _steps = map(quote, steps)
        path.reverse()

        request['TraversalRequestNameStack'] = request.path = path
        request['ACTUAL_URL'] = request['URL'] + quote(browser_path)

        # Set the posttraverse for duration of the traversal here
        self._post_traverse = post_traverse = []

        entry_name = ''
        try:
            # We build parents in the wrong order, so we
            # need to make sure we reverse it when we're done.
            while 1:
                bpth = getattr(object, '__before_publishing_traverse__', None)
                if bpth is not None:
                    bpth(object, self)

                path = request.path = request['TraversalRequestNameStack']
                # Check for method:
                if path:
                    entry_name = path.pop()
                else:
                    # If we have reached the end of the path, we look to see
                    # if we can find IBrowserPublisher.browserDefault. If so,
                    # we call it to let the object tell us how to publish it.
                    # BrowserDefault returns the object to be published
                    # (usually self) and a sequence of names to traverse to
                    # find the method to be published.

                    # This is webdav support. The last object in the path
                    # should not be acquired. Instead, a NullResource should
                    # be given if it doesn't exist:
                    if (no_acquire_flag and
                        hasattr(object, 'aq_base') and
                        not hasattr(object,'__bobo_traverse__')):
                        if object.aq_parent is not object.aq_inner.aq_parent:
                            from webdav.NullResource import NullResource
                            object = NullResource(parents[-2], object.getId(),
                                                  self).__of__(parents[-2])

                    if IBrowserPublisher.providedBy(object):
                        adapter = object
                    else:
                        adapter = queryMultiAdapter((object, self),
                                                    IBrowserPublisher)
                        if adapter is None:
                            # Zope2 doesn't set up its own adapters in a lot
                            # of cases so we will just use a default adapter.
                            adapter = DefaultPublishTraverse(object, self)

                    object, default_path = adapter.browserDefault(self)
                    if default_path:
                        request._hacked_path=1
                        if len(default_path) > 1:
                            path = list(default_path)
                            method = path.pop()
                            request['TraversalRequestNameStack'] = path
                            continue
                        else:
                            entry_name = default_path[0]
                    elif (method and hasattr(object,method)
                          and entry_name != method
                          and getattr(object, method) is not None):
                        request._hacked_path=1
                        entry_name = method
                        method = 'index_html'
                    else:
                        if hasattr(object, '__call__'):
                            self.roles = getRoles(object, '__call__', object.__call__,
                                                  self.roles)
                        if request._hacked_path:
                            i=URL.rfind('/')
                            if i > 0: response.setBase(URL[:i])
                        break
                step = quote(entry_name)
                _steps.append(step)
                request['URL'] = URL = '%s/%s' % (request['URL'], step)

                try:
                    subobject = self.traverseName(object, entry_name)
                    if (hasattr(object,'__bobo_traverse__') or
                        hasattr(object, entry_name)):
                        check_name = entry_name
                    else:
                        check_name = None

                    self.roles = getRoles(
                        object, check_name, subobject,
                        self.roles)
                    object = subobject
                # traverseName() might raise ZTK's NotFound
                except (KeyError, AttributeError, ztkNotFound):
                    if response.debug_mode:
                        return response.debugError(
                            "Cannot locate object at: %s" % URL)
                    else:
                        return response.notFoundError(URL)
                except Forbidden, e:
                    if self.response.debug_mode:
                        return response.debugError(e.args)
                    else:
                        return response.forbiddenError(entry_name)

                parents.append(object)

                steps.append(entry_name)
        finally:
            parents.reverse()

        # Note - no_acquire_flag is necessary to support
        # things like DAV.  We have to make sure
        # that the target object is not acquired
        # if the request_method is other than GET
        # or POST. Otherwise, you could never use
        # PUT to add a new object named 'test' if
        # an object 'test' existed above it in the
        # heirarchy -- you'd always get the
        # existing object :(
        if (no_acquire_flag and
            hasattr(parents[1], 'aq_base') and
            not hasattr(parents[1],'__bobo_traverse__')):
            if not (hasattr(parents[1].aq_base, entry_name) or
                    parents[1].aq_base.has_key(entry_name)):
                raise AttributeError, entry_name

        # After traversal post traversal hooks aren't available anymore
        del self._post_traverse

        request['PUBLISHED'] = parents.pop(0)

        # Do authorization checks
        user=groups=None
        i=0

        if 1:  # Always perform authentication.

            last_parent_index=len(parents)
            if hasattr(object, '__allow_groups__'):
                groups=object.__allow_groups__
                inext=0
            else:
                inext=None
                for i in range(last_parent_index):
                    if hasattr(parents[i],'__allow_groups__'):
                        groups=parents[i].__allow_groups__
                        inext=i+1
                        break

            if inext is not None:
                i=inext

                if hasattr(groups, 'validate'): v=groups.validate
                else: v=old_validation

                auth=request._auth

                if v is old_validation and self.roles is UNSPECIFIED_ROLES:
                    # No roles, so if we have a named group, get roles from
                    # group keys
                    if hasattr(groups,'keys'): self.roles=groups.keys()
                    else:
                        try: groups=groups()
                        except: pass
                        try: self.roles=groups.keys()
                        except: pass

                    if groups is None:
                        # Public group, hack structures to get it to validate
                        self.roles=None
                        auth=''

                if v is old_validation:
                    user=old_validation(groups, request, auth, self.roles)
                elif self.roles is UNSPECIFIED_ROLES: user=v(request, auth)
                else: user=v(request, auth, self.roles)

                while user is None and i < last_parent_index:
                    parent=parents[i]
                    i=i+1
                    if hasattr(parent, '__allow_groups__'):
                        groups=parent.__allow_groups__
                    else: continue
                    if hasattr(groups,'validate'): v=groups.validate
                    else: v=old_validation
                    if v is old_validation:
                        user=old_validation(groups, request, auth, self.roles)
                    elif self.roles is UNSPECIFIED_ROLES: user=v(request, auth)
                    else: user=v(request, auth, self.roles)

            if user is None and self.roles != UNSPECIFIED_ROLES:
                response.unauthorized()

        if user is not None:
            if validated_hook is not None: validated_hook(self, user)
            request['AUTHENTICATED_USER']=user
            request['AUTHENTICATION_PATH']='/'.join(steps[:-i])

        # Remove http request method from the URL.
        request['URL']=URL

        # Run post traversal hooks
        if post_traverse:
            result = exec_callables(post_traverse)
            if result is not None:
                object = result

        return object
 def test_view(self):
     view = Manage(self.site, TestRequest())
     self.assertTrue(IBrowserPublisher.providedBy(view))
Example #27
0
 def test_view(self):
     view = ContentsView(self.folder, TestRequest())
     self.failUnless(IBrowserPublisher.providedBy(view))
Example #28
0
 def test_view(self):
     view = Manage(self.site, TestRequest())
     self.assertTrue(IBrowserPublisher.providedBy(view))
 def test_view(self):
     view = ContentsView(self.folder, TestRequest())
     self.assertTrue(IBrowserPublisher.providedBy(view))
Example #30
0
    def traverse(self, path, response=None, validated_hook=None):
        """Traverse the object space

        The REQUEST must already have a PARENTS item with at least one
        object in it.  This is typically the root object.
        """
        request = self
        request_get = request.get
        if response is None:
            response = self.response

        # remember path for later use
        browser_path = path

        # Cleanup the path list
        if path[:1] == '/':
            path = path[1:]
        if path[-1:] == '/':
            path = path[:-1]
        clean = []
        for item in path.split('/'):
            # Make sure that certain things that dont make sense
            # cannot be traversed.
            if item in ('REQUEST', 'aq_self', 'aq_base'):
                return response.notFoundError(path)
            if not item or item == '.':
                continue
            elif item == '..':
                del clean[-1]
            else:
                clean.append(item)
        path = clean

        # How did this request come in? (HTTP GET, PUT, POST, etc.)
        method = request_get('REQUEST_METHOD', 'GET').upper()

        # Probably a browser
        no_acquire_flag = 0
        if (method in ('GET', 'POST', 'PURGE')
                and not is_xmlrpc_response(response)):
            # index_html is still the default method, only any object can
            # override it by implementing its own __browser_default__ method
            method = 'index_html'
        elif self.maybe_webdav_client:
            # Probably a WebDAV client.
            no_acquire_flag = 1

        URL = request['URL']
        parents = request['PARENTS']
        object = parents[-1]
        del parents[:]

        self.roles = getRoles(None, None, object, UNSPECIFIED_ROLES)

        # if the top object has a __bobo_traverse__ method, then use it
        # to possibly traverse to an alternate top-level object.
        if hasattr(object, '__bobo_traverse__'):
            try:
                new_object = object.__bobo_traverse__(request)
                if new_object is not None:
                    object = new_object
                    self.roles = getRoles(None, None, object,
                                          UNSPECIFIED_ROLES)
            except Exception:
                pass

        if not path and not method:
            return response.forbiddenError(self['URL'])

        # Traverse the URL to find the object:
        if hasattr(object, '__of__'):
            # Try to bind the top-level object to the request
            # This is how you get 'self.REQUEST'
            object = object.__of__(RequestContainer(REQUEST=request))
        parents.append(object)

        steps = self.steps
        self._steps = _steps = list(map(quote, steps))
        path.reverse()

        request['TraversalRequestNameStack'] = request.path = path
        request['ACTUAL_URL'] = request['URL'] + quote(browser_path)

        # Set the posttraverse for duration of the traversal here
        self._post_traverse = post_traverse = []

        # import time ordering problem
        if HAS_ZSERVER:
            from webdav.NullResource import NullResource
        else:
            NullResource = None

        entry_name = ''
        try:
            # We build parents in the wrong order, so we
            # need to make sure we reverse it when we're done.
            while 1:
                bpth = getattr(object, '__before_publishing_traverse__', None)
                if bpth is not None:
                    bpth(object, self)

                path = request.path = request['TraversalRequestNameStack']
                # Check for method:
                if path:
                    entry_name = path.pop()
                else:
                    # If we have reached the end of the path, we look to see
                    # if we can find IBrowserPublisher.browserDefault. If so,
                    # we call it to let the object tell us how to publish it.
                    # BrowserDefault returns the object to be published
                    # (usually self) and a sequence of names to traverse to
                    # find the method to be published.

                    # This is webdav support. The last object in the path
                    # should not be acquired. Instead, a NullResource should
                    # be given if it doesn't exist:
                    if (NullResource is not None and no_acquire_flag
                            and hasattr(object, 'aq_base')
                            and not hasattr(object, '__bobo_traverse__')):

                        if (object.__parent__
                                is not aq_inner(object).__parent__):
                            object = NullResource(parents[-2], object.getId(),
                                                  self).__of__(parents[-2])

                    if IBrowserPublisher.providedBy(object):
                        adapter = object
                    else:
                        adapter = queryMultiAdapter((object, self),
                                                    IBrowserPublisher)
                        if adapter is None:
                            # Zope2 doesn't set up its own adapters in a lot
                            # of cases so we will just use a default adapter.
                            adapter = DefaultPublishTraverse(object, self)

                    object, default_path = adapter.browserDefault(self)
                    if default_path:
                        request._hacked_path = 1
                        if len(default_path) > 1:
                            path = list(default_path)
                            method = path.pop()
                            request['TraversalRequestNameStack'] = path
                            continue
                        else:
                            entry_name = default_path[0]
                    elif (method and hasattr(object, method)
                          and entry_name != method
                          and getattr(object, method) is not None):
                        request._hacked_path = 1
                        entry_name = method
                        method = 'index_html'
                    else:
                        if hasattr(object, '__call__'):
                            self.roles = getRoles(object, '__call__',
                                                  object.__call__, self.roles)
                        if request._hacked_path:
                            i = URL.rfind('/')
                            if i > 0:
                                response.setBase(URL[:i])
                        break
                step = quote(entry_name)
                _steps.append(step)
                request['URL'] = URL = '%s/%s' % (request['URL'], step)

                try:
                    subobject = self.traverseName(object, entry_name)
                    if (hasattr(object, '__bobo_traverse__')
                            or hasattr(object, entry_name)):
                        check_name = entry_name
                    else:
                        check_name = None

                    self.roles = getRoles(object, check_name, subobject,
                                          self.roles)
                    object = subobject
                # traverseName() might raise ZTK's NotFound
                except (KeyError, AttributeError, ztkNotFound):
                    if response.debug_mode:
                        return response.debugError(
                            "Cannot locate object at: %s" % URL)
                    else:
                        return response.notFoundError(URL)
                except Forbidden as e:
                    if self.response.debug_mode:
                        return response.debugError(e.args)
                    else:
                        return response.forbiddenError(entry_name)

                parents.append(object)

                steps.append(entry_name)
        finally:
            parents.reverse()

        # Note - no_acquire_flag is necessary to support
        # things like DAV.  We have to make sure
        # that the target object is not acquired
        # if the request_method is other than GET
        # or POST. Otherwise, you could never use
        # PUT to add a new object named 'test' if
        # an object 'test' existed above it in the
        # heirarchy -- you'd always get the
        # existing object :(
        if (no_acquire_flag and hasattr(parents[1], 'aq_base')
                and not hasattr(parents[1], '__bobo_traverse__')):
            base = aq_base(parents[1])
            if not hasattr(base, entry_name):
                try:
                    if entry_name not in base:
                        raise AttributeError(entry_name)
                except TypeError:
                    raise AttributeError(entry_name)

        # After traversal post traversal hooks aren't available anymore
        del self._post_traverse

        request['PUBLISHED'] = parents.pop(0)

        # Do authorization checks
        user = groups = None
        i = 0

        if 1:  # Always perform authentication.

            last_parent_index = len(parents)
            if hasattr(object, '__allow_groups__'):
                groups = object.__allow_groups__
                inext = 0
            else:
                inext = None
                for i in range(last_parent_index):
                    if hasattr(parents[i], '__allow_groups__'):
                        groups = parents[i].__allow_groups__
                        inext = i + 1
                        break

            if inext is not None:
                i = inext

                if hasattr(groups, 'validate'):
                    v = groups.validate
                else:
                    v = old_validation

                auth = request._auth

                if v is old_validation and self.roles is UNSPECIFIED_ROLES:
                    # No roles, so if we have a named group, get roles from
                    # group keys
                    if hasattr(groups, 'keys'):
                        self.roles = list(groups.keys())
                    else:
                        try:
                            groups = groups()
                        except Exception:
                            pass
                        try:
                            self.roles = list(groups.keys())
                        except Exception:
                            pass

                    if groups is None:
                        # Public group, hack structures to get it to validate
                        self.roles = None
                        auth = ''

                if v is old_validation:
                    user = old_validation(groups, request, auth, self.roles)
                elif self.roles is UNSPECIFIED_ROLES:
                    user = v(request, auth)
                else:
                    user = v(request, auth, self.roles)

                while user is None and i < last_parent_index:
                    parent = parents[i]
                    i = i + 1
                    if hasattr(parent, '__allow_groups__'):
                        groups = parent.__allow_groups__
                    else:
                        continue
                    if hasattr(groups, 'validate'):
                        v = groups.validate
                    else:
                        v = old_validation
                    if v is old_validation:
                        user = old_validation(groups, request, auth,
                                              self.roles)
                    elif self.roles is UNSPECIFIED_ROLES:
                        user = v(request, auth)
                    else:
                        user = v(request, auth, self.roles)

            if user is None and self.roles != UNSPECIFIED_ROLES:
                response.unauthorized()

        if user is not None:
            if validated_hook is not None:
                validated_hook(self, user)
            request['AUTHENTICATED_USER'] = user
            request['AUTHENTICATION_PATH'] = '/'.join(steps[:-i])

        # Remove http request method from the URL.
        request['URL'] = URL

        # Run post traversal hooks
        if post_traverse:
            result = exec_callables(post_traverse)
            if result is not None:
                object = result

        return object
Example #31
0
 def test_view(self):
     view = ContentsView(self.folder, TestRequest())
     self.failUnless(IBrowserPublisher.providedBy(view))