1.1 --- a/WebStack/Helpers/Request.py Fri Aug 26 18:10:52 2005 +0000
1.2 +++ b/WebStack/Helpers/Request.py Fri Aug 26 18:11:48 2005 +0000
1.3 @@ -87,6 +87,71 @@
1.4
1.5 self.stream.close()
1.6
1.7 +class HeaderValue:
1.8 +
1.9 + "A container for header information."
1.10 +
1.11 + def __init__(self, principal_value, **attributes):
1.12 +
1.13 + """
1.14 + Initialise the container with the given 'principal_value' and optional
1.15 + keyword attributes representing the key=value pairs which accompany the
1.16 + 'principal_value'.
1.17 + """
1.18 +
1.19 + self.principal_value = principal_value
1.20 + self.attributes = attributes
1.21 +
1.22 + def __getattr__(self, name):
1.23 + if self.attributes.has_key(name):
1.24 + return self.attributes[name]
1.25 + else:
1.26 + raise AttributeError, name
1.27 +
1.28 + def __str__(self):
1.29 +
1.30 + """
1.31 + Format the header value object, producing a string suitable for the
1.32 + response header field.
1.33 + """
1.34 +
1.35 + l = []
1.36 + if self.principal_value:
1.37 + l.append(self.principal_value)
1.38 + for name, value in self.attributes.items():
1.39 + l.append("; ")
1.40 + l.append("%s=%s" % (name, value))
1.41 +
1.42 + # Make sure that only ASCII is used.
1.43 +
1.44 + return "".join(l).encode("US-ASCII")
1.45 +
1.46 +class ContentType(HeaderValue):
1.47 +
1.48 + "A container for content type information."
1.49 +
1.50 + def __init__(self, media_type, charset=None, **attributes):
1.51 +
1.52 + """
1.53 + Initialise the container with the given 'media_type', an optional
1.54 + 'charset', and optional keyword attributes representing the key=value
1.55 + pairs which qualify content types.
1.56 + """
1.57 +
1.58 + if charset is not None:
1.59 + attributes["charset"] = charset
1.60 + HeaderValue.__init__(self, media_type, **attributes)
1.61 +
1.62 + def __getattr__(self, name):
1.63 + if name == "media_type":
1.64 + return self.principal_value
1.65 + elif name == "charset":
1.66 + return self.attributes.get("charset")
1.67 + elif self.attributes.has_key(name):
1.68 + return self.attributes[name]
1.69 + else:
1.70 + raise AttributeError, name
1.71 +
1.72 class Cookie:
1.73
1.74 """
1.75 @@ -98,6 +163,66 @@
1.76 self.name = name
1.77 self.value = value
1.78
1.79 +class FileContent:
1.80 +
1.81 + """
1.82 + A simple class representing uploaded file content. This is useful in holding
1.83 + metadata as well as being an indicator of such content in environments such
1.84 + as Jython where it is not trivial to differentiate between plain strings and
1.85 + Unicode in a fashion also applicable to CPython.
1.86 + """
1.87 +
1.88 + def __init__(self, content, headers=None):
1.89 +
1.90 + """
1.91 + Initialise the object with 'content' and optional 'headers' describing
1.92 + the content.
1.93 + """
1.94 +
1.95 + self.content = content
1.96 + self.headers = headers or {}
1.97 +
1.98 + def __str__(self):
1.99 + return self.content
1.100 +
1.101 +def parse_header_value(header_class, header_value_str):
1.102 +
1.103 + """
1.104 + Create an object of the given 'header_class' by determining the details
1.105 + of the given 'header_value_str' - a string containing the value of a
1.106 + particular header.
1.107 + """
1.108 +
1.109 + if header_value_str is None:
1.110 + return header_class(None)
1.111 +
1.112 + l = header_value_str.split(";")
1.113 + attributes = {}
1.114 +
1.115 + # Find the attributes.
1.116 +
1.117 + principal_value, attributes_str = l[0].strip(), l[1:]
1.118 +
1.119 + for attribute_str in attributes_str:
1.120 + t = attribute_str.split("=")
1.121 + if len(t) > 1:
1.122 + name, value = t[0].strip(), t[1].strip()
1.123 + attributes[name] = value
1.124 +
1.125 + return header_class(principal_value, **attributes)
1.126 +
1.127 +def parse_headers(headers):
1.128 +
1.129 + """
1.130 + Parse the given 'headers' dictionary (containing names mapped to values),
1.131 + returing a dictionary mapping names to HeaderValue objects.
1.132 + """
1.133 +
1.134 + new_headers = {}
1.135 + for name, value in headers.items():
1.136 + new_headers[name] = parse_header_value(HeaderValue, value)
1.137 + return new_headers
1.138 +
1.139 def get_storage_items(storage_body):
1.140
1.141 """
1.142 @@ -146,9 +271,9 @@
1.143 # Detect stray FileUpload objects (eg. with Zope).
1.144
1.145 if hasattr(field_value, "read"):
1.146 - return field_value.read()
1.147 + return FileContent(field_value.read(), parse_headers(field_value.headers))
1.148 else:
1.149 - return field_value.value
1.150 + return FileContent(field_value.value, parse_headers(field_value.headers))
1.151 else:
1.152 return get_body_field(field_value, encoding)
1.153