Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Zope: Dev

Why does restrictedTraverse() in Zope 2 not respect IPublishTraverse adapters?

 

 

Zope dev RSS feed   Index | Next | Previous | View Threaded


optilude+lists at gmail

May 14, 2009, 8:14 AM

Post #1 of 6 (859 views)
Permalink
Why does restrictedTraverse() in Zope 2 not respect IPublishTraverse adapters?

Hi,

There's currently a funny inconsistency in Zope's Traversable class. If
you have a URL like http://localhost:8080/path/to/@@aview/foo, and
@@aview implements IPublishTraverse (and, I presume, if there's a custom
IPublishTraverse adapter for any other path component), URL traversal
will work fine, but calling to.restrictedTraverse('@@aview/foo') or some
variant thereof will fail, because (un)restrictedTraverse() does not
respect custom IPublishTraverse adapters.

I can kind of see why it's done like this since it's called
I*Publish*Traverse, but it is a pain.

Note that namespace traversal (like ++skin++) works fine with
restrictedTraverse().

I don't think it'd be hard to implement this, but:

- is this a bug?
- is there a reason not to do this?

Martin

--
Author of `Professional Plone Development`, a book for developers who
want to work with Plone. See http://martinaspeli.net/plone-book

_______________________________________________
Zope-Dev maillist - Zope-Dev [at] zope
http://mail.zope.org/mailman/listinfo/zope-dev
** No cross posts or HTML encoding! **
(Related lists -
http://mail.zope.org/mailman/listinfo/zope-announce
http://mail.zope.org/mailman/listinfo/zope )


tseaver at palladion

May 14, 2009, 9:55 AM

Post #2 of 6 (808 views)
Permalink
Re: Why does restrictedTraverse() in Zope 2 not respect IPublishTraverse adapters? [In reply to]

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Martin Aspeli wrote:

> There's currently a funny inconsistency in Zope's Traversable class. If
> you have a URL like http://localhost:8080/path/to/@@aview/foo, and
> @@aview implements IPublishTraverse (and, I presume, if there's a custom
> IPublishTraverse adapter for any other path component), URL traversal
> will work fine, but calling to.restrictedTraverse('@@aview/foo') or some
> variant thereof will fail, because (un)restrictedTraverse() does not
> respect custom IPublishTraverse adapters.

'restrictedTraverse' is not (and never has been) the same as URL
traversal. For instance:

- - URL traversal does no security checking until it finds the published
object.

- - URL traveresal manages the '__before_publishing_traverse__' hooks.


If you want your adapter to be respected by *both*, it needs to
implement the appropriate interfaces for both.

> I can kind of see why it's done like this since it's called
> I*Publish*Traverse, but it is a pain.
>
> Note that namespace traversal (like ++skin++) works fine with
> restrictedTraverse().
>
> I don't think it'd be hard to implement this, but:
>
> - is this a bug?

No.

> - is there a reason not to do this?

- -1 to adding any more majyk to the over-complicated Z3-style traversal
dance inside Zope2, especially as it would involve a bunch of subtle
behavior changes which would be hard to explain.

For maximum portability across Z2 / Z3 / BFG, you could just do the same
thing and implement __getitem__ on any object you want to be traversable
by either the publisher or APIs like (un)restrictedTraverse, and forego
the over-complicated component-laden traversal dance. ;)


Tres.
- --
===================================================================
Tres Seaver +1 540-429-0999 tseaver [at] palladion
Palladion Software "Excellence by Design" http://palladion.com
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFKDEz/+gerLs4ltQ4RAlYAAJ436Gtk2+ibpVAX/8H+Q6BOJ3+AWQCfT7HC
kDTUth7NAOCOt6yrAWR20jY=
=NvUz
-----END PGP SIGNATURE-----

