def iter_mime_headers_and_bodies(wsgi_input, mime_boundary, read_chunk_size): mime_documents_iter = iter_multipart_mime_documents( wsgi_input, mime_boundary, read_chunk_size) for file_like in mime_documents_iter: hdrs = parse_mime_headers(file_like) yield (hdrs, file_like)
def _translate_form(self, env, boundary): """ Translates the form data into subrequests and issues a response. :param env: The WSGI environment dict. :param boundary: The MIME type boundary to look for. :returns: status_line, headers_list, body """ keys = self._get_keys(env) if six.PY3: boundary = boundary.encode('utf-8') status = message = '' attributes = {} file_attributes = {} subheaders = [] file_count = 0 for fp in iter_multipart_mime_documents( env['wsgi.input'], boundary, read_chunk_size=READ_CHUNK_SIZE): hdrs = parse_mime_headers(fp) disp, attrs = parse_content_disposition( hdrs.get('Content-Disposition', '')) if disp == 'form-data' and attrs.get('filename'): file_count += 1 try: if file_count > int(attributes.get('max_file_count') or 0): status = '400 Bad Request' message = 'max file count exceeded' break except ValueError: raise FormInvalid('max_file_count not an integer') file_attributes = attributes.copy() file_attributes['filename'] = attrs['filename'] or 'filename' if 'content-type' not in attributes and 'content-type' in hdrs: file_attributes['content-type'] = \ hdrs['Content-Type'] or 'application/octet-stream' if 'content-encoding' not in attributes and \ 'content-encoding' in hdrs: file_attributes['content-encoding'] = \ hdrs['Content-Encoding'] status, subheaders = \ self._perform_subrequest(env, file_attributes, fp, keys) if not status.startswith('2'): break else: data = b'' mxln = MAX_VALUE_LENGTH while mxln: chunk = fp.read(mxln) if not chunk: break mxln -= len(chunk) data += chunk while fp.read(READ_CHUNK_SIZE): pass if six.PY3: data = data.decode('utf-8') if 'name' in attrs: attributes[attrs['name'].lower()] = data.rstrip('\r\n--') if not status: status = '400 Bad Request' message = 'no files to process' headers = [(k, v) for k, v in subheaders if k.lower().startswith('access-control')] redirect = attributes.get('redirect') if not redirect: body = status if message: body = status + '\r\nFormPost: ' + message.title() headers.extend([('Content-Type', 'text/plain'), ('Content-Length', len(body))]) if six.PY3: body = body.encode('utf-8') return status, headers, body status = status.split(' ', 1)[0] if '?' in redirect: redirect += '&' else: redirect += '?' redirect += 'status=%s&message=%s' % (quote(status), quote(message)) body = '<html><body><p><a href="%s">' \ 'Click to continue...</a></p></body></html>' % redirect if six.PY3: body = body.encode('utf-8') headers.extend( [('Location', redirect), ('Content-Length', str(len(body)))]) return '303 See Other', headers, body
def _translate_form(self, env, boundary): """ Translates the form data into subrequests and issues a response. :param env: The WSGI environment dict. :param boundary: The MIME type boundary to look for. :returns: status_line, headers_list, body """ keys = self._get_keys(env) if six.PY3: boundary = boundary.encode('utf-8') status = message = '' attributes = {} subheaders = [] file_count = 0 for fp in iter_multipart_mime_documents( env['wsgi.input'], boundary, read_chunk_size=READ_CHUNK_SIZE): hdrs = parse_mime_headers(fp) disp, attrs = parse_content_disposition( hdrs.get('Content-Disposition', '')) if disp == 'form-data' and attrs.get('filename'): file_count += 1 try: if file_count > int(attributes.get('max_file_count') or 0): status = '400 Bad Request' message = 'max file count exceeded' break except ValueError: raise FormInvalid('max_file_count not an integer') attributes['filename'] = attrs['filename'] or 'filename' if 'content-type' not in attributes and 'content-type' in hdrs: attributes['content-type'] = \ hdrs['Content-Type'] or 'application/octet-stream' if 'content-encoding' not in attributes and \ 'content-encoding' in hdrs: attributes['content-encoding'] = hdrs['Content-Encoding'] status, subheaders = \ self._perform_subrequest(env, attributes, fp, keys) if not status.startswith('2'): break else: data = b'' mxln = MAX_VALUE_LENGTH while mxln: chunk = fp.read(mxln) if not chunk: break mxln -= len(chunk) data += chunk while fp.read(READ_CHUNK_SIZE): pass if six.PY3: data = data.decode('utf-8') if 'name' in attrs: attributes[attrs['name'].lower()] = data.rstrip('\r\n--') if not status: status = '400 Bad Request' message = 'no files to process' headers = [(k, v) for k, v in subheaders if k.lower().startswith('access-control')] redirect = attributes.get('redirect') if not redirect: body = status if message: body = status + '\r\nFormPost: ' + message.title() headers.extend([('Content-Type', 'text/plain'), ('Content-Length', len(body))]) if six.PY3: body = body.encode('utf-8') return status, headers, body status = status.split(' ', 1)[0] if '?' in redirect: redirect += '&' else: redirect += '?' redirect += 'status=%s&message=%s' % (quote(status), quote(message)) body = '<html><body><p><a href="%s">' \ 'Click to continue...</a></p></body></html>' % redirect if six.PY3: body = body.encode('utf-8') headers.extend( [('Location', redirect), ('Content-Length', str(len(body)))]) return '303 See Other', headers, body