예제 #1
0
    def __bobo_traverse__(self, REQUEST, name=None):
        if name is None:
            # Make this more explicit, otherwise getattr(self, name)
            # would raise a TypeError getattr(): attribute name must be string
            return None

        if name == 'Control_Panel':
            return APP_MANAGER.__of__(self)
        try:
            return getattr(self, name)
        except AttributeError:
            pass

        try:
            return self[name]
        except KeyError:
            pass

        method = REQUEST.get('REQUEST_METHOD', 'GET')
        if NullResource is not None and method not in ('GET', 'POST'):
            return NullResource(self, name, REQUEST).__of__(self)

        if method not in ('GET', 'POST'):
            return NullResource(self, name, REQUEST).__of__(self)

        # Waaa. unrestrictedTraverse calls us with a fake REQUEST.
        # There is probably a better fix for this.
        try:
            REQUEST.RESPONSE.notFoundError("%s\n%s" % (name, method))
        except AttributeError:
            raise KeyError(name)
 def index_html(self):
     """ Allow creation of .
     """
     if 'index_html' in self:
         return self._getOb('index_html')
     request = getattr(self, 'REQUEST', None)
     if request and 'REQUEST_METHOD' in request:
         if (request.maybe_webdav_client and
                 request['REQUEST_METHOD'] in ['PUT']):
             # Very likely a WebDAV client trying to create something
             nr = NullResource(self, 'index_html')
             nr.__replaceable__ = REPLACEABLE
             return nr
     return None
예제 #3
0
 def index_html(self):
     """ Allow creation of .
     """
     if 'index_html' in self:
         return self._getOb('index_html')
     request = getattr(self, 'REQUEST', None)
     if request and 'REQUEST_METHOD' in request:
         if (request.maybe_webdav_client
                 and request['REQUEST_METHOD'] in ['PUT']):
             # Very likely a WebDAV client trying to create something
             nr = NullResource(self, 'index_html')
             nr.__replaceable__ = REPLACEABLE
             return nr
     return None
예제 #4
0
    def publishTraverse(self, request, name):

        context = aq_inner(self.context)

        # If we are trying to traverse to the folder "body" pseudo-object
        # returned by listDAVObjects(), return that immediately

        if getattr(request, 'maybe_webdav_client', False) \
           and name == DAV_FOLDER_DATA_ID:
            return FolderDataResource(DAV_FOLDER_DATA_ID,
                                      context).__of__(context)

        defaultTraversal = super(DexterityPublishTraverse,
                                 self).publishTraverse(request, name)

        # If this is a WebDAV PUT/PROPFIND/PROPPATCH request, don't acquire
        # things. If we did, we couldn't create a new object with PUT, for
        # example, because the acquired object would shadow the NullResource

        if getattr(request, 'maybe_webdav_client', False) \
           and request.get('REQUEST_METHOD', 'GET') not in ('GET', 'POST',) \
           and IAcquirer.providedBy(defaultTraversal):
            parent = aq_parent(aq_inner(defaultTraversal))
            if parent is not None and parent is not context:
                return NullResource(self.context, name,
                                    request).__of__(self.context)

        return defaultTraversal
예제 #5
0
    def __bobo_traverse__(self, request, name):
        """
    If no subobject is found through Folder API
    then try to lookup the object by invoking _getExtensibleContent
    """
        # Normal traversal
        try:
            return getattr(self, name)
        except AttributeError:
            pass

        try:
            return self[name]
        except KeyError:
            pass

        document = self.getExtensibleContent(request, name)
        if document is not None:
            return aq_base(document).__of__(self)

        # Not found section
        method = request.get('REQUEST_METHOD', 'GET')
        if not method in ('GET', 'POST'):
            return NullResource(self, name, request).__of__(self)
        # Waaa. unrestrictedTraverse calls us with a fake REQUEST.
        # There is proabably a better fix for this.
        try:
            request.RESPONSE.notFoundError("%s\n%s" % (name, method))
        except AttributeError:
            raise KeyError(name)