_______________________________________________
Zope-Dev maillist - Zope-Dev [at] zope
http://mail.zope.org/mailman/listinfo/zope-dev
** No cross posts or HTML encoding! **
(Related lists -
http://mail.zope.org/mailman/listinfo/zope-announce
http://mail.zope.org/mailman/listinfo/zope )


l at lrowe

May 14, 2009, 1:55 PM

Post #3 of 6 (805 views)
Permalink
Re: Why does restrictedTraverse() in Zope 2 not respect IPublishTraverse adapters? [In reply to]

Tres Seaver wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Martin Aspeli wrote:
>
>> There's currently a funny inconsistency in Zope's Traversable class. If
>> you have a URL like http://localhost:8080/path/to/@@aview/foo, and
>> @@aview implements IPublishTraverse (and, I presume, if there's a custom
>> IPublishTraverse adapter for any other path component), URL traversal
>> will work fine, but calling to.restrictedTraverse('@@aview/foo') or some
>> variant thereof will fail, because (un)restrictedTraverse() does not
>> respect custom IPublishTraverse adapters.
>
> 'restrictedTraverse' is not (and never has been) the same as URL
> traversal. For instance:
>
> - - URL traversal does no security checking until it finds the published
> object.
>
> - - URL traveresal manages the '__before_publishing_traverse__' hooks.
>
>
> If you want your adapter to be respected by *both*, it needs to
> implement the appropriate interfaces for both.
>
>> I can kind of see why it's done like this since it's called
>> I*Publish*Traverse, but it is a pain.
>>
>> Note that namespace traversal (like ++skin++) works fine with
>> restrictedTraverse().
>>
>> I don't think it'd be hard to implement this, but:
>>
>> - is this a bug?
>
> No.
>
>> - is there a reason not to do this?
>
> - -1 to adding any more majyk to the over-complicated Z3-style traversal
> dance inside Zope2, especially as it would involve a bunch of subtle
> behavior changes which would be hard to explain.
>
> For maximum portability across Z2 / Z3 / BFG, you could just do the same
> thing and implement __getitem__ on any object you want to be traversable
> by either the publisher or APIs like (un)restrictedTraverse, and forego
> the over-complicated component-laden traversal dance. ;)

Minimal example demonstrating this with a view in zope2:

>>> from zope.component import getSiteManager
>>> from Testing.makerequest import makerequest
>>> from zope.publisher.browser import IBrowserView
>>> from Acquisition import Explicit
>>> from zope.component import getSiteManager
>>> app = makerequest(app)
>>> smgr = getSiteManager()
>>> class Foo(Explicit):
... def __init__(self, context, request):
... self.context, self.request = context, request
... def __getitem__(self, key):
... return int(key)
...
>>> smgr.registerAdapter(Foo, (None, IRequest), IBrowserView, name='foo')
>>> app.unrestrictedTraverse('@@foo/12345')
12345

Laurence

_______________________________________________
Zope-Dev maillist - Zope-Dev [at] zope
http://mail.zope.org/mailman/listinfo/zope-dev
** No cross posts or HTML encoding! **
(Related lists -
http://mail.zope.org/mailman/listinfo/zope-announce
http://mail.zope.org/mailman/listinfo/zope )


slinkp at gmail

May 15, 2009, 12:28 PM

Post #4 of 6 (794 views)
Permalink
Re: Why does restrictedTraverse() in Zope 2 not respect IPublishTraverse adapters? [In reply to]

On Thu, May 14, 2009 at 10:55:40PM +0200, Laurence Rowe wrote:
> > For maximum portability across Z2 / Z3 / BFG, you could just do the same
> > thing and implement __getitem__ on any object you want to be traversable
> > by either the publisher or APIs like (un)restrictedTraverse, and forego
> > the over-complicated component-laden traversal dance. ;)
>
> Minimal example demonstrating this with a view in zope2:
>
> >>> from zope.component import getSiteManager
> >>> from Testing.makerequest import makerequest
> >>> from zope.publisher.browser import IBrowserView
> >>> from Acquisition import Explicit
> >>> from zope.component import getSiteManager
> >>> app = makerequest(app)
> >>> smgr = getSiteManager()
> >>> class Foo(Explicit):
> ... def __init__(self, context, request):
> ... self.context, self.request = context, request
> ... def __getitem__(self, key):
> ... return int(key)
> ...
> >>> smgr.registerAdapter(Foo, (None, IRequest), IBrowserView, name='foo')
> >>> app.unrestrictedTraverse('@@foo/12345')
> 12345

Thanks for reminding me of this. I keep forgetting that this works!

I only add that if you want to use __getitem__ for publishing, the
items you return should inherit from Acquisition.(Im|Ex)plicit to make
the security machinery happy.

--

