test_encoding.py (10985B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\lib\cherrypy\test\test_encoding.py 2 import gzip 3 import sys 4 import cherrypy 5 from cherrypy._cpcompat import BytesIO, IncompleteRead, ntob, ntou 6 europoundUnicode = ntou('\x80\xa3') 7 sing = u'\u6bdb\u6cfd\u4e1c: Sing, Little Birdie?' 8 sing8 = sing.encode('utf-8') 9 sing16 = sing.encode('utf-16') 10 from cherrypy.test import helper 11 12 class EncodingTests(helper.CPWebCase): 13 14 def setup_server(): 15 16 class Root: 17 18 def index(self, param): 19 yield europoundUnicode 20 21 index.exposed = True 22 23 def mao_zedong(self): 24 return sing 25 26 mao_zedong.exposed = True 27 28 def utf8(self): 29 return sing8 30 31 utf8.exposed = True 32 utf8._cp_config = {'tools.encode.encoding': 'utf-8'} 33 34 def cookies_and_headers(self): 35 cherrypy.response.cookie['candy'] = 'bar' 36 cherrypy.response.cookie['candy']['domain'] = 'cherrypy.org' 37 cherrypy.response.headers['Some-Header'] = 'My d\xc3\xb6g has fleas' 38 return 'Any content' 39 40 cookies_and_headers.exposed = True 41 42 def reqparams(self, *args, **kwargs): 43 return ntob(', ').join([ ': '.join((k, v)).encode('utf8') for k, v in cherrypy.request.params.items() ]) 44 45 reqparams.exposed = True 46 47 def nontext(self, *args, **kwargs): 48 cherrypy.response.headers['Content-Type'] = 'application/binary' 49 return '\x00\x01\x02\x03' 50 51 nontext.exposed = True 52 nontext._cp_config = {'tools.encode.text_only': False, 53 'tools.encode.add_charset': True} 54 55 class GZIP: 56 57 def index(self): 58 yield 'Hello, world' 59 60 index.exposed = True 61 62 def noshow(self): 63 raise IndexError() 64 yield 'Here be dragons' 65 66 noshow.exposed = True 67 noshow._cp_config = {'tools.encode.on': False} 68 69 def noshow_stream(self): 70 raise IndexError() 71 yield 'Here be dragons' 72 73 noshow_stream.exposed = True 74 noshow_stream._cp_config = {'response.stream': True} 75 76 class Decode: 77 78 def extra_charset(self, *args, **kwargs): 79 return ', '.join([ ': '.join((k, v)) for k, v in cherrypy.request.params.items() ]) 80 81 extra_charset.exposed = True 82 extra_charset._cp_config = {'tools.decode.on': True, 83 'tools.decode.default_encoding': ['utf-16']} 84 85 def force_charset(self, *args, **kwargs): 86 return ', '.join([ ': '.join((k, v)) for k, v in cherrypy.request.params.items() ]) 87 88 force_charset.exposed = True 89 force_charset._cp_config = {'tools.decode.on': True, 90 'tools.decode.encoding': 'utf-16'} 91 92 root = Root() 93 root.gzip = GZIP() 94 root.decode = Decode() 95 cherrypy.tree.mount(root, config={'/gzip': {'tools.gzip.on': True}}) 96 97 setup_server = staticmethod(setup_server) 98 99 def test_query_string_decoding(self): 100 europoundUtf8 = europoundUnicode.encode('utf-8') 101 self.getPage(ntob('/?param=') + europoundUtf8) 102 self.assertBody(europoundUtf8) 103 self.getPage('/reqparams?q=%C2%A3') 104 self.assertBody(ntob('q: \xc2\xa3')) 105 self.getPage('/reqparams?q=%A3') 106 self.assertStatus(404) 107 self.assertErrorPage(404, "The given query string could not be processed. Query strings for this resource must be encoded with 'utf8'.") 108 109 def test_urlencoded_decoding(self): 110 europoundUtf8 = europoundUnicode.encode('utf-8') 111 body = ntob('param=') + europoundUtf8 112 (self.getPage('/', method='POST', headers=[('Content-Type', 'application/x-www-form-urlencoded'), ('Content-Length', str(len(body)))], body=body),) 113 self.assertBody(europoundUtf8) 114 body = ntob('q=\xc2\xa3') 115 (self.getPage('/reqparams', method='POST', headers=[('Content-Type', 'application/x-www-form-urlencoded'), ('Content-Length', str(len(body)))], body=body),) 116 self.assertBody(ntob('q: \xc2\xa3')) 117 body = ntob('\xff\xfeq\x00=\xff\xfe\xa3\x00') 118 (self.getPage('/reqparams', method='POST', headers=[('Content-Type', 'application/x-www-form-urlencoded;charset=utf-16'), ('Content-Length', str(len(body)))], body=body),) 119 self.assertBody(ntob('q: \xc2\xa3')) 120 body = ntob('\xff\xfeq\x00=\xff\xfe\xa3\x00') 121 (self.getPage('/reqparams', method='POST', headers=[('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8'), ('Content-Length', str(len(body)))], body=body),) 122 self.assertStatus(400) 123 self.assertErrorPage(400, "The request entity could not be decoded. The following charsets were attempted: ['utf-8']") 124 125 def test_decode_tool(self): 126 body = ntob('\xff\xfeq\x00=\xff\xfe\xa3\x00') 127 (self.getPage('/decode/extra_charset', method='POST', headers=[('Content-Type', 'application/x-www-form-urlencoded'), ('Content-Length', str(len(body)))], body=body),) 128 self.assertBody(ntob('q: \xc2\xa3')) 129 body = ntob('q=\xc2\xa3') 130 (self.getPage('/decode/extra_charset', method='POST', headers=[('Content-Type', 'application/x-www-form-urlencoded'), ('Content-Length', str(len(body)))], body=body),) 131 self.assertBody(ntob('q: \xc2\xa3')) 132 body = ntob('q=\xc2\xa3') 133 (self.getPage('/decode/force_charset', method='POST', headers=[('Content-Type', 'application/x-www-form-urlencoded'), ('Content-Length', str(len(body)))], body=body),) 134 self.assertErrorPage(400, "The request entity could not be decoded. The following charsets were attempted: ['utf-16']") 135 136 def test_multipart_decoding(self): 137 body = ntob('\r\n'.join(['--X', 138 'Content-Type: text/plain;charset=utf-16', 139 'Content-Disposition: form-data; name="text"', 140 '', 141 '\xff\xfea\x00b\x00\x1c c\x00', 142 '--X', 143 'Content-Type: text/plain;charset=utf-16', 144 'Content-Disposition: form-data; name="submit"', 145 '', 146 '\xff\xfeC\x00r\x00e\x00a\x00t\x00e\x00', 147 '--X--'])) 148 (self.getPage('/reqparams', method='POST', headers=[('Content-Type', 'multipart/form-data;boundary=X'), ('Content-Length', str(len(body)))], body=body),) 149 self.assertBody(ntob('text: ab\xe2\x80\x9cc, submit: Create')) 150 151 def test_multipart_decoding_no_charset(self): 152 body = ntob('\r\n'.join(['--X', 153 'Content-Disposition: form-data; name="text"', 154 '', 155 '\xe2\x80\x9c', 156 '--X', 157 'Content-Disposition: form-data; name="submit"', 158 '', 159 'Create', 160 '--X--'])) 161 (self.getPage('/reqparams', method='POST', headers=[('Content-Type', 'multipart/form-data;boundary=X'), ('Content-Length', str(len(body)))], body=body),) 162 self.assertBody(ntob('text: \xe2\x80\x9c, submit: Create')) 163 164 def test_multipart_decoding_no_successful_charset(self): 165 body = ntob('\r\n'.join(['--X', 166 'Content-Disposition: form-data; name="text"', 167 '', 168 '\xff\xfea\x00b\x00\x1c c\x00', 169 '--X', 170 'Content-Disposition: form-data; name="submit"', 171 '', 172 '\xff\xfeC\x00r\x00e\x00a\x00t\x00e\x00', 173 '--X--'])) 174 (self.getPage('/reqparams', method='POST', headers=[('Content-Type', 'multipart/form-data;boundary=X'), ('Content-Length', str(len(body)))], body=body),) 175 self.assertStatus(400) 176 self.assertErrorPage(400, "The request entity could not be decoded. The following charsets were attempted: ['us-ascii', 'utf-8']") 177 178 def test_nontext(self): 179 self.getPage('/nontext') 180 self.assertHeader('Content-Type', 'application/binary;charset=utf-8') 181 self.assertBody('\x00\x01\x02\x03') 182 183 def testEncoding(self): 184 self.getPage('/mao_zedong') 185 self.assertBody(sing8) 186 self.getPage('/mao_zedong', [('Accept-Charset', 'utf-16')]) 187 self.assertHeader('Content-Type', 'text/html;charset=utf-16') 188 self.assertBody(sing16) 189 self.getPage('/mao_zedong', [('Accept-Charset', 'iso-8859-1;q=1, utf-16;q=0.5')]) 190 self.assertBody(sing16) 191 self.getPage('/mao_zedong', [('Accept-Charset', '*;q=1, utf-7;q=.2')]) 192 self.assertBody(sing8) 193 self.getPage('/mao_zedong', [('Accept-Charset', 'iso-8859-1, *;q=0')]) 194 self.assertStatus('406 Not Acceptable') 195 self.assertInBody('Your client sent this Accept-Charset header: iso-8859-1, *;q=0. We tried these charsets: iso-8859-1.') 196 self.getPage('/mao_zedong', [('Accept-Charset', 'us-ascii, ISO-8859-1, x-mac-ce')]) 197 self.assertStatus('406 Not Acceptable') 198 self.assertInBody('Your client sent this Accept-Charset header: us-ascii, ISO-8859-1, x-mac-ce. We tried these charsets: ISO-8859-1, us-ascii, x-mac-ce.') 199 self.getPage('/utf8') 200 self.assertBody(sing8) 201 self.getPage('/utf8', [('Accept-Charset', 'us-ascii, ISO-8859-1')]) 202 self.assertStatus('406 Not Acceptable') 203 204 def testGzip(self): 205 zbuf = BytesIO() 206 zfile = gzip.GzipFile(mode='wb', fileobj=zbuf, compresslevel=9) 207 zfile.write(ntob('Hello, world')) 208 zfile.close() 209 self.getPage('/gzip/', headers=[('Accept-Encoding', 'gzip')]) 210 self.assertInBody(zbuf.getvalue()[:3]) 211 self.assertHeader('Vary', 'Accept-Encoding') 212 self.assertHeader('Content-Encoding', 'gzip') 213 self.getPage('/gzip/', headers=[('Accept-Encoding', 'identity')]) 214 self.assertHeader('Vary', 'Accept-Encoding') 215 self.assertNoHeader('Content-Encoding') 216 self.assertBody('Hello, world') 217 self.getPage('/gzip/', headers=[('Accept-Encoding', 'gzip;q=0')]) 218 self.assertHeader('Vary', 'Accept-Encoding') 219 self.assertNoHeader('Content-Encoding') 220 self.assertBody('Hello, world') 221 self.getPage('/gzip/', headers=[('Accept-Encoding', '*;q=0')]) 222 self.assertStatus(406) 223 self.assertNoHeader('Content-Encoding') 224 self.assertErrorPage(406, 'identity, gzip') 225 self.getPage('/gzip/noshow', headers=[('Accept-Encoding', 'gzip')]) 226 self.assertNoHeader('Content-Encoding') 227 self.assertStatus(500) 228 self.assertErrorPage(500, pattern='IndexError\n') 229 if cherrypy.server.protocol_version == 'HTTP/1.0' or getattr(cherrypy.server, 'using_apache', False): 230 self.getPage('/gzip/noshow_stream', headers=[('Accept-Encoding', 'gzip')]) 231 self.assertHeader('Content-Encoding', 'gzip') 232 self.assertInBody('\x1f\x8b\x08\x00') 233 else: 234 self.assertRaises((ValueError, IncompleteRead), self.getPage, '/gzip/noshow_stream', headers=[('Accept-Encoding', 'gzip')]) 235 236 def test_UnicodeHeaders(self): 237 self.getPage('/cookies_and_headers') 238 self.assertBody('Any content')