Ticket #5682: patch_django_5682.20080309.diff
File patch_django_5682.20080309.diff, 15.5 KB (added by , 17 years ago) |
---|
-
django/http/__init__.py
1 1 import os 2 2 from Cookie import SimpleCookie 3 3 from pprint import pformat 4 from urllib import urlencode 4 from urllib import urlencode, unquote 5 5 from urlparse import urljoin 6 6 try: 7 7 # The mod_python version is more efficient, so try importing it first. … … 23 23 class HttpRequest(object): 24 24 """A basic HTTP request.""" 25 25 26 # The encoding used in GET/POST dicts. None means use default setting.26 # The encoding used in GET/POST/PUT dicts. None means use default setting. 27 27 _encoding = None 28 28 29 29 def __init__(self): 30 self.GET, self.POST, self. COOKIES, self.META, self.FILES ={}, {}, {}, {}, {}30 self.GET, self.POST, self.PUT, self.COOKIES, self.META, self.DATA, self.FILES = {}, {}, {}, {}, {}, {}, {} 31 31 self.path = '' 32 32 self.method = None 33 33 34 34 def __repr__(self): 35 return '<HttpRequest\nGET:%s,\nPOST:%s,\n COOKIES:%s,\nMETA:%s>' % \36 (pformat(self.GET), pformat(self.POST), pformat(self. COOKIES),37 pformat(self. META))35 return '<HttpRequest\nGET:%s,\nPOST:%s,\nPUT:%s,\nCOOKIES:%s,\nMETA:%s>' % \ 36 (pformat(self.GET), pformat(self.POST), pformat(self.PUT), 37 pformat(self.COOKIES), pformat(self.META)) 38 38 39 39 def __getitem__(self, key): 40 for d in (self.POST, self.GET ):40 for d in (self.POST, self.GET, self.PUT): 41 41 if key in d: 42 42 return d[key] 43 raise KeyError, "%s not found in either POST or GET" % key43 raise KeyError, "%s not found in either POST, GET or PUT" % key 44 44 45 45 def has_key(self, key): 46 return key in self.GET or key in self.POST 46 return key in self.GET or key in self.POST or key in self.PUT 47 47 48 48 __contains__ = has_key 49 49 … … 84 84 85 85 def _set_encoding(self, val): 86 86 """ 87 Sets the encoding used for GET/POST accesses. If the GET or POST87 Sets the encoding used for GET/POST/PUT accesses. If the GET, POST or PUT 88 88 dictionary has already been created, it is removed and recreated on the 89 89 next access (so that it is decoded correctly). 90 90 """ … … 93 93 del self._get 94 94 if hasattr(self, '_post'): 95 95 del self._post 96 if hasattr(self, '_put'): 97 del self._put 96 98 97 99 def _get_encoding(self): 98 100 return self._encoding … … 100 102 encoding = property(_get_encoding, _set_encoding) 101 103 102 104 def parse_file_upload(header_dict, post_data): 103 """Returns a tuple of ( POSTQueryDict, FILES MultiValueDict)."""105 """Returns a tuple of (DATA QueryDict, FILES MultiValueDict).""" 104 106 import email, email.Message 105 107 from cgi import parse_header 106 108 raw_message = '\r\n'.join(['%s:%s' % pair for pair in header_dict.items()]) 107 109 raw_message += '\r\n\r\n' + post_data 108 110 msg = email.message_from_string(raw_message) 109 POST= QueryDict('', mutable=True)111 DATA = QueryDict('', mutable=True) 110 112 FILES = MultiValueDict() 111 113 for submessage in msg.get_payload(): 112 114 if submessage and isinstance(submessage, email.Message.Message): … … 129 131 'content': submessage.get_payload(), 130 132 })) 131 133 else: 132 POST.appendlist(name_dict['name'], submessage.get_payload())133 return POST, FILES134 DATA.appendlist(name_dict['name'], submessage.get_payload()) 135 return DATA, FILES 134 136 135 137 136 138 class QueryDict(MultiValueDict): … … 198 200 def appendlist(self, key, value): 199 201 self._assert_mutable() 200 202 key = str_to_unicode(key, self.encoding) 203 if key == u'text': # restrict unquoting for sms 204 value = unquote(value) 201 205 value = str_to_unicode(value, self.encoding) 202 206 MultiValueDict.appendlist(self, key, value) 203 207 -
django/test/client.py
216 216 217 217 return self.request(**r) 218 218 219 def delete(self, path, data={}, **extra): 220 "Request a response from the server using DELETE." 221 r = { 222 'CONTENT_LENGTH': None, 223 'CONTENT_TYPE': 'text/html; charset=utf-8', 224 'PATH_INFO': path, 225 'QUERY_STRING': urlencode(data, doseq=True), 226 'REQUEST_METHOD': 'DELETE', 227 } 228 r.update(extra) 229 230 return self.request(**r) 231 232 def delete(self, path, data={}, **extra): 233 "Request a response from the server using DELETE." 234 r = { 235 'CONTENT_LENGTH': None, 236 'CONTENT_TYPE': 'text/html; charset=utf-8', 237 'PATH_INFO': path, 238 'QUERY_STRING': urlencode(data, doseq=True), 239 'REQUEST_METHOD': 'DELETE', 240 } 241 r.update(extra) 242 243 return self.request(**r) 244 219 245 def post(self, path, data={}, content_type=MULTIPART_CONTENT, **extra): 220 246 "Request a response from the server using POST." 221 247 … … 235 261 236 262 return self.request(**r) 237 263 264 def put(self, path, data={}, content_type=MULTIPART_CONTENT, **extra): 265 "Request a response from the server using PUT." 266 267 if content_type is MULTIPART_CONTENT: 268 put_data = encode_multipart(BOUNDARY, data) 269 else: 270 put_data = data 271 272 r = { 273 'CONTENT_LENGTH': len(put_data), 274 'CONTENT_TYPE': content_type, 275 'PATH_INFO': path, 276 'REQUEST_METHOD': 'PUT', 277 'wsgi.input': StringIO(put_data), 278 } 279 r.update(extra) 280 281 return self.request(**r) 282 283 def put(self, path, data={}, content_type=MULTIPART_CONTENT, **extra): 284 "Request a response from the server using PUT." 285 286 if content_type is MULTIPART_CONTENT: 287 put_data = encode_multipart(BOUNDARY, data) 288 else: 289 put_data = data 290 291 r = { 292 'CONTENT_LENGTH': len(put_data), 293 'CONTENT_TYPE': content_type, 294 'PATH_INFO': path, 295 'REQUEST_METHOD': 'PUT', 296 'wsgi.input': StringIO(put_data), 297 } 298 r.update(extra) 299 300 return self.request(**r) 301 238 302 def login(self, **credentials): 239 303 """Set the Client to appear as if it has sucessfully logged into a site. 240 304 -
django/core/handlers/wsgi.py
91 91 except: 92 92 post = '<could not parse>' 93 93 try: 94 put = pformat(self.PUT) 95 except: 96 put = '<could not parse>' 97 try: 94 98 cookies = pformat(self.COOKIES) 95 99 except: 96 100 cookies = '<could not parse>' … … 98 102 meta = pformat(self.META) 99 103 except: 100 104 meta = '<could not parse>' 101 return '<WSGIRequest\nGET:%s,\nPOST:%s,\n COOKIES:%s,\nMETA:%s>' % \102 (get, post, cookies, meta)105 return '<WSGIRequest\nGET:%s,\nPOST:%s,\nPUT:%s,\nCOOKIES:%s,\nMETA:%s>' % \ 106 (get, post, put, cookies, meta) 103 107 104 108 def get_full_path(self): 105 109 return '%s%s' % (self.path, self.environ.get('QUERY_STRING', '') and ('?' + self.environ.get('QUERY_STRING', '')) or '') … … 108 112 return 'wsgi.url_scheme' in self.environ \ 109 113 and self.environ['wsgi.url_scheme'] == 'https' 110 114 111 def _load_ post_and_files(self):112 # Populates self._ postand self._files113 if self.method == 'POST':115 def _load_data_and_files(self): 116 # Populates self._data and self._files 117 if self.method in ('POST', 'PUT'): 114 118 if self.environ.get('CONTENT_TYPE', '').startswith('multipart'): 115 119 header_dict = dict([(k, v) for k, v in self.environ.items() if k.startswith('HTTP_')]) 116 120 header_dict['Content-Type'] = self.environ.get('CONTENT_TYPE', '') 117 self._ post, self._files = http.parse_file_upload(header_dict, self.raw_post_data)121 self._data, self._files = http.parse_file_upload(header_dict, self.raw_post_data) 118 122 else: 119 self._ post, self._files = http.QueryDict(self.raw_post_data, encoding=self._encoding), datastructures.MultiValueDict()123 self._data, self._files = http.QueryDict(self.raw_post_data, encoding=self._encoding), datastructures.MultiValueDict() 120 124 else: 121 self._ post, self._files = http.QueryDict('', encoding=self._encoding), datastructures.MultiValueDict()125 self._data, self._files = http.QueryDict('', encoding=self._encoding), datastructures.MultiValueDict() 122 126 127 def _load_post_and_files(self): 128 # Populates self._post, preserve backward compatibility. 129 if not hasattr(self, '_data'): 130 self._load_data_and_files() 131 self._post = self._data 132 123 133 def _get_request(self): 124 134 if not hasattr(self, '_request'): 125 self._request = datastructures.MergeDict(self.POST, self. GET)135 self._request = datastructures.MergeDict(self.POST, self.PUT, self.GET) 126 136 return self._request 127 137 128 138 def _get_get(self): 129 139 if not hasattr(self, '_get'): 130 140 # The WSGI spec says 'QUERY_STRING' may be absent. 131 self._get = http.QueryDict(self.environ.get('QUERY_STRING', ''), encoding=self._encoding) 141 query_string = self.environ.get('QUERY_STRING', '') 142 if 'charset' in query_string: # for sms 143 self._encoding = query_string.split('charset=', 1)[1].split('&', 1)[0].lower() 144 self._get = http.QueryDict(query_string, encoding=self._encoding) 132 145 return self._get 133 146 134 147 def _set_get(self, get): … … 136 149 137 150 def _get_post(self): 138 151 if not hasattr(self, '_post'): 139 self._ load_post_and_files()152 self._post = self.DATA 140 153 return self._post 141 154 142 155 def _set_post(self, post): 143 156 self._post = post 144 157 158 def _get_put(self): 159 if not hasattr(self, '_put'): 160 self._put = self.DATA 161 return self._put 162 163 def _set_put(self, put): 164 self._put = put 165 145 166 def _get_cookies(self): 146 167 if not hasattr(self, '_cookies'): 147 168 self._cookies = http.parse_cookie(self.environ.get('HTTP_COOKIE', '')) … … 152 173 153 174 def _get_files(self): 154 175 if not hasattr(self, '_files'): 155 self._load_ post_and_files()176 self._load_data_and_files() 156 177 return self._files 157 178 179 def _get_data(self): 180 if not hasattr(self, '_data'): 181 self._load_data_and_files() 182 return self._data 183 158 184 def _get_raw_post_data(self): 159 185 try: 160 186 return self._raw_post_data … … 174 200 175 201 GET = property(_get_get, _set_get) 176 202 POST = property(_get_post, _set_post) 203 PUT = property(_get_put, _set_put) 177 204 COOKIES = property(_get_cookies, _set_cookies) 178 205 FILES = property(_get_files) 206 DATA = property(_get_data) 179 207 REQUEST = property(_get_request) 180 208 raw_post_data = property(_get_raw_post_data) 181 209 210 182 211 class WSGIHandler(BaseHandler): 183 212 initLock = Lock() 184 213 request_class = WSGIRequest -
django/core/handlers/modpython.py
29 29 except: 30 30 post = '<could not parse>' 31 31 try: 32 put = pformat(self.PUT) 33 except: 34 put = '<could not parse>' 35 try: 32 36 cookies = pformat(self.COOKIES) 33 37 except: 34 38 cookies = '<could not parse>' … … 36 40 meta = pformat(self.META) 37 41 except: 38 42 meta = '<could not parse>' 39 return smart_str(u'<ModPythonRequest\npath:%s,\nGET:%s,\nPOST:%s,\n COOKIES:%s,\nMETA:%s>' %43 return smart_str(u'<ModPythonRequest\npath:%s,\nGET:%s,\nPOST:%s,\nPUT:%s,\nCOOKIES:%s,\nMETA:%s>' % 40 44 (self.path, unicode(get), unicode(post), 41 unicode( cookies), unicode(meta)))45 unicode(put), unicode(cookies), unicode(meta))) 42 46 43 47 def get_full_path(self): 44 48 return '%s%s' % (self.path, self._req.args and ('?' + self._req.args) or '') … … 50 54 # mod_python < 3.2.10 doesn't have req.is_https(). 51 55 return self._req.subprocess_env.get('HTTPS', '').lower() in ('on', '1') 52 56 53 def _load_ post_and_files(self):57 def _load_data_and_files(self): 54 58 "Populates self._post and self._files" 55 59 if 'content-type' in self._req.headers_in and self._req.headers_in['content-type'].startswith('multipart'): 56 self._ post, self._files = http.parse_file_upload(self._req.headers_in, self.raw_post_data)60 self._data, self._files = http.parse_file_upload(self._req.headers_in, self.raw_post_data) 57 61 else: 58 self._ post, self._files = http.QueryDict(self.raw_post_data, encoding=self._encoding), datastructures.MultiValueDict()62 self._data, self._files = http.QueryDict(self.raw_post_data, encoding=self._encoding), datastructures.MultiValueDict() 59 63 64 def _load_post_and_files(self): 65 # Populates self._post, preserve backward compatibility. 66 if not hasattr(self, '_data'): 67 self._load_data_and_files() 68 self._post = self._data 69 60 70 def _get_request(self): 61 71 if not hasattr(self, '_request'): 62 self._request = datastructures.MergeDict(self.POST, self. GET)72 self._request = datastructures.MergeDict(self.POST, self.PUT, self.GET) 63 73 return self._request 64 74 65 75 def _get_get(self): 66 76 if not hasattr(self, '_get'): 77 if self._req.args is not None and 'charset' in self._req.args: # for sms 78 self._encoding = self._req.args.split('charset=', 1)[1].split('&', 1)[0].lower() 67 79 self._get = http.QueryDict(self._req.args, encoding=self._encoding) 68 80 return self._get 69 81 … … 72 84 73 85 def _get_post(self): 74 86 if not hasattr(self, '_post'): 75 self._ load_post_and_files()87 self._post = self.DATA 76 88 return self._post 77 89 78 90 def _set_post(self, post): 79 91 self._post = post 80 92 93 def _get_put(self): 94 if not hasattr(self, '_put'): 95 self._put = self.DATA 96 return self._put 97 98 def _set_put(self, put): 99 self._put = put 100 81 101 def _get_cookies(self): 82 102 if not hasattr(self, '_cookies'): 83 103 self._cookies = http.parse_cookie(self._req.headers_in.get('cookie', '')) … … 86 106 def _set_cookies(self, cookies): 87 107 self._cookies = cookies 88 108 109 def _get_data(self): 110 if not hasattr(self, '_data'): 111 self._load_data_and_files() 112 return self._data 113 89 114 def _get_files(self): 90 115 if not hasattr(self, '_files'): 91 self._load_ post_and_files()116 self._load_data_and_files() 92 117 return self._files 93 118 94 119 def _get_meta(self): … … 130 155 131 156 GET = property(_get_get, _set_get) 132 157 POST = property(_get_post, _set_post) 158 PUT = property(_get_put, _set_put) 133 159 COOKIES = property(_get_cookies, _set_cookies) 134 160 FILES = property(_get_files) 161 DATA = property(_get_data) 135 162 META = property(_get_meta) 136 163 REQUEST = property(_get_request) 137 164 raw_post_data = property(_get_raw_post_data)