Paul Winkler
http://www.slinkp.com
_______________________________________________
Zope-Dev maillist - Zope-Dev [at] zope
http://mail.zope.org/mailman/listinfo/zope-dev
** No cross posts or HTML encoding! **
(Related lists -
http://mail.zope.org/mailman/listinfo/zope-announce
http://mail.zope.org/mailman/listinfo/zope )


plonecode at hackel

May 17, 2009, 1:32 PM

Post #5 of 6 (735 views)
Permalink
Re: Why does restrictedTraverse() in Zope 2 not respect IPublishTraverse adapters? [In reply to]

Some days ago I ran into the same problem, and have been pointed to this
thread. Maybe you are interested in my solution. It's ugly, but I needed it
for a test-case, where I wanted to access
"@@plone_context_state/is_view_template":

>>> from ZPublisher.HTTPRequest import HTTPRequest
>>> from ZPublisher.HTTPResponse import HTTPResponse
>>> from Products.PloneTestCase import PloneTestCase
>>> import base64
>>> user_id = PloneTestCase.default_user
>>> password = PloneTestCase.default_password
>>> encoded = base64.encodestring( '%s:%s' % ( user_id, password ) )
>>> auth_header = 'basic %s' % encoded
>>> resp = HTTPResponse()
>>> env={'SERVER_URL':'http://nohost/plone',
... 'URL':'http://nohost/plone',
... 'HTTP_AUTHORIZATION': auth_header,
... 'REQUEST_METHOD': 'GET',
... 'steps': [],
... '_hacked_path': 0,
... '_test_counter': 0,
... }
>>> request = HTTPRequest(stdin=None, environ=env, response=resp)
>>> request['PARENTS'] = [self.getPortal()]
>>> contextState = request.traverse("weblog/issue193/"
... "@@plone_context_state")
>>> request['ACTUAL_URL'] = 'http://nohost/weblog/issue193'
>>> contextState.is_view_template()
True
>>> request.close()

Grüße
Jan Hackel

Martin Aspeli wrote:
> There's currently a funny inconsistency in Zope's Traversable class. If
> you have a URL like http://localhost:8080/path/to/@@aview/foo, and
> @@aview implements IPublishTraverse (and, I presume, if there's a custom
> IPublishTraverse adapter for any other path component), URL traversal
> will work fine, but calling to.restrictedTraverse('@@aview/foo') or some
> variant thereof will fail, because (un)restrictedTraverse() does not
> respect custom IPublishTraverse adapters.



_______________________________________________
Zope-Dev maillist - Zope-Dev [at] zope
http://mail.zope.org/mailman/listinfo/zope-dev
** No cross posts or HTML encoding! **
(Related lists -
http://mail.zope.org/mailman/listinfo/zope-announce
http://mail.zope.org/mailman/listinfo/zope )


optilude+lists at gmail

May 20, 2009, 3:35 AM

Post #6 of 6 (731 views)
Permalink
Re: Why does restrictedTraverse() in Zope 2 not respect IPublishTraverse adapters? [In reply to]

Jan Hackel wrote:
> Some days ago I ran into the same problem, and have been pointed to this
> thread. Maybe you are interested in my solution. It's ugly, but I needed it
> for a test-case, where I wanted to access
> "@@plone_context_state/is_view_template":
>
> >>> from ZPublisher.HTTPRequest import HTTPRequest
> >>> from ZPublisher.HTTPResponse import HTTPResponse
> >>> from Products.PloneTestCase import PloneTestCase
> >>> import base64
> >>> user_id = PloneTestCase.default_user
> >>> password = PloneTestCase.default_password
> >>> encoded = base64.encodestring( '%s:%s' % ( user_id, password ) )
> >>> auth_header = 'basic %s' % encoded
> >>> resp = HTTPResponse()
> >>> env={'SERVER_URL':'http://nohost/plone',
> ... 'URL':'http://nohost/plone',
> ... 'HTTP_AUTHORIZATION': auth_header,
> ... 'REQUEST_METHOD': 'GET',
> ... 'steps': [],
> ... '_hacked_path': 0,
> ... '_test_counter': 0,
> ... }
> >>> request = HTTPRequest(stdin=None, environ=env, response=resp)
> >>> request['PARENTS'] = [self.getPortal()]
> >>> contextState = request.traverse("weblog/issue193/"
> ... "@@plone_context_state")
> >>> request['ACTUAL_URL'] = 'http://nohost/weblog/issue193'
> >>> contextState.is_view_template()
> True
> >>> request.close()

For this, you should possibly use zope.testbrowser (and
Products.Five.testbrowser).

The reason you needed this particular hack was that the
is_view_template() method looks at the url quite specifically. For most
cases, context.restrictedTraverse('@@plone_context_state') would've worked.

Martin

--
Author of `Professional Plone Development`, a book for developers who
want to work with Plone. See http://martinaspeli.net/plone-book

_______________________________________________
Zope-Dev maillist - Zope-Dev [at] zope
http://mail.zope.org/mailman/listinfo/zope-dev
** No cross posts or HTML encoding! **
(Related lists -
http://mail.zope.org/mailman/listinfo/zope-announce
http://mail.zope.org/mailman/listinfo/zope )

Zope dev RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact Gossamer Threads
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.