예제 #6
0
 def __getitem__(self, key):
     if key in self:
         return self._getOb(key, None)
     request = getattr(self, 'REQUEST', None)
     if not isinstance(request, (str, NoneType)):
         method = request.get('REQUEST_METHOD', 'GET')
         if (request.maybe_webdav_client and method not in ('GET', 'POST')):
             return NullResource(self, key, request).__of__(self)
     raise KeyError, key
예제 #7
0
 def __getitem__(self, key):
     v=self._getOb(key, None)
     if v is not None: return v
     if hasattr(self, 'REQUEST'):
         request=self.REQUEST
         method=request.get('REQUEST_METHOD', 'GET')
         if request.maybe_webdav_client and not method in ('GET', 'POST'):
             return NullResource(self, key, request).__of__(self)
     raise KeyError, key
예제 #8
0
 def __getitem__(self, key):
     if key in self:
         return self._getOb(key, None)
     request = getattr(self, 'REQUEST', None)
     if not (isinstance(request, str) or request is None):
         method = request.get('REQUEST_METHOD', 'GET')
         if (request.maybe_webdav_client and method not in ('GET', 'POST')):
             if bbb.HAS_ZSERVER:
                 from webdav.NullResource import NullResource
                 return NullResource(self, key, request).__of__(self)
     raise KeyError(key)
예제 #9
0
    def __getitem__(self, key):
        value = self._getOb(key, None)
        if value is not None:
            return value

        # WebDAV PUT support
        if hasattr(self, 'REQUEST'):
            request = self.REQUEST
            method = request.get('REQUEST_METHOD', 'GET')
            if (getattr(request, 'maybe_webdav_client', False)
                    and method not in ('GET', 'POST')):
                return NullResource(self, key, request).__of__(self)
        raise KeyError(key)
예제 #10
0
    def __call__(self):
        context = self.context
        request = self.request
        response = request.response

        content_type = request.getHeader('content-type').strip(';')
        prefix = self._getPrefix(content_type)
        name = context.generateUniqueId(prefix)

        nullresouce = NullResource(context, name, request)
        nullresouce.__of__(context)
        nullresouce.PUT(request, response)

        # fix the request headers to get the correct metadata mappings
        request = self._updateRequest(request, content_type)

        # Look it up and finish up, then return it.
        obj = context._getOb(name)
        obj.PUT(request, response)
        obj.setTitle(request['Title'])
        obj.reindexObject(idxs='Title')
        return obj
예제 #11
0
 def index_html(self, REQUEST=None, RESPONSE=None):
     """ Special case index_html """
     if 'index_html' in self:
         return self._getOb('index_html')
     request = REQUEST
     if request is None:
         request = getattr(self, 'REQUEST', None)
     if request and 'REQUEST_METHOD' in request:
         if request.maybe_webdav_client:
             method = request['REQUEST_METHOD']
             if method == 'PUT':
                 # Very likely a WebDAV client trying to create something
                 nr = NullResource(self, 'index_html')
                 nr.__replaceable__ = REPLACEABLE
                 return nr
             elif method in ('GET', 'HEAD', 'POST'):
                 # Do nothing, let it go and acquire.
                 pass
             else:
                 raise AttributeError('index_html')
     # Acquire from parent
     parent = aq_parent(aq_inner(self))
     target = parent.aq_acquire('index_html')
     return ReplaceableWrapper(target).__of__(parent).__of__(self)
