def __call__(self, env, start_response): """ Main hook into the WSGI paste.deploy filter/app pipeline. :param env: The WSGI environment dict. :param start_response: The WSGI start_response hook. :returns: Response as per WSGI. """ if env["REQUEST_METHOD"] == "POST": try: content_type, attrs = parse_content_disposition(env.get("CONTENT_TYPE") or "") if content_type == "multipart/form-data" and "boundary" in attrs: http_user_agent = "%s FormPost" % (env.get("HTTP_USER_AGENT", "")) env["HTTP_USER_AGENT"] = http_user_agent.strip() status, headers, body = self._translate_form(env, attrs["boundary"]) start_response(status, headers) return [body] except MimeInvalid: body = "FormPost: invalid starting boundary" start_response("400 Bad Request", (("Content-Type", "text/plain"), ("Content-Length", str(len(body))))) return [body] except (FormInvalid, EOFError) as err: body = "FormPost: %s" % err start_response("400 Bad Request", (("Content-Type", "text/plain"), ("Content-Length", str(len(body))))) return [body] except FormUnauthorized as err: message = "FormPost: %s" % str(err).title() return HTTPUnauthorized(body=message)(env, start_response) return self.app(env, start_response)
def __call__(self, env, start_response): """ Main hook into the WSGI paste.deploy filter/app pipeline. :param env: The WSGI environment dict. :param start_response: The WSGI start_response hook. :returns: Response as per WSGI. """ if env['REQUEST_METHOD'] == 'POST': try: content_type, attrs = \ parse_content_disposition(env.get('CONTENT_TYPE') or '') if content_type == 'multipart/form-data' and \ 'boundary' in attrs: http_user_agent = "%s FormPost" % (env.get( 'HTTP_USER_AGENT', '')) env['HTTP_USER_AGENT'] = http_user_agent.strip() status, headers, body = self._translate_form( env, attrs['boundary']) start_response(status, headers) return [body] except (FormInvalid, MimeInvalid, EOFError) as err: body = 'FormPost: %s' % err start_response('400 Bad Request', (('Content-Type', 'text/plain'), ('Content-Length', str(len(body))))) return [body] except FormUnauthorized as err: message = 'FormPost: %s' % str(err).title() return HTTPUnauthorized(body=message)(env, start_response) return self.app(env, start_response)
def __call__(self, env, start_response): """ Main hook into the WSGI paste.deploy filter/app pipeline. :param env: The WSGI environment dict. :param start_response: The WSGI start_response hook. :returns: Response as per WSGI. """ if env['REQUEST_METHOD'] == 'POST': try: content_type, attrs = \ parse_content_disposition(env.get('CONTENT_TYPE') or '') if content_type == 'multipart/form-data' and \ 'boundary' in attrs: http_user_agent = "%s FormPost" % ( env.get('HTTP_USER_AGENT', '')) env['HTTP_USER_AGENT'] = http_user_agent.strip() status, headers, body = self._translate_form( env, attrs['boundary']) start_response(status, headers) return [body] except (FormInvalid, MimeInvalid, EOFError) as err: body = 'FormPost: %s' % err start_response( '400 Bad Request', (('Content-Type', 'text/plain'), ('Content-Length', str(len(body))))) return [body] except FormUnauthorized as err: message = 'FormPost: %s' % str(err).title() return HTTPUnauthorized(body=message)( env, start_response) return self.app(env, start_response)
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) 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 = rfc822.Message(fp, 0) disp, attrs = parse_content_disposition(hdrs.getheader("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" status, subheaders, message = self._perform_subrequest(env, attributes, fp, keys) if status[:1] != "2": break else: data = "" 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 "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))]) 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 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