# HG changeset patch # User paulb # Date 1093650711 0 # Node ID 6448ed817132558b43729754ed7d7516f2e48afe # Parent 3ae86352b0234aa87750d009b85d0795cd699d82 [project @ 2004-08-27 23:51:51 by paulb] Fixed content type interpretation. Fixed file upload support (not currently working for JavaServlet). diff -r 3ae86352b023 -r 6448ed817132 WebStack/BaseHTTPRequestHandler.py --- a/WebStack/BaseHTTPRequestHandler.py Fri Aug 27 23:51:02 2004 +0000 +++ b/WebStack/BaseHTTPRequestHandler.py Fri Aug 27 23:51:51 2004 +0000 @@ -207,7 +207,10 @@ the default encoding is to be overridden. Returns a dictionary mapping field names to lists of values (even if a - single value is associated with any given field name). + single value is associated with any given field name). Each value is + either a Unicode object (representing a simple form field, for example) + or a file-like object (representing a file upload form field, for + example). """ encoding = self.get_content_type().charset or encoding or "iso-8859-1" @@ -227,7 +230,10 @@ for field_name in self.storage_body.keys(): fields[field_name] = [] for field_value in self.storage_body.getlist(field_name): - fields[field_name].append(unicode(field_value, encoding)) + if hasattr(field_value, "file"): + fields[field_name].append(field_value.file) + else: + fields[field_name].append(unicode(field_value, encoding)) return fields def get_user(self): diff -r 3ae86352b023 -r 6448ed817132 WebStack/CGI.py --- a/WebStack/CGI.py Fri Aug 27 23:51:02 2004 +0000 +++ b/WebStack/CGI.py Fri Aug 27 23:51:51 2004 +0000 @@ -201,7 +201,10 @@ the default encoding is to be overridden. Returns a dictionary mapping field names to lists of values (even if a - single value is associated with any given field name). + single value is associated with any given field name). Each value is + either a Unicode object (representing a simple form field, for example) + or a file-like object (representing a file upload form field, for + example). """ encoding = self.get_content_type().charset or encoding or "iso-8859-1" @@ -220,7 +223,10 @@ for field_name in self.storage_body.keys(): fields[field_name] = [] for field_value in self.storage_body.getlist(field_name): - fields[field_name].append(unicode(field_value, encoding)) + if hasattr(field_value, "file"): + fields[field_name].append(field_value.file) + else: + fields[field_name].append(unicode(field_value, encoding)) return fields def get_user(self): diff -r 3ae86352b023 -r 6448ed817132 WebStack/Generic.py --- a/WebStack/Generic.py Fri Aug 27 23:51:02 2004 +0000 +++ b/WebStack/Generic.py Fri Aug 27 23:51:51 2004 +0000 @@ -19,9 +19,10 @@ "A container for content type information." - def __init__(self, content_type, charset=None): + def __init__(self, content_type, charset=None, attributes=None): self.content_type = content_type self.charset = charset + self.attributes = attributes class Transaction: @@ -51,11 +52,22 @@ if content_type_field is None: return ContentType(None, "iso-8859-1") - t = content_type_field.split("; charset=") - if len(t) == 1: - return ContentType(t[0], "iso-8859-1") - else: - return ContentType(t[0], t[1]) + l = content_type_field.split(";") + content_type_attributes = [] + content_type_charset = "iso-8859-1" + + # Find the charset and remember all other attributes. + + content_type_str, attributes = l[0].strip(), l[1:] + + for attribute in attributes: + t = attribute.strip().split("=") + if t[0] == "charset" and len(t) > 1: + content_type_charset = t[1] + else: + content_type_attributes.append(t) + + return ContentType(content_type_str, content_type_charset, content_type_attributes) def format_content_type(self, content_type): @@ -242,7 +254,10 @@ the default encoding is to be overridden. Returns a dictionary mapping field names to lists of values (even if a - single value is associated with any given field name). + single value is associated with any given field name). Each value is + either a Unicode object (representing a simple form field, for example) + or a file-like object (representing a file upload form field, for + example). """ raise NotImplementedError, "get_fields_from_body" diff -r 3ae86352b023 -r 6448ed817132 WebStack/JavaServlet.py --- a/WebStack/JavaServlet.py Fri Aug 27 23:51:02 2004 +0000 +++ b/WebStack/JavaServlet.py Fri Aug 27 23:51:51 2004 +0000 @@ -8,6 +8,7 @@ from StringIO import StringIO from Helpers.Request import Cookie import javax.servlet.http.Cookie +from cgi import FieldStorage class Stream: @@ -65,6 +66,10 @@ cookie_name = cookie.getName() self.cookies_in[cookie_name] = Cookie(cookie_name, cookie.getValue()) + # Cached information. + + self.storage_body = None + def commit(self): """ @@ -231,18 +236,63 @@ the default encoding is to be overridden. Returns a dictionary mapping field names to lists of values (even if a - single value is associated with any given field name). + single value is associated with any given field name). Each value is + either a Unicode object (representing a simple form field, for example) + or a file-like object (representing a file upload form field, for + example). NOTE: There may not be a reliable means of extracting only the fields NOTE: from the message body. Moreover, the encoding of the fields may NOTE: not be pertinent. """ - parameter_map = self.request.getParameterMap() fields = {} - if parameter_map: - for key in parameter_map.keySet(): - fields[key] = parameter_map[key] + + # Where the content type is "multipart/form-data", we use the + # FieldStorage class from the standard library. Otherwise, we use the + # Servlet API's parameter access methods. + + if self.get_content_type() and self.get_content_type().content_type == "multipart/form-data": + + # NOTE: Taken from WebStack.CGI.get_fields_from_body. + + if self.storage_body is None: + self.storage_body = FieldStorage(fp=self.get_request_stream(), headers=self.get_headers(), + environ={"REQUEST_METHOD" : self.get_request_method()}, keep_blank_values=1) + + # Avoid strange design issues with FieldStorage by checking the internal + # field list directly. + + if self.storage_body.list is not None: + + # Traverse the storage, finding each field value. + + for field_name in self.storage_body.keys(): + + # NOTE: Jython 2.1 does not have a cgi module with a + # NOTE: FieldStorage.getlist implementation. + + field_values = self.storage_body.getvalue(field_name) + + if type(field_values) == type([]): + fields[field_name] = [] + for field_value in field_values: + if hasattr(field_value, "file"): + fields[field_name].append(field_value.file) + else: + fields[field_name].append(field_value) + else: + if hasattr(field_values, "file"): + fields[field_name] = [field_values.file] + else: + fields[field_name] = [field_values] + + else: + parameter_map = self.request.getParameterMap() + if parameter_map: + for key in parameter_map.keySet(): + fields[key] = parameter_map[key] + return fields def get_user(self): diff -r 3ae86352b023 -r 6448ed817132 WebStack/ModPython.py --- a/WebStack/ModPython.py Fri Aug 27 23:51:02 2004 +0000 +++ b/WebStack/ModPython.py Fri Aug 27 23:51:51 2004 +0000 @@ -161,7 +161,10 @@ the default encoding is to be overridden. Returns a dictionary mapping field names to lists of values (even if a - single value is associated with any given field name). + single value is associated with any given field name). Each value is + either a Unicode object (representing a simple form field, for example) + or a file-like object (representing a file upload form field, for + example). The mod_python.util.FieldStorage class may augment the fields from the body with fields found in the path. @@ -178,7 +181,10 @@ for field in self.storage_body.list: if not fields.has_key(field.name): fields[field.name] = [] - fields[field.name].append(unicode(field.value, encoding)) + if hasattr(field.value, "file"): + fields[field.name].append(field.value.file) + else: + fields[field.name].append(unicode(field.value, encoding)) return fields def get_user(self): diff -r 3ae86352b023 -r 6448ed817132 WebStack/Twisted.py --- a/WebStack/Twisted.py Fri Aug 27 23:51:02 2004 +0000 +++ b/WebStack/Twisted.py Fri Aug 27 23:51:51 2004 +0000 @@ -156,7 +156,10 @@ the default encoding is to be overridden. Returns a dictionary mapping field names to lists of values (even if a - single value is associated with any given field name). + single value is associated with any given field name). Each value is + either a Unicode object (representing a simple form field, for example) + or a file-like object (representing a file upload form field, for + example). """ encoding = self.get_content_type().charset or encoding or "iso-8859-1" @@ -164,7 +167,10 @@ for field_name, field_values in self.trans.args.items(): fields[field_name] = [] for field_value in field_values: - fields[field_name].append(unicode(field_value, encoding)) + if hasattr(field_value, "file"): + fields[field_name].append(field_value.file) + else: + fields[field_name].append(unicode(field_value, encoding)) return fields def get_user(self): diff -r 3ae86352b023 -r 6448ed817132 WebStack/Webware.py --- a/WebStack/Webware.py Fri Aug 27 23:51:02 2004 +0000 +++ b/WebStack/Webware.py Fri Aug 27 23:51:51 2004 +0000 @@ -172,7 +172,10 @@ the default encoding is to be overridden. Returns a dictionary mapping field names to lists of values (even if a - single value is associated with any given field name). + single value is associated with any given field name). Each value is + either a Unicode object (representing a simple form field, for example) + or a file-like object (representing a file upload form field, for + example). """ encoding = self.get_content_type().charset or encoding or "iso-8859-1" @@ -184,9 +187,15 @@ if type(field_values) == type([]): fields[field_name] = [] for field_value in field_values: - fields[field_name].append(unicode(field_value, encoding)) + if hasattr(field_value, "file"): + fields[field_name].append(field_value.file) + else: + fields[field_name].append(unicode(field_value, encoding)) else: - fields[field_name] = [unicode(field_values, encoding)] + if hasattr(field_values, "file"): + fields[field_name] = [field_values.file] + else: + fields[field_name] = [unicode(field_values, encoding)] return fields def get_user(self): diff -r 3ae86352b023 -r 6448ed817132 WebStack/Zope.py --- a/WebStack/Zope.py Fri Aug 27 23:51:02 2004 +0000 +++ b/WebStack/Zope.py Fri Aug 27 23:51:51 2004 +0000 @@ -10,6 +10,7 @@ from Helpers import Environment from Helpers.Request import Cookie from Helpers.Response import ConvertingStream +from ZPublisher.HTTPRequest import FileUpload class Transaction(Generic.Transaction): @@ -174,7 +175,10 @@ the default encoding is to be overridden. Returns a dictionary mapping field names to lists of values (even if a - single value is associated with any given field name). + single value is associated with any given field name). Each value is + either a Unicode object (representing a simple form field, for example) + or a file-like object (representing a file upload form field, for + example). NOTE: Zope doesn't distinguish between path and body fields. """ @@ -186,7 +190,10 @@ for field_name, field_values in self.get_fields_from_path().items(): fields[field_name] = [] for field_value in field_values: - fields[field_name].append(unicode(field_value, encoding)) + if isinstance(field_value, FileUpload): + fields[field_name].append(field_value) + else: + fields[field_name].append(unicode(field_value, encoding)) return fields def get_user(self):