Commit cac3d5bf authored by Florent Guillaume's avatar Florent Guillaume

Collector #1498: Don't choke on malformed cookies. Cookies of the form

"foo=bar; hmm; baz=gee" will give an empty value for 'hmm' instead of
silently discarding it and the rest of the string. (Thanks to 'sirilyan'
for the patch.)
parent 066b9e9e
......@@ -45,11 +45,16 @@ Zope Changes
text/<foo> types
Bugs fixed
- Collector #1498: Don't choke on malformed cookies. Cookies of
the form "foo=bar; hmm; baz=gee" will give an empty value for
'hmm' instead of silently discarding it and the rest of the
string. (Thanks to 'sirilyan' for the patch.)
- bin/zopectl test now uses os.execv, instead os os.system,
so that options with characters that needs shell quoting
doesn't break the command.
- Collector #945: Allow adding empty PythonScript instances
programmatically.
......
......@@ -14,7 +14,7 @@
$Id$
"""
import re, sys, Globals, Moniker, tempfile, ExtensionClass
import re, sys, Globals, Moniker, tempfile, ExtensionClass
from marshal import loads, dumps
from urllib import quote, unquote
from zlib import compress, decompress
......@@ -29,6 +29,8 @@ from cgi import escape
CopyError='Copy Error'
copy_re = re.compile('^copy([0-9]*)_of_(.*)')
_marker=[]
class CopyContainer(ExtensionClass.Base):
"""Interface for containerish objects which allow cut/copy/paste"""
......@@ -113,19 +115,17 @@ class CopyContainer(ExtensionClass.Base):
return self.manage_main(self, REQUEST)
return cp
copy_re=re.compile('^copy[0-9]*_of_')
def _get_id(self, id):
# Allow containers to override the generation of
# object copy id by attempting to call its _get_id
# method, if it exists.
copy_match=self.copy_re.match(id)
if (copy_match) and (copy_match.end() < len(id)):
n=1
orig_id=self.copy_re.sub('', id)
match = copy_re.match(id)
if match:
n = int(match.group(1) or '1')
orig_id = match.group(2)
else:
n=0
orig_id=id
n = 0
orig_id = id
while 1:
if self._getOb(id, None) is None:
return id
......
......@@ -183,6 +183,43 @@ class TestCopySupport( CopySupportTestBase ):
self.failUnless( 'copy_of_file' in self.folder2.objectIds() )
self.failUnless( result == [{'id':'file', 'new_id':'copy_of_file'}])
def testPasteSingleSameIDMultipleTimes(self):
cookie = self.folder1.manage_copyObjects(ids=('file',))
result = self.folder1.manage_pasteObjects(cookie)
self.assertEqual(self.folder1.objectIds(), ['file', 'copy_of_file'])
self.assertEqual(result, [{'id':'file', 'new_id':'copy_of_file'}])
# make another copy of file
cookie = self.folder1.manage_copyObjects(ids=('file',))
result = self.folder1.manage_pasteObjects(cookie)
self.assertEqual(self.folder1.objectIds(),
['file', 'copy_of_file', 'copy2_of_file'])
self.assertEqual(result, [{'id':'file', 'new_id':'copy2_of_file'}])
# now copy the copy
cookie = self.folder1.manage_copyObjects(ids=('copy_of_file',))
result = self.folder1.manage_pasteObjects(cookie)
self.assertEqual(self.folder1.objectIds(),
['file', 'copy_of_file', 'copy2_of_file',
'copy3_of_file'])
self.assertEqual(result, [{'id':'copy_of_file',
'new_id':'copy3_of_file'}])
# or copy another copy
cookie = self.folder1.manage_copyObjects(ids=('copy2_of_file',))
result = self.folder1.manage_pasteObjects(cookie)
self.assertEqual(self.folder1.objectIds(),
['file', 'copy_of_file', 'copy2_of_file',
'copy3_of_file', 'copy4_of_file'])
self.assertEqual(result, [{'id':'copy2_of_file',
'new_id':'copy4_of_file'}])
def testPasteSpecialName(self):
manage_addFile(self.folder1, 'copy_of_',
file='', content_type='text/plain')
cookie = self.folder1.manage_copyObjects(ids=('copy_of_',))
result = self.folder1.manage_pasteObjects(cookie)
self.assertEqual(self.folder1.objectIds(),
['file', 'copy_of_', 'copy2_of_'])
self.assertEqual(result, [{'id':'copy_of_', 'new_id':'copy2_of_'}])
def testPasteMultiNotSameID( self ):
self.failUnless( 'file' in self.folder1.objectIds() )
self.failIf( 'file1' in self.folder1.objectIds() )
......
......@@ -1438,6 +1438,8 @@ def parse_cookie(text,
'([\x00- ]*([^\x00- ;,="]+)="([^"]*)"([\x00- ]*[;,])?[\x00- ]*)'),
parmre=re.compile(
'([\x00- ]*([^\x00- ;,="]+)=([^\x00- ;,"]*)([\x00- ]*[;,])?[\x00- ]*)'),
paramlessre=re.compile(
'([\x00- ]*([^\x00- ;,="]+)[\x00- ]*[;,][\x00- ]*)'),
acquire=parse_cookie_lock.acquire,
release=parse_cookie_lock.release,
......@@ -1469,7 +1471,15 @@ def parse_cookie(text,
value = mo_p.group(3)
else:
return result
# Broken Cookie without = nor value.
broken_p = paramlessre.match(text)
if broken_p:
l = len(broken_p.group(1))
name = broken_p.group(2)
value = ''
else:
return result
finally: release()
......
......@@ -564,6 +564,25 @@ class ProcessInputsTests(unittest.TestCase):
self._noTaintedValues(req)
self._onlyTaintedformHoldsTaintedStrings(req)
def testCookieParsing(self):
env = {'SERVER_NAME': 'testingharnas', 'SERVER_PORT': '80'}
env['HTTP_COOKIE'] = 'foo=bar; baz=gee'
req = self._getHTTPRequest(env)
self.assertEquals(req.cookies['foo'], 'bar')
self.assertEquals(req.cookies['baz'], 'gee')
env['HTTP_COOKIE'] = 'foo=bar; baz="gee, like, e=mc^2"'
req = self._getHTTPRequest(env)
self.assertEquals(req.cookies['foo'], 'bar')
self.assertEquals(req.cookies['baz'], 'gee, like, e=mc^2')
# Collector #1498: empty cookies
env['HTTP_COOKIE'] = 'foo=bar; hmm; baz=gee'
req = self._getHTTPRequest(env)
self.assertEquals(req.cookies['foo'], 'bar')
self.assertEquals(req.cookies['hmm'], '')
self.assertEquals(req.cookies['baz'], 'gee')
TEST_ENVIRON = {
'CONTENT_TYPE': 'multipart/form-data; boundary=12345',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment