Mercurial > p > roundup > code
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 '<%s>'%match.group(2) | 48 return '<%s>'%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 |