예제 #12
0
    def __bobo_traverse__(self, REQUEST, name):
        # Allows transparent access to session subobjects.
        #
        # Sometimes, the request doesn't have a response, e.g. when
        # PageTemplates traverse through the object path, they pass in
        # a phony request (a dict).
        RESPONSE = getattr(REQUEST, 'RESPONSE', None)

        # Is it a registered sub object
        data = self.getSubObject(name, REQUEST, RESPONSE)
        if data is not None:
            return data
        # Or a standard attribute (maybe acquired...)
        target = None
        method = REQUEST.get('REQUEST_METHOD', 'GET').upper()
        # Logic from "ZPublisher.BaseRequest.BaseRequest.traverse"
        # to check whether this is a browser request
        if (len(REQUEST.get('TraversalRequestNameStack', ())) == 0 and
            not (method in ('GET', 'HEAD', 'POST') and not
                 isinstance(RESPONSE, xmlrpc.Response))):
            if shasattr(self, name):
                target = getattr(self, name)
        else:
            if shasattr(self, name):  # attributes of self come first
                target = getattr(self, name)
            else:  # then views
                gsm = getSiteManager()
                factory = gsm.adapters.lookup(
                    (providedBy(self), providedBy(REQUEST)), Interface, name
                )
                if factory is not None:
                    # We don't return the view, we raise an
                    # AttributeError instead (below)
                    target = None
                else:  # then acquired attributes
                    target = getattr(self, name, None)

        if target is not None:
            return target
        elif (method not in ('GET', 'POST') and not
              isinstance(RESPONSE, xmlrpc.Response) and
              REQUEST.maybe_webdav_client):
            return NullResource(self, name, REQUEST).__of__(self)
        else:
            # Raising AttributeError will look up views for us
            raise AttributeError(name)
 def index_html(self):
     """Acquire if not present."""
     request = getattr(self, 'REQUEST', None)
     if request and 'REQUEST_METHOD' in request:
         if request.maybe_webdav_client:
             method = request['REQUEST_METHOD']
             if bbb.HAS_ZSERVER and method in ('PUT', ):
                 # Very likely a WebDAV client trying to create something
                 return ReplaceableWrapper(NullResource(self, 'index_html'))
             elif method in ('GET', 'HEAD', 'POST'):
                 # Do nothing, let it go and acquire.
                 pass
             else:
                 raise AttributeError('index_html')
     # Acquire from parent
     _target = aq_parent(aq_inner(self)).aq_acquire('index_html')
     return ReplaceableWrapper(aq_base(_target).__of__(self))
예제 #14
0
 def index_html(self):
     """ Acquire if not present. """
     request = getattr(self, 'REQUEST', None)
     if (request is not None and 'REQUEST_METHOD' in request
             and request.maybe_webdav_client):
         method = request['REQUEST_METHOD']
         if bbb.HAS_ZSERVER and method in ('PUT', ):
             # Very likely a WebDAV client trying to create something
             result = NullResource(self, 'index_html')
             setattr(result, '__replaceable__', REPLACEABLE)
             return result
         elif method not in ('GET', 'HEAD', 'POST'):
             raise AttributeError('index_html')
     # Acquire from skin.
     _target = self.__getattr__('index_html')
     result = aq_base(_target).__of__(self)
     setattr(result, '__replaceable__', REPLACEABLE)
     return result
예제 #15
0
 def index_html(self, REQUEST=None, RESPONSE=None):
     """Special case index_html"""
     request = REQUEST
     if request is None:
         request = getattr(self, 'REQUEST', None)
     if request and request.has_key('REQUEST_METHOD'):
         if request.maybe_webdav_client:
             method = request['REQUEST_METHOD']
             if method in ('PUT', ):
                 # Very likely a WebDAV client trying to create something
                 return ReplaceableWrapper(NullResource(self, 'index_html'))
             elif method in ('GET', 'HEAD', 'POST'):
                 # Do nothing, let it go and acquire.
                 pass
             else:
                 raise AttributeError, 'index_html'
     # Acquire from parent
     _target = aq_parent(aq_inner(self)).aq_acquire('index_html')
     return ReplaceableWrapper(aq_base(_target).__of__(self))
예제 #16
0
    def __bobo_traverse__(self, REQUEST, name=None):

        try:
            return getattr(self, name)
        except AttributeError:
            pass
        try:
            return self[name]
        except KeyError:
            pass
        method = REQUEST.get('REQUEST_METHOD', 'GET')
        if not method in ('GET', 'POST'):
            return NullResource(self, name, REQUEST).__of__(self)

        # Waaa. unrestrictedTraverse calls us with a fake REQUEST.
        # There is proabably a better fix for this.
        try:
            REQUEST.RESPONSE.notFoundError("%s\n%s" % (name, method))
        except AttributeError:
            raise KeyError, name
