Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
Zope
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
Zope
Commits
a9bcf327
Commit
a9bcf327
authored
Jun 29, 2015
by
Tres Seaver
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'lp789863-make_request_unpublishable-2.13' into 2.13
parents
55485d69
c233041e
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
90 additions
and
15 deletions
+90
-15
doc/CHANGES.rst
doc/CHANGES.rst
+3
-0
src/ZPublisher/BaseRequest.py
src/ZPublisher/BaseRequest.py
+4
-0
src/ZPublisher/HTTPRequest.py
src/ZPublisher/HTTPRequest.py
+1
-0
src/ZPublisher/tests/testBaseRequest.py
src/ZPublisher/tests/testBaseRequest.py
+32
-2
src/ZPublisher/tests/testHTTPRequest.py
src/ZPublisher/tests/testHTTPRequest.py
+50
-13
No files found.
doc/CHANGES.rst
View file @
a9bcf327
...
@@ -8,6 +8,9 @@ http://docs.zope.org/zope2/
...
@@ -8,6 +8,9 @@ http://docs.zope.org/zope2/
2.13.23 (unreleased)
2.13.23 (unreleased)
--------------------
--------------------
- LP #789863: Ensure that Request objects cannot be published / traversed
directly via a URL.
- Issue #27: Fix publishing of ``ZPublisher.Iterators.IStreamIterator`` under
- Issue #27: Fix publishing of ``ZPublisher.Iterators.IStreamIterator`` under
WSGI. This interface does not have ``seek`` or ``tell``. Introduce
WSGI. This interface does not have ``seek`` or ``tell``. Introduce
``ZPublisher.Iterators.IUnboundStreamIterator`` to support publishing
``ZPublisher.Iterators.IUnboundStreamIterator`` to support publishing
...
...
src/ZPublisher/BaseRequest.py
View file @
a9bcf327
...
@@ -206,6 +206,7 @@ class BaseRequest:
...
@@ -206,6 +206,7 @@ class BaseRequest:
def
__init__
(
self
,
other
=
None
,
**
kw
):
def
__init__
(
self
,
other
=
None
,
**
kw
):
"""The constructor is not allowed to raise errors
"""The constructor is not allowed to raise errors
"""
"""
self
.
__doc__
=
None
# Make BaseRequest objects unpublishable
if
other
is
None
:
other
=
kw
if
other
is
None
:
other
=
kw
else
:
other
.
update
(
kw
)
else
:
other
.
update
(
kw
)
self
.
other
=
other
self
.
other
=
other
...
@@ -276,6 +277,9 @@ class BaseRequest:
...
@@ -276,6 +277,9 @@ class BaseRequest:
raise
KeyError
,
key
raise
KeyError
,
key
return
v
return
v
def
__bobo_traverse__
(
self
,
name
):
raise
KeyError
(
name
)
def
__getattr__
(
self
,
key
,
default
=
_marker
):
def
__getattr__
(
self
,
key
,
default
=
_marker
):
v
=
self
.
get
(
key
,
default
)
v
=
self
.
get
(
key
,
default
)
if
v
is
_marker
:
if
v
is
_marker
:
...
...
src/ZPublisher/HTTPRequest.py
View file @
a9bcf327
...
@@ -315,6 +315,7 @@ class HTTPRequest(BaseRequest):
...
@@ -315,6 +315,7 @@ class HTTPRequest(BaseRequest):
self
.
_locale
=
locales
.
getLocale
(
None
,
None
,
None
)
self
.
_locale
=
locales
.
getLocale
(
None
,
None
,
None
)
def
__init__
(
self
,
stdin
,
environ
,
response
,
clean
=
0
):
def
__init__
(
self
,
stdin
,
environ
,
response
,
clean
=
0
):
self
.
__doc__
=
None
# Make HTTPRequest objects unpublishable
self
.
_orig_env
=
environ
self
.
_orig_env
=
environ
# Avoid the overhead of scrubbing the environment in the
# Avoid the overhead of scrubbing the environment in the
# case of request cloning for traversal purposes. If the
# case of request cloning for traversal purposes. If the
...
...
src/ZPublisher/tests/testBaseRequest.py
View file @
a9bcf327
...
@@ -189,6 +189,19 @@ class TestBaseRequest(unittest.TestCase, BaseRequest_factory):
...
@@ -189,6 +189,19 @@ class TestBaseRequest(unittest.TestCase, BaseRequest_factory):
folder
=
root
.
_setObject
(
'folder'
,
self
.
_makeBasicObject
())
folder
=
root
.
_setObject
(
'folder'
,
self
.
_makeBasicObject
())
return
root
,
folder
return
root
,
folder
def
test_no_docstring_on_instance
(
self
):
root
,
folder
=
self
.
_makeRootAndFolder
()
r
=
self
.
_makeOne
(
root
)
self
.
assertTrue
(
r
.
__doc__
is
None
)
def
test___bobo_traverse___raises
(
self
):
root
,
folder
=
self
.
_makeRootAndFolder
()
folder
.
_setObject
(
'objBasic'
,
self
.
_makeBasicObject
())
r
=
self
.
_makeOne
(
root
)
self
.
assertRaises
(
KeyError
,
r
.
__bobo_traverse__
,
'REQUEST'
)
self
.
assertRaises
(
KeyError
,
r
.
__bobo_traverse__
,
'BODY'
)
self
.
assertRaises
(
KeyError
,
r
.
__bobo_traverse__
,
'BODYFILE'
)
def
test_traverse_basic
(
self
):
def
test_traverse_basic
(
self
):
root
,
folder
=
self
.
_makeRootAndFolder
()
root
,
folder
=
self
.
_makeRootAndFolder
()
folder
.
_setObject
(
'objBasic'
,
self
.
_makeBasicObject
())
folder
.
_setObject
(
'objBasic'
,
self
.
_makeBasicObject
())
...
@@ -468,7 +481,7 @@ class TestBaseRequest(unittest.TestCase, BaseRequest_factory):
...
@@ -468,7 +481,7 @@ class TestBaseRequest(unittest.TestCase, BaseRequest_factory):
self
.
assertRaises
(
NotFound
,
r
.
traverse
,
'not_found'
)
self
.
assertRaises
(
NotFound
,
r
.
traverse
,
'not_found'
)
class
Test
BaseRequestZope3Views
(
unittest
.
TestCase
,
BaseRequest_factory
):
class
Test
RequestZope3ViewsBase
(
unittest
.
TestCase
,
BaseRequest_factory
):
_dummy_interface
=
None
_dummy_interface
=
None
...
@@ -479,13 +492,27 @@ class TestBaseRequestZope3Views(unittest.TestCase, BaseRequest_factory):
...
@@ -479,13 +492,27 @@ class TestBaseRequestZope3Views(unittest.TestCase, BaseRequest_factory):
def
_makeOne
(
self
,
root
):
def
_makeOne
(
self
,
root
):
from
zope.interface
import
directlyProvides
from
zope.interface
import
directlyProvides
from
zope.publisher.browser
import
IDefaultBrowserLayer
from
zope.publisher.browser
import
IDefaultBrowserLayer
request
=
super
(
Test
BaseRequestZope3Views
,
self
).
_makeOne
(
root
)
request
=
super
(
Test
RequestZope3ViewsBase
,
self
).
_makeOne
(
root
)
# The request needs to implement the proper interface
# The request needs to implement the proper interface
directlyProvides
(
request
,
IDefaultBrowserLayer
)
directlyProvides
(
request
,
IDefaultBrowserLayer
)
return
request
return
request
def
_makeDummyAclUsers
(
self
):
from
Acquisition
import
Implicit
from
AccessControl.ZopeSecurityPolicy
import
_noroles
class
AclUsers
(
Implicit
):
def
validate
(
self
,
request
,
auth
=
''
,
roles
=
_noroles
):
# always validate access as anonymous, good for checking
# if things are publishable regardless of authorization
from
AccessControl.SpecialUsers
import
nobody
return
nobody
.
__of__
(
self
)
acl_users
=
AclUsers
()
return
acl_users
def
_makeRootAndFolder
(
self
):
def
_makeRootAndFolder
(
self
):
root
=
self
.
_makeBasicObject
()
root
=
self
.
_makeBasicObject
()
root
.
__allow_groups__
=
self
.
_makeDummyAclUsers
()
folder
=
root
.
_setObject
(
'folder'
,
self
.
_makeDummyObject
(
'folder'
))
folder
=
root
.
_setObject
(
'folder'
,
self
.
_makeDummyObject
(
'folder'
))
return
root
,
folder
return
root
,
folder
...
@@ -613,6 +640,9 @@ class TestBaseRequestZope3Views(unittest.TestCase, BaseRequest_factory):
...
@@ -613,6 +640,9 @@ class TestBaseRequestZope3Views(unittest.TestCase, BaseRequest_factory):
gsm
.
registerAdapter
(
name
,
(
self
.
_dummyInterface
(),
IBrowserRequest
),
gsm
.
registerAdapter
(
name
,
(
self
.
_dummyInterface
(),
IBrowserRequest
),
IDefaultViewName
,
''
)
IDefaultViewName
,
''
)
class
TestBaseRequestZope3Views
(
TestRequestZope3ViewsBase
):
def
test_traverse_view
(
self
):
def
test_traverse_view
(
self
):
#simple view
#simple view
root
,
folder
=
self
.
_makeRootAndFolder
()
root
,
folder
=
self
.
_makeRootAndFolder
()
...
...
src/ZPublisher/tests/testHTTPRequest.py
View file @
a9bcf327
import
unittest
import
unittest
from
ZPublisher.tests.testBaseRequest
import
TestRequestZope3ViewsBase
class
RecordTests
(
unittest
.
TestCase
):
class
RecordTests
(
unittest
.
TestCase
):
...
@@ -11,7 +13,8 @@ class RecordTests(unittest.TestCase):
...
@@ -11,7 +13,8 @@ class RecordTests(unittest.TestCase):
d
=
eval
(
r
)
d
=
eval
(
r
)
self
.
assertEqual
(
d
,
rec
.
__dict__
)
self
.
assertEqual
(
d
,
rec
.
__dict__
)
class
HTTPRequestTests
(
unittest
.
TestCase
):
class
HTTPRequestFactoryMixin
(
object
):
def
_getTargetClass
(
self
):
def
_getTargetClass
(
self
):
from
ZPublisher.HTTPRequest
import
HTTPRequest
from
ZPublisher.HTTPRequest
import
HTTPRequest
...
@@ -19,7 +22,7 @@ class HTTPRequestTests(unittest.TestCase):
...
@@ -19,7 +22,7 @@ class HTTPRequestTests(unittest.TestCase):
def
_makeOne
(
self
,
stdin
=
None
,
environ
=
None
,
response
=
None
,
clean
=
1
):
def
_makeOne
(
self
,
stdin
=
None
,
environ
=
None
,
response
=
None
,
clean
=
1
):
from
StringIO
import
StringIO
from
StringIO
import
StringIO
from
ZPublisher
import
NotFound
from
ZPublisher
.HTTPResponse
import
HTTPResponse
if
stdin
is
None
:
if
stdin
is
None
:
stdin
=
StringIO
()
stdin
=
StringIO
()
...
@@ -36,20 +39,12 @@ class HTTPRequestTests(unittest.TestCase):
...
@@ -36,20 +39,12 @@ class HTTPRequestTests(unittest.TestCase):
environ
[
'SERVER_PORT'
]
=
'8080'
environ
[
'SERVER_PORT'
]
=
'8080'
if
response
is
None
:
if
response
is
None
:
class
_FauxResponse
(
object
):
response
=
HTTPResponse
(
stdout
=
StringIO
())
_auth
=
None
debug_mode
=
False
errmsg
=
'OK'
def
notFoundError
(
self
,
message
):
return
self
.
_getTargetClass
()(
stdin
,
environ
,
response
,
clean
)
raise
NotFound
,
message
def
exception
(
self
,
*
args
,
**
kw
):
pass
response
=
_FauxResponse
()
return
self
.
_getTargetClass
()(
stdin
,
environ
,
response
,
clean
)
class
HTTPRequestTests
(
unittest
.
TestCase
,
HTTPRequestFactoryMixin
):
def
_processInputs
(
self
,
inputs
):
def
_processInputs
(
self
,
inputs
):
from
urllib
import
quote_plus
from
urllib
import
quote_plus
...
@@ -137,6 +132,19 @@ class HTTPRequestTests(unittest.TestCase):
...
@@ -137,6 +132,19 @@ class HTTPRequestTests(unittest.TestCase):
"Key %s not correctly reproduced in tainted; expected %r, "
"Key %s not correctly reproduced in tainted; expected %r, "
"got %r"
%
(
key
,
req
.
form
[
key
],
req
.
taintedform
[
key
]))
"got %r"
%
(
key
,
req
.
form
[
key
],
req
.
taintedform
[
key
]))
def
test_no_docstring_on_instance
(
self
):
env
=
{
'SERVER_NAME'
:
'testingharnas'
,
'SERVER_PORT'
:
'80'
}
req
=
self
.
_makeOne
(
environ
=
env
)
self
.
assertTrue
(
req
.
__doc__
is
None
)
def
test___bobo_traverse___raises
(
self
):
env
=
{
'SERVER_NAME'
:
'testingharnas'
,
'SERVER_PORT'
:
'80'
}
req
=
self
.
_makeOne
(
environ
=
env
)
self
.
assertRaises
(
KeyError
,
req
.
__bobo_traverse__
,
'REQUEST'
)
self
.
assertRaises
(
KeyError
,
req
.
__bobo_traverse__
,
'BODY'
)
self
.
assertRaises
(
KeyError
,
req
.
__bobo_traverse__
,
'BODYFILE'
)
self
.
assertRaises
(
KeyError
,
req
.
__bobo_traverse__
,
'RESPONSE'
)
def
test_processInputs_wo_query_string
(
self
):
def
test_processInputs_wo_query_string
(
self
):
env
=
{
'SERVER_NAME'
:
'testingharnas'
,
'SERVER_PORT'
:
'80'
}
env
=
{
'SERVER_NAME'
:
'testingharnas'
,
'SERVER_PORT'
:
'80'
}
req
=
self
.
_makeOne
(
environ
=
env
)
req
=
self
.
_makeOne
(
environ
=
env
)
...
@@ -1046,6 +1054,34 @@ class HTTPRequestTests(unittest.TestCase):
...
@@ -1046,6 +1054,34 @@ class HTTPRequestTests(unittest.TestCase):
req
.
_script
=
[
'foo'
,
'bar'
]
req
.
_script
=
[
'foo'
,
'bar'
]
self
.
assertEquals
(
req
.
getVirtualRoot
(),
'/foo/bar'
)
self
.
assertEquals
(
req
.
getVirtualRoot
(),
'/foo/bar'
)
class
TestHTTPRequestZope3Views
(
TestRequestZope3ViewsBase
,):
def
_makeOne
(
self
,
root
):
from
zope.interface
import
directlyProvides
from
zope.publisher.browser
import
IDefaultBrowserLayer
request
=
HTTPRequestFactoryMixin
().
_makeOne
()
request
[
'PARENTS'
]
=
[
root
]
# The request needs to implement the proper interface
directlyProvides
(
request
,
IDefaultBrowserLayer
)
return
request
def
test_no_traversal_of_view_request_attribute
(
self
):
# make sure views don't accidentally publish the 'request' attribute
from
ZPublisher
import
NotFound
root
,
_
=
self
.
_makeRootAndFolder
()
# make sure the view itself is traversable:
view
=
self
.
_makeOne
(
root
).
traverse
(
'folder/@@meth'
)
from
ZPublisher.HTTPRequest
import
HTTPRequest
self
.
assertEqual
(
view
.
request
.
__class__
,
HTTPRequest
,)
# but not the request:
self
.
assertRaises
(
NotFound
,
self
.
_makeOne
(
root
).
traverse
,
'folder/@@meth/request'
)
TEST_ENVIRON
=
{
TEST_ENVIRON
=
{
'CONTENT_TYPE'
:
'multipart/form-data; boundary=12345'
,
'CONTENT_TYPE'
:
'multipart/form-data; boundary=12345'
,
'REQUEST_METHOD'
:
'POST'
,
'REQUEST_METHOD'
:
'POST'
,
...
@@ -1077,4 +1113,5 @@ def test_suite():
...
@@ -1077,4 +1113,5 @@ def test_suite():
suite
=
unittest
.
TestSuite
()
suite
=
unittest
.
TestSuite
()
suite
.
addTest
(
unittest
.
makeSuite
(
RecordTests
))
suite
.
addTest
(
unittest
.
makeSuite
(
RecordTests
))
suite
.
addTest
(
unittest
.
makeSuite
(
HTTPRequestTests
))
suite
.
addTest
(
unittest
.
makeSuite
(
HTTPRequestTests
))
suite
.
addTest
(
unittest
.
makeSuite
(
TestHTTPRequestZope3Views
))
return
suite
return
suite
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment