diff --git a/django/test/client.py b/django/test/client.py
index 8fd765e..6d12321 100644
a
|
b
|
class FakePayload(object):
|
43 | 43 | length. This makes sure that views can't do anything under the test client |
44 | 44 | that wouldn't work in Real Life. |
45 | 45 | """ |
46 | | def __init__(self, content): |
47 | | self.__content = BytesIO(content) |
48 | | self.__len = len(content) |
| 46 | def __init__(self, content=None): |
| 47 | self.__content = BytesIO() |
| 48 | self.__len = 0 |
| 49 | self.read_started = False |
| 50 | if content is not None: |
| 51 | self.write(content) |
| 52 | |
| 53 | def __len__(self): |
| 54 | return self.__len |
49 | 55 | |
50 | 56 | def read(self, num_bytes=None): |
| 57 | if not self.read_started: |
| 58 | self.__content.seek(0) |
| 59 | self.read_started = True |
51 | 60 | if num_bytes is None: |
52 | 61 | num_bytes = self.__len or 0 |
53 | 62 | assert self.__len >= num_bytes, "Cannot read more than the available bytes from the HTTP incoming data." |
… |
… |
class FakePayload(object):
|
55 | 64 | self.__len -= num_bytes |
56 | 65 | return content |
57 | 66 | |
| 67 | def write(self, content): |
| 68 | if self.read_started: |
| 69 | raise ValueError("Unable to write a payload after he's been read") |
| 70 | content = force_bytes(content) |
| 71 | self.__content.write(content) |
| 72 | self.__len += len(content) |
| 73 | |
58 | 74 | |
59 | 75 | class ClientHandler(BaseHandler): |
60 | 76 | """ |
diff --git a/tests/regressiontests/file_uploads/tests.py b/tests/regressiontests/file_uploads/tests.py
index 2a1ec7d..918f77d 100644
a
|
b
|
class FileUploadTests(TestCase):
|
62 | 62 | |
63 | 63 | def test_base64_upload(self): |
64 | 64 | test_string = "This data will be transmitted base64-encoded." |
65 | | payload = "\r\n".join([ |
| 65 | payload = client.FakePayload("\r\n".join([ |
66 | 66 | '--' + client.BOUNDARY, |
67 | 67 | 'Content-Disposition: form-data; name="file"; filename="test.txt"', |
68 | 68 | 'Content-Type: application/octet-stream', |
69 | 69 | 'Content-Transfer-Encoding: base64', |
70 | | '', |
71 | | base64.b64encode(force_bytes(test_string)).decode('ascii'), |
72 | | '--' + client.BOUNDARY + '--', |
73 | | '', |
74 | | ]).encode('utf-8') |
| 70 | '',])) |
| 71 | payload.write(b"\r\n" + base64.b64encode(force_bytes(test_string)) + b"\r\n") |
| 72 | payload.write('--' + client.BOUNDARY + '--\r\n') |
75 | 73 | r = { |
76 | 74 | 'CONTENT_LENGTH': len(payload), |
77 | 75 | 'CONTENT_TYPE': client.MULTIPART_CONTENT, |
78 | 76 | 'PATH_INFO': "/file_uploads/echo_content/", |
79 | 77 | 'REQUEST_METHOD': 'POST', |
80 | | 'wsgi.input': client.FakePayload(payload), |
| 78 | 'wsgi.input': payload, |
81 | 79 | } |
82 | 80 | response = self.client.request(**r) |
83 | 81 | received = json.loads(response.content.decode('utf-8')) |
… |
… |
class FileUploadTests(TestCase):
|
126 | 124 | "../..\\hax0rd.txt" # Relative path, mixed. |
127 | 125 | ] |
128 | 126 | |
129 | | payload = [] |
| 127 | payload = client.FakePayload() |
130 | 128 | for i, name in enumerate(scary_file_names): |
131 | | payload.extend([ |
| 129 | payload.write('\r\n'.join([ |
132 | 130 | '--' + client.BOUNDARY, |
133 | 131 | 'Content-Disposition: form-data; name="file%s"; filename="%s"' % (i, name), |
134 | 132 | 'Content-Type: application/octet-stream', |
135 | 133 | '', |
136 | | 'You got pwnd.' |
137 | | ]) |
138 | | payload.extend([ |
139 | | '--' + client.BOUNDARY + '--', |
140 | | '', |
141 | | ]) |
| 134 | 'You got pwnd.\r\n' |
| 135 | ])) |
| 136 | payload.write('\r\n--' + client.BOUNDARY + '--\r\n') |
142 | 137 | |
143 | | payload = "\r\n".join(payload).encode('utf-8') |
144 | 138 | r = { |
145 | 139 | 'CONTENT_LENGTH': len(payload), |
146 | 140 | 'CONTENT_TYPE': client.MULTIPART_CONTENT, |
147 | 141 | 'PATH_INFO': "/file_uploads/echo/", |
148 | 142 | 'REQUEST_METHOD': 'POST', |
149 | | 'wsgi.input': client.FakePayload(payload), |
| 143 | 'wsgi.input': payload, |
150 | 144 | } |
151 | 145 | response = self.client.request(**r) |
152 | 146 | |
… |
… |
class FileUploadTests(TestCase):
|
159 | 153 | def test_filename_overflow(self): |
160 | 154 | """File names over 256 characters (dangerous on some platforms) get fixed up.""" |
161 | 155 | name = "%s.txt" % ("f"*500) |
162 | | payload = "\r\n".join([ |
| 156 | payload = client.FakePayload("\r\n".join([ |
163 | 157 | '--' + client.BOUNDARY, |
164 | 158 | 'Content-Disposition: form-data; name="file"; filename="%s"' % name, |
165 | 159 | 'Content-Type: application/octet-stream', |
… |
… |
class FileUploadTests(TestCase):
|
167 | 161 | 'Oops.' |
168 | 162 | '--' + client.BOUNDARY + '--', |
169 | 163 | '', |
170 | | ]).encode('utf-8') |
| 164 | ])) |
171 | 165 | r = { |
172 | 166 | 'CONTENT_LENGTH': len(payload), |
173 | 167 | 'CONTENT_TYPE': client.MULTIPART_CONTENT, |
174 | 168 | 'PATH_INFO': "/file_uploads/echo/", |
175 | 169 | 'REQUEST_METHOD': 'POST', |
176 | | 'wsgi.input': client.FakePayload(payload), |
| 170 | 'wsgi.input': payload, |
177 | 171 | } |
178 | 172 | got = json.loads(self.client.request(**r).content.decode('utf-8')) |
179 | 173 | self.assertTrue(len(got['file']) < 256, "Got a long file name (%s characters)." % len(got['file'])) |
… |
… |
class FileUploadTests(TestCase):
|
184 | 178 | attempt to read beyond the end of the stream, and simply will handle |
185 | 179 | the part that can be parsed gracefully. |
186 | 180 | """ |
187 | | payload = "\r\n".join([ |
| 181 | payload_str = "\r\n".join([ |
188 | 182 | '--' + client.BOUNDARY, |
189 | 183 | 'Content-Disposition: form-data; name="file"; filename="foo.txt"', |
190 | 184 | 'Content-Type: application/octet-stream', |
… |
… |
class FileUploadTests(TestCase):
|
192 | 186 | 'file contents' |
193 | 187 | '--' + client.BOUNDARY + '--', |
194 | 188 | '', |
195 | | ]).encode('utf-8') |
196 | | payload = payload[:-10] |
| 189 | ]) |
| 190 | payload = client.FakePayload(payload_str[:-10]) |
197 | 191 | r = { |
198 | 192 | 'CONTENT_LENGTH': len(payload), |
199 | 193 | 'CONTENT_TYPE': client.MULTIPART_CONTENT, |
200 | 194 | 'PATH_INFO': '/file_uploads/echo/', |
201 | 195 | 'REQUEST_METHOD': 'POST', |
202 | | 'wsgi.input': client.FakePayload(payload), |
| 196 | 'wsgi.input': payload, |
203 | 197 | } |
204 | 198 | got = json.loads(self.client.request(**r).content.decode('utf-8')) |
205 | 199 | self.assertEqual(got, {}) |