1.1 --- a/WebStack/Generic.py Fri Sep 03 21:35:54 2004 +0000
1.2 +++ b/WebStack/Generic.py Sun Sep 05 11:12:32 2004 +0000
1.3 @@ -15,7 +15,46 @@
1.4 directors.
1.5 """
1.6
1.7 -class ContentType:
1.8 +class HeaderValue:
1.9 +
1.10 + "A container for header information."
1.11 +
1.12 + def __init__(self, principal_value, **attributes):
1.13 +
1.14 + """
1.15 + Initialise the container with the given 'principal_value' and optional
1.16 + keyword attributes representing the key=value pairs which accompany the
1.17 + 'principal_value'.
1.18 + """
1.19 +
1.20 + self.principal_value = principal_value
1.21 + self.attributes = attributes
1.22 +
1.23 + def __getattr__(self, name):
1.24 + if self.attributes.has_key(name):
1.25 + return self.attributes[name]
1.26 + else:
1.27 + raise AttributeError, name
1.28 +
1.29 + def __str__(self):
1.30 +
1.31 + """
1.32 + Format the header value object, producing a string suitable for the
1.33 + response header field.
1.34 + """
1.35 +
1.36 + l = []
1.37 + if self.principal_value:
1.38 + l.append(self.principal_value)
1.39 + for name, value in self.attributes.items():
1.40 + l.append("; ")
1.41 + l.append("%s=%s" % (name, value))
1.42 +
1.43 + # Make sure that only ASCII is used.
1.44 +
1.45 + return "".join(l).encode("US-ASCII")
1.46 +
1.47 +class ContentType(HeaderValue):
1.48
1.49 "A container for content type information."
1.50
1.51 @@ -27,30 +66,19 @@
1.52 pairs which qualify content types.
1.53 """
1.54
1.55 - self.media_type = media_type
1.56 - self.charset = charset
1.57 - self.attributes = attributes
1.58 -
1.59 - def __str__(self):
1.60 -
1.61 - """
1.62 - Format the content type object, producing a string suitable for the
1.63 - response header field.
1.64 - """
1.65 + if charset is not None:
1.66 + attributes["charset"] = charset
1.67 + HeaderValue.__init__(self, media_type, **attributes)
1.68
1.69 - l = []
1.70 - if self.media_type:
1.71 - l.append(self.media_type)
1.72 - if self.charset:
1.73 - l.append("; ")
1.74 - l.append("charset=%s" % self.charset)
1.75 - for name, value in self.attributes.items():
1.76 - l.append("; ")
1.77 - l.append("%s=%s" % (name, value))
1.78 -
1.79 - # Make sure that only ASCII is used.
1.80 -
1.81 - return "".join(l).encode("US-ASCII")
1.82 + def __getattr__(self, name):
1.83 + if name == "media_type":
1.84 + return self.principal_value
1.85 + elif name == "charset":
1.86 + return self.attributes.get("charset")
1.87 + elif self.attributes.has_key(name):
1.88 + return self.attributes[name]
1.89 + else:
1.90 + raise AttributeError, name
1.91
1.92 class Transaction:
1.93
1.94 @@ -74,34 +102,34 @@
1.95
1.96 # Utility methods.
1.97
1.98 - def parse_content_type(self, content_type_field):
1.99 + def parse_header_value(self, header_class, header_value_str):
1.100
1.101 """
1.102 - Determine the content type and charset from the supplied
1.103 - 'content_type_field' string.
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 content_type_field is None:
1.110 - return ContentType(None)
1.111 + if header_value_str is None:
1.112 + return header_class(None)
1.113
1.114 - l = content_type_field.split(";")
1.115 + l = header_value_str.split(";")
1.116 attributes = {}
1.117 - charset = None
1.118
1.119 - # Find the charset and remember all other attributes.
1.120 + # Find the attributes.
1.121
1.122 - media_type, attributes_str = l[0].strip(), l[1:]
1.123 + principal_value, attributes_str = l[0].strip(), l[1:]
1.124
1.125 for attribute_str in attributes_str:
1.126 t = attribute_str.split("=")
1.127 if len(t) > 1:
1.128 name, value = t[0].strip(), t[1].strip()
1.129 - if name == "charset":
1.130 - charset = value
1.131 - else:
1.132 - attributes[name] = value
1.133 + attributes[name] = value
1.134
1.135 - return ContentType(media_type, charset, **attributes)
1.136 + return header_class(principal_value, **attributes)
1.137 +
1.138 + def parse_content_type(self, content_type_field):
1.139 + return self.parse_header_value(ContentType, content_type_field)
1.140
1.141 def format_header_value(self, value):
1.142
2.1 --- a/WebStack/JavaServlet.py Fri Sep 03 21:35:54 2004 +0000
2.2 +++ b/WebStack/JavaServlet.py Sun Sep 05 11:12:32 2004 +0000
2.3 @@ -15,6 +15,7 @@
2.4 import javax.mail.Session
2.5 import java.util.Properties
2.6 import java.net.URLDecoder
2.7 +from WebStack.Generic import HeaderValue
2.8
2.9 class Stream:
2.10
2.11 @@ -511,15 +512,14 @@
2.12
2.13 # Should get: form-data; name="x"
2.14
2.15 - disposition = part.getHeader("Content-Disposition")[0]
2.16 - name = self._get_header_attribute(disposition, "name")
2.17 + disposition = self.parse_header_value(HeaderValue, part.getHeader("Content-Disposition")[0])
2.18
2.19 # Store and optionally convert the field.
2.20
2.21 - if name is not None:
2.22 - if not fields.has_key(name):
2.23 - fields[name] = []
2.24 - fields[name].append(subcontent)
2.25 + if disposition.name is not None:
2.26 + if not fields.has_key(disposition.name[1:-1]):
2.27 + fields[disposition.name[1:-1]] = []
2.28 + fields[disposition.name[1:-1]].append(subcontent)
2.29
2.30 # Otherwise, descend deeper into the multipart hierarchy.
2.31
2.32 @@ -528,15 +528,6 @@
2.33
2.34 return fields
2.35
2.36 - def _get_header_attribute(self, header_value, attribute_name):
2.37 - parts = header_value.split(";")
2.38 - if len(parts) > 1:
2.39 - for attribute in parts[1:]:
2.40 - t = attribute.split("=")
2.41 - if len(t) == 2 and t[0].strip() == attribute_name:
2.42 - return t[1].strip()[1:-1]
2.43 - return None
2.44 -
2.45 class Session:
2.46
2.47 """