comparison roundup/cgi/client.py @ 3916:57ad3e2c2545

handle bad cookies Roundup's cgi gets all cookies from all apps on the same server. some apps aren't as well behaved as roundup and generate cookies that do not follow the spec perfectly. This causes python's Cookie module to throw an exception when trying to parse them. In the spirit of being liberal in what we accept, we create a LiberalCookie class that can handle those out-of-spec cookies and allow roundup to continue onward. [SF#1691708] code from S. Woodside
author Justus Pendleton <jpend@users.sourceforge.net>
date Sat, 22 Sep 2007 21:20:57 +0000
parents 182ba3207899
children 0112e9e1d068
comparison
equal deleted inserted replaced
3915:6b3919328381 3916:57ad3e2c2545
1 # $Id: client.py,v 1.237 2007-09-12 16:16:49 jpend Exp $ 1 # $Id: client.py,v 1.238 2007-09-22 21:20:57 jpend Exp $
2 2
3 """WWW request handler (also used in the stand-alone server). 3 """WWW request handler (also used in the stand-alone server).
4 """ 4 """
5 __docformat__ = 'restructuredtext' 5 __docformat__ = 'restructuredtext'
6 6
7 import base64, binascii, cgi, codecs, mimetypes, os 7 import base64, binascii, cgi, codecs, mimetypes, os
8 import random, re, rfc822, stat, time, urllib, urlparse 8 import random, re, rfc822, stat, time, urllib, urlparse
9 import Cookie, socket, errno 9 import Cookie, socket, errno
10 from Cookie import CookieError, BaseCookie, SimpleCookie
10 11
11 from roundup import roundupdb, date, hyperdb, password 12 from roundup import roundupdb, date, hyperdb, password
12 from roundup.cgi import templating, cgitb, TranslationService 13 from roundup.cgi import templating, cgitb, TranslationService
13 from roundup.cgi.actions import * 14 from roundup.cgi.actions import *
14 from roundup.exceptions import * 15 from roundup.exceptions import *
44 ''' 45 '''
45 if ok.has_key(match.group(3).lower()): 46 if ok.has_key(match.group(3).lower()):
46 return match.group(1) 47 return match.group(1)
47 return '&lt;%s&gt;'%match.group(2) 48 return '&lt;%s&gt;'%match.group(2)
48 49
50
49 error_message = ""'''<html><head><title>An error has occurred</title></head> 51 error_message = ""'''<html><head><title>An error has occurred</title></head>
50 <body><h1>An error has occurred</h1> 52 <body><h1>An error has occurred</h1>
51 <p>A problem was encountered processing your request. 53 <p>A problem was encountered processing your request.
52 The tracker maintainers have been notified of the problem.</p> 54 The tracker maintainers have been notified of the problem.</p>
53 </body></html>''' 55 </body></html>'''
56
57
58 class LiberalCookie(SimpleCookie):
59 ''' Python's SimpleCookie throws an exception if the cookie uses invalid
60 syntax. Other applications on the same server may have done precisely
61 this, preventing roundup from working through no fault of roundup.
62 Numerous other python apps have run into the same problem:
63
64 trac: http://trac.edgewall.org/ticket/2256
65 mailman: http://bugs.python.org/issue472646
66
67 This particular implementation comes from trac's solution to the
68 problem. Unfortunately it requires some hackery in SimpleCookie's
69 internals to provide a more liberal __set method.
70 '''
71 def load(self, rawdata, ignore_parse_errors=True):
72 if ignore_parse_errors:
73 self.bad_cookies = []
74 self._BaseCookie__set = self._loose_set
75 SimpleCookie.load(self, rawdata)
76 if ignore_parse_errors:
77 self._BaseCookie__set = self._strict_set
78 for key in self.bad_cookies:
79 del self[key]
80
81 _strict_set = BaseCookie._BaseCookie__set
82
83 def _loose_set(self, key, real_value, coded_value):
84 try:
85 self._strict_set(key, real_value, coded_value)
86 except CookieError:
87 self.bad_cookies.append(key)
88 dict.__setitem__(self, key, None)
89
54 90
55 class Client: 91 class Client:
56 '''Instantiate to handle one CGI request. 92 '''Instantiate to handle one CGI request.
57 93
58 See inner_main for request processing. 94 See inner_main for request processing.
179 215
180 # default character set 216 # default character set
181 self.charset = self.STORAGE_CHARSET 217 self.charset = self.STORAGE_CHARSET
182 218
183 # parse cookies (used in charset and session lookups) 219 # parse cookies (used in charset and session lookups)
184 self.cookie = Cookie.SimpleCookie(self.env.get('HTTP_COOKIE', '')) 220 # use our own LiberalCookie to handle bad apps on the same
221 # server that have set cookies that are out of spec
222 self.cookie = LiberalCookie(self.env.get('HTTP_COOKIE', ''))
185 223
186 self.user = None 224 self.user = None
187 self.userid = None 225 self.userid = None
188 self.nodeid = None 226 self.nodeid = None
189 self.classname = None 227 self.classname = None

Roundup Issue Tracker: http://roundup-tracker.org/