def index_html(self): """ download the image """ # validate access fieldname = getattr(self.data, 'fieldname', getattr(self, 'fieldname', None)) guarded_getattr(self.context, fieldname) set_headers(self.data, self.request.response) return stream_data(self.data)
def validate_access(self): if IOrganisation.providedBy(self.context): return True fieldname = getattr(self.data, 'fieldname', getattr(self, 'fieldname', None)) guarded_getattr(self.context, fieldname)
def test_access_to_private_content_not_allowed_via_rich_text(self): try: from plone.app.textfield.value import RichTextValue except ImportError: return from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate foobar = create_private_document(self.portal, 'foobar') login(self.portal, TEST_USER_NAME) foobar.text = RichTextValue(u'Secret.', 'text/plain', 'text/html') self.assertEqual( self.portal.portal_workflow.getInfoFor(foobar, 'review_state'), 'private') # Check that guarded_getattr is happy for the current user. self.assertEqual(guarded_getattr(self.portal, 'foobar'), foobar) self.assertEqual( guarded_getattr(self.portal.foobar, 'text'), foobar.text) # Access to text.output may be more restricted than access to the # text object itself, but this makes no sense, so we switch that # off in this test. # self.assertRaises( # Unauthorized, guarded_getattr, self.portal.foobar.text, 'output') self.portal.foobar.text.__allow_access_to_unprotected_subobjects__ = 1 self.assertEqual( guarded_getattr(self.portal.foobar.text, 'output'), '<p>Secret.</p>') TEMPLATE = '<p tal:content="structure python:%s" />' pt = ZopePageTemplate( 'mytemplate', TEMPLATE % "'access {0.foobar.text.output}'.format(context)") hack_pt(pt, context=self.portal) self.assertEqual(pt.pt_render(), '<p>access <p>Secret.</p></p>') # Check the same for anonymous. logout() self.assertRaises( Unauthorized, guarded_getattr, self.portal, 'foobar') self.assertRaises( Unauthorized, guarded_getattr, self.portal.foobar, 'text') # *If* somehow anonymous can access the text, then we have allowed # access to the output as well. self.assertEqual( guarded_getattr(self.portal.foobar.text, 'output'), '<p>Secret.</p>') # But for the template anonymous would need access to everything, # which rightly fails. self.assertRaises(Unauthorized, pt.pt_render) # Test the simpler access without str.format for the current user. login(self.portal, TEST_USER_NAME) pt = ZopePageTemplate( 'mytemplate', TEMPLATE % "context.foobar.text.output") hack_pt(pt, context=self.portal) self.assertEqual(pt.pt_render(), '<p><p>Secret.</p></p>') # and for anonymous logout() self.assertRaises(Unauthorized, pt.pt_render)
def _construct(self, context, id): """Creates and returns the named folder.""" dispatcher = guarded_getattr(context, 'manage_addProduct')['OFSP'] factory = guarded_getattr(dispatcher, 'manage_addFolder') factory(id) o = context.restrictedTraverse(id) # Commit a subtransaction to assign the new object to # the correct database. transaction.commit(1) return o
def __getattr__(self, name, default=None): # Make *extra* sure that the wrapper isn't used to access # __call__, etc. if name.startswith('__'): self.__you_lose() return guarded_getattr(self._wrapped, name, default)
def __getattr__(self, name, default=None): # Make *extra* sure that the wrapper isn't used to access # __call__, etc. if name.startswith("__"): self.__you_lose() return guarded_getattr(self._wrapped, name, default)
def test_editWithoutModifyPortalContent(self): edit = guarded_getattr(self.folder, 'edit') original_permission_list = self.folder.permission_settings('Modify portal content') assert len(original_permission_list) == 1 self.folder.manage_permission('Modify portal content', [], 0) self.assertRaises(Unauthorized, guarded_getattr, self.folder, 'edit') # Reset to original permissions self.folder.manage_permission('Modify portal content', original_permission_list[0]['roles'], original_permission_list[0]['acquire'])
def getUI(self, ui=None): """Returns a UI object. """ if not ui: ui = self.default_ui tool = aq_get(self, "composite_tool", None, 1) if tool is None: raise CompositeError("No composite_tool found") return guarded_getattr(tool.uis, ui)
def test_values_validates(self): sm = SecurityManager() old = self.setSecurityManager(sm) values = guarded_getattr({GuardTestCase: 1}, 'values') try: next(values()) finally: self.setSecurityManager(old) self.assertTrue(sm.calls)
def test_attr_handler_table(self): d = {} _dict = type(d) old = ContainerAssertions.get(_dict) mytable = {'keys': 1, 'values': Method, } ContainerAssertions[_dict] = mytable try: guarded_getattr(d, 'keys') self.assertEqual(len(self.__sm.calls), 0) values = guarded_getattr(d, 'values') self.assertEqual(values.__class__, Method) self.assertEqual(values.args, (d, 'values')) self.assertRaises(Unauthorized, guarded_getattr, d, 'items') finally: ContainerAssertions[_dict] = old
def test_editWithoutModifyPortalContent(self): edit = guarded_getattr(self.folder, "edit") original_permission_list = self.folder.permission_settings("Modify portal content") assert len(original_permission_list) == 1 self.folder.manage_permission("Modify portal content", [], 0) self.assertRaises(Unauthorized, guarded_getattr, self.folder, "edit") # Reset to original permissions self.folder.manage_permission( "Modify portal content", original_permission_list[0]["roles"], original_permission_list[0]["acquire"] )
def test_attr_handler_table(self): from AccessControl import Unauthorized from AccessControl.ZopeGuards import guarded_getattr from AccessControl.SimpleObjectPolicies import ContainerAssertions d = {} _dict = type(d) old = ContainerAssertions.get(_dict) mytable = {"keys": 1, "values": Method} ContainerAssertions[_dict] = mytable try: guarded_getattr(d, "keys") self.assertEqual(len(self.__sm.calls), 0) values = guarded_getattr(d, "values") self.assertEqual(values.__class__, Method) self.assertEqual(values.args, (d, "values")) self.assertRaises(Unauthorized, guarded_getattr, d, "items") finally: ContainerAssertions[_dict] = old
def render(self, field, key, value, REQUEST, render_prefix=None): """ """ form = getattr(field, 'aq_parent', None) if form is not None: obj = getattr(form, 'aq_parent', None) else: obj = None if obj is not None: report_method = guarded_getattr(obj, field['report_method']) if callable(report_method): return report_method()
def _getFile(self): if not self.fieldname: info = IPrimaryFieldInfo(self.context, None) if info is None: # Ensure that we have at least a fieldname raise NotFound(self, '', self.request) self.fieldname = info.fieldname # respect field level security as defined in plone.autoform # check if attribute access would be allowed! guarded_getattr(self.context, self.fieldname, None) file = info.value else: context = getattr(self.context, 'aq_explicit', self.context) file = guarded_getattr(context, self.fieldname, None) if file is None: raise NotFound(self, self.fieldname, self.request) return file
def test_attr_handler_table(self): from AccessControl import Unauthorized from AccessControl.ZopeGuards import guarded_getattr from AccessControl.SimpleObjectPolicies import ContainerAssertions d = {} _dict = type(d) old = ContainerAssertions.get(_dict) mytable = {'keys': 1, 'values': Method, } ContainerAssertions[_dict] = mytable try: guarded_getattr(d, 'keys') self.assertEqual(len(self.__sm.calls), 0) values = guarded_getattr(d, 'values') self.assertEqual(values.__class__, Method) self.assertEqual(values.args, (d, 'values')) self.assertRaises(Unauthorized, guarded_getattr, d, 'items') finally: ContainerAssertions[_dict] = old
def _testSetPasswordSecurity(self, login): login.manage_permission(Permissions.SetOwnPassword, [], 0) with self.assertRaises(Unauthorized): guarded_getattr(login, 'setPassword')('secret') with self.assertRaises(Unauthorized): guarded_getattr(login, 'edit')(password='******') # edit(password=None) has no effect. It's a special case, because in the user interface # we show an empty field for password. login.edit(password=None) self.assertFalse(login.getPassword()) # Make sure that edit method cannot call __setPasswordByForce and nothing # changes. login.edit(password_by_force='waaa') self.assertFalse(login.getPassword()) login.manage_permission(Permissions.SetOwnPassword, ['Anonymous'], 0) login.setPassword('secret') password = login.getPassword() self.assertTrue(password) login.edit(password=None) self.assertEqual(login.getPassword(), password)
def getTemplateChangeInfo(self, paths): """Returns information for changing the template applied to objects. """ root = self.getPhysicalRoot() tool = aq_parent(aq_inner(self)) obs = [] all_choices = None # {template -> 1} current = None for path in str(paths).split(':'): ob = root.unrestrictedTraverse(path) obs.append(ob) if not ICompositeElement.providedBy(ob): raise ValueError("Not a composite element: %s" % path) m = guarded_getattr(ob, "queryInlineTemplate") template = m() if current is None: current = template elif current and current != template: # The current template isn't the same for all of the elements, # so there is no common current template. Spell this condition # using a non-string value. current = 0 m = guarded_getattr(ob, "listAllowableInlineTemplates") templates = m() d = {} for name, template in templates: d[name] = template if all_choices is None: all_choices = d else: for template in all_choices.keys(): if not d.has_key(template): del all_choices[template] return { "obs": obs, "templates": all_choices, "current_template": current, }
def __getattr__(self, name, default=None): # Make *extra* sure that the wrapper isn't used to access # __call__, etc. if name.startswith('__'): # Acquisition will nowadays try to do an getattr on all # objects which aren't Acquisition wrappers, asking for a # __parent__ pointer. We don't want to raise Unauthorized # in this case but simply an AttributeError. if name in ('__parent__', '__name__'): raise AttributeError(name) self.__you_lose() return guarded_getattr(self._wrapped, name, default)
def test_01_checkAnonymousProcessing(self): """ Test whether a timer can be invoked by anonymous. """ noSecurityManager() timer_service = self.app.Control_Panel.timer_service process_timer = guarded_getattr(timer_service, 'process_timer') try: guarded_apply(process_timer, (0, )) except Unauthorized: self.fail('calling process_timer is unauthorized') except: # Do not care about any exception but unauthorized. pass
def test_01_checkAnonymousProcessing(self): """ Test whether a timer can be invoked by anonymous. """ noSecurityManager() timer_service = self.app.Control_Panel.timer_service process_timer = guarded_getattr(timer_service, 'process_timer') try: guarded_apply(process_timer, (0,)) except Unauthorized: self.fail('calling process_timer is unauthorized') except: # Do not care about any exception but unauthorized. pass
def showSlot(self, path, RESPONSE): """Redirects to (and possibly creates) the workspace for a slot. """ from composite import Composite obj = self.getPhysicalRoot() parts = str(path).split('/') for name in parts: obj = obj.restrictedTraverse(name) if IComposite.providedBy(obj): gen = guarded_getattr(obj, "generateSlots") gen() RESPONSE.redirect("%s/%s" % ( obj.absolute_url(), self.workspace_view_name))
def get_field(self, field_name, args, kwargs): """Get the field value using guarded methods.""" first, rest = formatter_field_name_split(field_name) obj = self.get_value(first, args, kwargs) # loop through the rest of the field_name, doing # getattr or getitem as needed for is_attr, i in rest: if is_attr: obj = guarded_getattr(obj, i) else: obj = guarded_getitem(obj, i) return obj, first
def _getNodeList(self, context): """Returns the list of possible nodes """ node_select_method_id = self.getProperty('node_select_method_id') if node_select_method_id: return guarded_getattr(context, node_select_method_id)() # no script defined, used the explicitly selected values node_list = self.getAggregateValueList() portal_categories = self.getPortalObject().portal_categories if self.getProperty('include_virtual_none_node'): node_list.append(portal_categories.budget_special_node.none) if self.getProperty('include_virtual_other_node'): node_list.append(portal_categories.budget_special_node.all_other) return node_list
def test_simple_object_policies(self): ''' Test that we are able to access attributes of simple types (here: unicode and bytes) ''' from AccessControl.ZopeGuards import guarded_getattr orig_value = self.__sm.reject self.__sm.reject = True try: items = [b'a ', u'a '] for item in items: self.assertEqual(guarded_getattr(item, 'strip')(), item.strip()) finally: self.__sm.reject = orig_value self.assertEqual(len(self.__sm.calls), 0)
def changeTemplate(self, paths, template, reload=0, close=1, REQUEST=None): """Changes the template for objects. """ info = self.getTemplateChangeInfo(paths) if template not in info["templates"]: raise KeyError("Template %s is not among the choices" % template) tool = aq_parent(aq_inner(self)) for ob in info["obs"]: assert ICompositeElement.providedBy(ob) m = guarded_getattr(ob, "setInlineTemplate") m(template) if REQUEST is not None: if reload: REQUEST["RESPONSE"].redirect(REQUEST["HTTP_REFERER"]) elif close: return close_dialog_html
def _getFile(self): if not self.fieldname: info = IPrimaryFieldInfo(self.context, None) if info is None: # Ensure that we have at least a filedname raise NotFound(self, '', self.request) self.fieldname = info.fieldname file = info.value else: context = getattr(self.context, 'aq_explicit', self.context) file = guarded_getattr(context, self.fieldname, None) if file is None: raise NotFound(self, self.fieldname, self.request) return file
def showSlot(self, path, RESPONSE): """Redirects to (and possibly creates) the workspace for a slot. """ from composite import Composite obj = self.getPhysicalRoot() parts = path.split('/') for name in parts: obj = obj.restrictedTraverse(name) try: is_comp = isinstance(obj, Composite) except TypeError: is_comp = 0 # Python 2.1 bug if is_comp: gen = guarded_getattr(obj, "generateSlots") gen() RESPONSE.redirect(obj.absolute_url() + "/manage_workspace")
def get_field(self, field_name, args, kwargs): """ Here we're overridding so we can use guarded_getattr instead of regular getattr """ first, rest = field_name._formatter_field_name_split() obj = self.get_value(first, args, kwargs) # loop through the rest of the field_name, doing # getattr or getitem as needed for is_attr, i in rest: if is_attr: obj = guarded_getattr(obj, i) else: obj = obj[i] return obj, first
def processForm(self, form): """ Process an XForms submission. """ submit = form.get('__submit__') if not submit: # return an empty string as the 'message', since we haven't actually # processed anything return (form, '', False) model, submission = submit.split('+') if not (model and submission): return (form, 'No model and/or submission specified', True) messages = [] # validate the form content_container = getattr(self.aq_explicit, self.content_container) for key in form.keys(): for obj in (content_container.get_filteredDataDefinition() + content_container.security_management): if (getattr(obj, 'indexName', '') == key or getattr(obj, 'id', '') == key): val, message = obj.validate(self, form.get(key)) if message: messages.append(message) else: form[key] = val if messages: message = '' for msg in messages: message += '<p>%s</p>' % msg return (form, message, True) # look for a callback method for processing this form if guarded_hasattr(self.aq_explicit, 'cb_'+str(model)): process_cb = guarded_getattr(self.aq_explicit, 'cb_'+str(model)) # the form has been processed, we don't need to do anything else form['__populate__'] = False return process_cb(form) return (form, 'No matching model found', True)
def processForm(self, form): """ Process an XForms submission. """ submit = form.get('__submit__') if not submit: # return an empty string as the 'message', since we haven't actually # processed anything return (form, '', False) model, submission = submit.split('+') if not (model and submission): return (form, 'No model and/or submission specified', True) messages = [] # validate the form content_container = getattr(self.aq_explicit, self.content_container) for key in form.keys(): for obj in (content_container.get_filteredDataDefinition() + content_container.security_management): if (getattr(obj, 'indexName', '') == key or getattr(obj, 'id', '') == key): val, message = obj.validate(self, form.get(key)) if message: messages.append(message) else: form[key] = val if messages: message = '' for msg in messages: message += '<p>%s</p>' % msg return (form, message, True) # look for a callback method for processing this form if guarded_hasattr(self.aq_explicit, 'cb_' + str(model)): process_cb = guarded_getattr(self.aq_explicit, 'cb_' + str(model)) # the form has been processed, we don't need to do anything else form['__populate__'] = False return process_cb(form) return (form, 'No matching model found', True)
def design(self, transformer="common"): """Renders the composite with editing features. """ tool = aq_get(self, "composite_tool", None, 1) if tool is None: raise CompositeError("No composite_tool found") # Never cache a design view. req = getattr(self, "REQUEST", None) if req is not None: req["RESPONSE"].setHeader("Cache-Control", "no-cache") self._v_editing = 1 try: text = self() finally: self._v_editing = 0 tf = guarded_getattr(tool.transformers, transformer) return tf.transform(self, text)
def guarded_next(iterator, default=_marker): """next(iterator[, default]) Return the next item from the iterator. If default is given and the iterator is exhausted, it is returned instead of raising StopIteration. """ try: iternext = guarded_getattr(iterator, "next").__call__ # this way an AttributeError while executing next() isn't hidden # (2.6 does this too) except AttributeError: raise TypeError("%s object is not an iterator" % type(iterator).__name__) try: return iternext() except StopIteration: if default is _marker: raise return default
def guarded_next(iterator, default=_marker): """next(iterator[, default]) Return the next item from the iterator. If default is given and the iterator is exhausted, it is returned instead of raising StopIteration. """ try: iternext = guarded_getattr(iterator, 'next').__call__ # this way an AttributeError while executing next() isn't hidden # (2.6 does this too) except AttributeError: raise TypeError("%s object is not an iterator" % type(iterator).__name__) try: return iternext() except StopIteration: if default is _marker: raise return default
def _substituteTextContent(self, text, safe_substitute=True, **kw): # If a method for string substitutions of the text content, perform it. # Decode everything into unicode before the substitutions, in order to # avoid encoding errors. method_id = self.getTextContentSubstitutionMappingMethodId() if method_id: try: method = guarded_getattr(self, method_id) except AttributeError: LOG( 'TextDocument', WARNING, 'could not get the substitution' ' mapping method %s from %r, so the content will not be' ' substituted.' % (method_id, self.getRelativeUrl())) return text mapping = method(**kw) is_str = isinstance(text, str) if is_str: text = text.decode('utf-8') class UnicodeMapping: def __getitem__(self, item): v = mapping[item] if isinstance(v, str): v = v.decode('utf-8') elif not isinstance(v, unicode): v = str(v).decode('utf-8') return v unicode_mapping = UnicodeMapping() if safe_substitute: text = Template(text).safe_substitute(unicode_mapping) else: text = Template(text).substitute(unicode_mapping) # If the original was a str, convert it back to str. if is_str: text = text.encode('utf-8') return text
def test_authenticatedContentType(self): """See https://dev.plone.org/archetypes/ticket/712 content_type should not be protected by a security declaration, as it is usually an attribute. If a security declaration *is* set (in BaseObject or one of it's base classes) non-anonymous access from protected code (guarded_getattr) will fail. """ from AccessControl.unauthorized import Unauthorized from AccessControl.Permissions import view from AccessControl.ZopeGuards import guarded_getattr dummy = self._dummy dummy.manage_permission(view, ('Manager',), False) # dummy.content_type in a Python Script self.assertRaises(Unauthorized, guarded_getattr, dummy, 'content_type') self.setRoles(('Manager',)) # dummy.content_type in a Python Script self.assertEqual(guarded_getattr(dummy, 'content_type'), 'text/html')
def deleteElements(self, source_paths): sources = [] for p in source_paths: if hasattr(p, "split"): p = p.split('/') if p: sources.append(p) # Replace with nulls to avoid changing indexes while deleting. orig_slots = {} try: for source in sources: slot = self.restrictedTraverse(source[:-1]) assert ISlot.providedBy(slot), repr(slot) slot_id = id(aq_base(slot)) if not orig_slots.has_key(slot_id): orig_slots[slot_id] = slot nullify = guarded_getattr(slot, "nullify") # Check security nullify(source[-1]) finally: # Clear the nulls just added. for slot in orig_slots.values(): slot.pack()
def _substituteTextContent(self, text, safe_substitute=True, **kw): # If a method for string substitutions of the text content, perform it. # Decode everything into unicode before the substitutions, in order to # avoid encoding errors. method_id = self.getTextContentSubstitutionMappingMethodId() if method_id: try: method = guarded_getattr(self, method_id) except AttributeError: LOG('TextDocument', WARNING, 'could not get the substitution' ' mapping method %s from %r, so the content will not be' ' substituted.' % (method_id, self.getRelativeUrl())) return text mapping = method(**kw) is_str = isinstance(text, str) if is_str: text = text.decode('utf-8') unicode_mapping = {} for k, v in mapping.iteritems(): if isinstance(v, str): v = v.decode('utf-8') elif not isinstance(v, unicode): v = str(v).decode('utf-8') unicode_mapping[k] = v if safe_substitute: text = Template(text).safe_substitute(unicode_mapping) else: text = Template(text).substitute(unicode_mapping) # If the original was a str, convert it back to str. if is_str: text = text.encode('utf-8') return text
def unrestrictedTraverse(self, path, default=_marker, restricted=False): """Lookup an object by path. path -- The path to the object. May be a sequence of strings or a slash separated string. If the path begins with an empty path element (i.e., an empty string or a slash) then the lookup is performed from the application root. Otherwise, the lookup is relative to self. Two dots (..) as a path element indicates an upward traversal to the acquisition parent. default -- If provided, this is the value returned if the path cannot be traversed for any reason (i.e., no object exists at that path or the object is inaccessible). restricted -- If false (default) then no security checking is performed. If true, then all of the objects along the path are validated with the security machinery. Usually invoked using restrictedTraverse(). """ if not path: return self if isinstance(path, str): # Unicode paths are not allowed path = path.split('/') else: path = list(path) REQUEST = {'TraversalRequestNameStack': path} path.reverse() path_pop = path.pop if len(path) > 1 and not path[0]: # Remove trailing slash path_pop(0) if restricted: validate = getSecurityManager().validate if not path[-1]: # If the path starts with an empty string, go to the root first. path_pop() obj = self.getPhysicalRoot() if restricted: validate(None, None, None, obj) # may raise Unauthorized else: obj = self # import time ordering problem from webdav.NullResource import NullResource resource = _marker try: while path: name = path_pop() __traceback_info__ = path, name if name[0] == '_': # Never allowed in a URL. raise NotFound, name if name == '..': next = aq_parent(obj) if next is not None: if restricted and not validate(obj, obj, name, next): raise Unauthorized(name) obj = next continue bobo_traverse = getattr(obj, '__bobo_traverse__', None) try: if name and name[:1] in '@+' and name != '+' and nsParse(name)[1]: # Process URI segment parameters. ns, nm = nsParse(name) try: next = namespaceLookup( ns, nm, obj, aq_acquire(self, 'REQUEST')) if IAcquirer.providedBy(next): next = next.__of__(obj) if restricted and not validate( obj, obj, name, next): raise Unauthorized(name) except LocationError: raise AttributeError(name) else: next = UseTraversalDefault # indicator try: if bobo_traverse is not None: next = bobo_traverse(REQUEST, name) if restricted: if aq_base(next) is not next: # The object is wrapped, so the acquisition # context is the container. container = aq_parent(aq_inner(next)) elif getattr(next, 'im_self', None) is not None: # Bound method, the bound instance # is the container container = next.im_self elif getattr(aq_base(obj), name, _marker) is next: # Unwrapped direct attribute of the object so # object is the container container = obj else: # Can't determine container container = None # If next is a simple unwrapped property, its # parentage is indeterminate, but it may have # been acquired safely. In this case validate # will raise an error, and we can explicitly # check that our value was acquired safely. try: ok = validate(obj, container, name, next) except Unauthorized: ok = False if not ok: if (container is not None or guarded_getattr(obj, name, _marker) is not next): raise Unauthorized(name) except UseTraversalDefault: # behave as if there had been no '__bobo_traverse__' bobo_traverse = None if next is UseTraversalDefault: if getattr(aq_base(obj), name, _marker) is not _marker: if restricted: next = guarded_getattr(obj, name) else: next = getattr(obj, name) else: try: next = obj[name] # The item lookup may return a NullResource, # if this is the case we save it and return it # if all other lookups fail. if isinstance(next, NullResource): resource = next raise KeyError(name) except AttributeError: # Raise NotFound for easier debugging # instead of AttributeError: __getitem__ raise NotFound(name) if restricted and not validate( obj, obj, None, next): raise Unauthorized(name) except (AttributeError, NotFound, KeyError), e: # Try to look for a view next = queryMultiAdapter((obj, aq_acquire(self, 'REQUEST')), Interface, name) if next is not None: if IAcquirer.providedBy(next): next = next.__of__(obj) if restricted and not validate(obj, obj, name, next): raise Unauthorized(name) elif bobo_traverse is not None: # Attribute lookup should not be done after # __bobo_traverse__: raise e else: # No view, try acquired attributes try: if restricted: next = guarded_getattr(obj, name, _marker) else: next = getattr(obj, name, _marker) except AttributeError: raise e if next is _marker: # If we have a NullResource from earlier use it. next = resource if next is _marker: # Nothing found re-raise error raise e obj = next return obj
def unrestrictedTraverse(self, path, default=_marker, restricted=False): """Lookup an object by path. path -- The path to the object. May be a sequence of strings or a slash separated string. If the path begins with an empty path element (i.e., an empty string or a slash) then the lookup is performed from the application root. Otherwise, the lookup is relative to self. Two dots (..) as a path element indicates an upward traversal to the acquisition parent. default -- If provided, this is the value returned if the path cannot be traversed for any reason (i.e., no object exists at that path or the object is inaccessible). restricted -- If false (default) then no security checking is performed. If true, then all of the objects along the path are validated with the security machinery. Usually invoked using restrictedTraverse(). """ if not path: return self if isinstance(path, str): # Unicode paths are not allowed path = path.split('/') else: path = list(path) REQUEST = {'TraversalRequestNameStack': path} path.reverse() path_pop = path.pop if len(path) > 1 and not path[0]: # Remove trailing slash path_pop(0) if restricted: validate = getSecurityManager().validate if not path[-1]: # If the path starts with an empty string, go to the root first. path_pop() obj = self.getPhysicalRoot() if restricted: validate(None, None, None, obj) # may raise Unauthorized else: obj = self # import time ordering problem from webdav.NullResource import NullResource resource = _marker try: while path: name = path_pop() __traceback_info__ = path, name if name[0] == '_': # Never allowed in a URL. raise NotFound, name if name == '..': next = aq_parent(obj) if next is not None: if restricted and not validate(obj, obj, name, next): raise Unauthorized(name) obj = next continue bobo_traverse = getattr(obj, '__bobo_traverse__', None) try: if name and name[:1] in '@+' and name != '+' and nsParse( name)[1]: # Process URI segment parameters. ns, nm = nsParse(name) try: next = namespaceLookup(ns, nm, obj, aq_acquire(self, 'REQUEST')) if IAcquirer.providedBy(next): next = next.__of__(obj) if restricted and not validate( obj, obj, name, next): raise Unauthorized(name) except LocationError: raise AttributeError(name) else: next = UseTraversalDefault # indicator try: if bobo_traverse is not None: next = bobo_traverse(REQUEST, name) if restricted: if aq_base(next) is not next: # The object is wrapped, so the acquisition # context is the container. container = aq_parent(aq_inner(next)) elif getattr(next, 'im_self', None) is not None: # Bound method, the bound instance # is the container container = next.im_self elif getattr(aq_base(obj), name, _marker) is next: # Unwrapped direct attribute of the object so # object is the container container = obj else: # Can't determine container container = None # If next is a simple unwrapped property, its # parentage is indeterminate, but it may have # been acquired safely. In this case validate # will raise an error, and we can explicitly # check that our value was acquired safely. try: ok = validate(obj, container, name, next) except Unauthorized: ok = False if not ok: if (container is not None or guarded_getattr( obj, name, _marker) is not next): raise Unauthorized(name) except UseTraversalDefault: # behave as if there had been no '__bobo_traverse__' bobo_traverse = None if next is UseTraversalDefault: if getattr(aq_base(obj), name, _marker) is not _marker: if restricted: next = guarded_getattr(obj, name) else: next = getattr(obj, name) else: try: next = obj[name] # The item lookup may return a NullResource, # if this is the case we save it and return it # if all other lookups fail. if isinstance(next, NullResource): resource = next raise KeyError(name) except (AttributeError, TypeError): # Raise NotFound for easier debugging # instead of AttributeError: __getitem__ # or TypeError: not subscriptable raise NotFound(name) if restricted and not validate( obj, obj, None, next): raise Unauthorized(name) except (AttributeError, NotFound, KeyError), e: # Try to look for a view next = queryMultiAdapter( (obj, aq_acquire(self, 'REQUEST')), Interface, name) if next is not None: if IAcquirer.providedBy(next): next = next.__of__(obj) if restricted and not validate(obj, obj, name, next): raise Unauthorized(name) elif bobo_traverse is not None: # Attribute lookup should not be done after # __bobo_traverse__: raise e else: # No view, try acquired attributes try: if restricted: next = guarded_getattr(obj, name, _marker) else: next = getattr(obj, name, _marker) except AttributeError: raise e if next is _marker: # If we have a NullResource from earlier use it. next = resource if next is _marker: # Nothing found re-raise error raise e obj = next return obj