예제 #17
0
  def _getStaticDocument(self, request, name):
    try:
      return self[name]
    except KeyError:
      pass
    document = self.getExtensibleContent(request, name)
    if document is not None:
      return aq_base(document).__of__(self)

    try:
      return getattr(self, name)
    except AttributeError:
      pass

    # Not found section
    method = request.get('REQUEST_METHOD', 'GET')
    if not method in ('GET', 'POST'):
      return NullResource(self, name, request).__of__(self)
    # Waaa. unrestrictedTraverse calls us with a fake REQUEST.
    # There is proabably a better fix for this.
    try:
      request.RESPONSE.notFoundError("%s\n%s" % (name, method))
    except AttributeError:
      raise KeyError, name
예제 #18
0
def __bobo_traverse__(self, REQUEST, name):
    """Allows transparent access to session subobjects.
    """
    # sometimes, the request doesn't have a response, e.g. when
    # PageTemplates traverse through the object path, they pass in
    # a phony request (a dict).

    RESPONSE = getattr(REQUEST, 'RESPONSE', None)

    # Is it a registered sub object
    data = self.getSubObject(name, REQUEST, RESPONSE)
    if data is not None:
        return data
    # Or a standard attribute (maybe acquired...)
    target = None
    method = REQUEST.get('REQUEST_METHOD', 'GET').upper()
    # Logic from "ZPublisher.BaseRequest.BaseRequest.traverse"
    # to check whether this is a browser request
    if (len(REQUEST.get('TraversalRequestNameStack', ())) == 0 and  # NOQA
            not (method in ('GET', 'HEAD', 'POST')
                 and not isinstance(RESPONSE, xmlrpc.Response))):
        if shasattr(self, name):
            target = getattr(self, name)
    else:
        if shasattr(self, name):  # attributes of self come first
            target = getattr(self, name)
        else:  # then views
            target = queryMultiAdapter((self, REQUEST), Interface, name)
            if target is not None:
                # We don't return the view, we raise an
                # AttributeError instead (below)
                target = None
            else:  # then acquired attributes
                target = getattr(self, name, None)
                if target is not None:
                    logger.debug(
                        'traverse without explicit acquisition '
                        'object=%r name=%r subobject=%r url=%r referer=%r',
                        self, name, target, REQUEST.get('ACTUAL_URL'),
                        REQUEST.get('HTTP_REFERER', '-'))
                    #
                    # STOP TRAVERSING WITHOUT EXPLICIT ACQUISITION
                    #
                    if REQUEST.get('ACTUAL_URL') and (
                            IContentish.providedBy(target) or  # NOQA
                            IPloneSiteRoot.providedBy(target)):
                        logger.warning(
                            'traverse without explicit acquisition '
                            'object=%r name=%r subobject=%r url=%r referer=%r',
                            self, name, target, REQUEST.get('ACTUAL_URL'),
                            REQUEST.get('HTTP_REFERER', '-'))
                        if not config.DRYRUN:
                            target = None

    if target is not None:
        return target
    elif (method not in ('GET', 'POST')
          and not isinstance(RESPONSE, xmlrpc.Response) and  # NOQA
          REQUEST.maybe_webdav_client):
        return NullResource(self, name, REQUEST).__of__(self)
    else:
        # Raising AttributeError will look up views for us
        raise AttributeError(name)
예제 #19
0
 def testPUT_factoryAddsImageNoTraverse(self):
     request = self.app.REQUEST
     new = NullResource(self.folder, 'image', request).__of__(self.folder)
     new.PUT(request, request.RESPONSE)
     self.failUnless(hasattr(aq_base(self.folder), 'image'))
     self.failUnless(self._exists('image.gif.tmp'))
예제 #20
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
예제 #21
0
파일: BaseRequest.py 프로젝트: wlang42/Zope
    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