1.1 --- a/WebStack/BaseHTTPRequestHandler.py Fri Aug 26 18:08:56 2005 +0000
1.2 +++ b/WebStack/BaseHTTPRequestHandler.py Fri Aug 26 18:10:52 2005 +0000
1.3 @@ -20,16 +20,16 @@
1.4 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1.5 """
1.6
1.7 -import Generic
1.8 -from Helpers.Request import MessageBodyStream, get_body_fields, decode_value, get_storage_items, Cookie
1.9 -from Helpers.Response import ConvertingStream
1.10 -from Helpers.Auth import UserInfo
1.11 -from Helpers.Session import SessionStore
1.12 +import WebStack.Generic
1.13 +from WebStack.Helpers.Request import MessageBodyStream, get_body_fields, decode_value, get_storage_items, Cookie
1.14 +from WebStack.Helpers.Response import ConvertingStream
1.15 +from WebStack.Helpers.Auth import UserInfo
1.16 +from WebStack.Helpers.Session import SessionStore
1.17 from cgi import parse_qs, FieldStorage
1.18 from Cookie import SimpleCookie
1.19 from StringIO import StringIO
1.20
1.21 -class Transaction(Generic.Transaction):
1.22 +class Transaction(WebStack.Generic.Transaction):
1.23
1.24 """
1.25 BaseHTTPRequestHandler transaction interface.
2.1 --- a/WebStack/CGI.py Fri Aug 26 18:08:56 2005 +0000
2.2 +++ b/WebStack/CGI.py Fri Aug 26 18:10:52 2005 +0000
2.3 @@ -20,18 +20,18 @@
2.4 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2.5 """
2.6
2.7 -import Generic
2.8 +import WebStack.Generic
2.9 import os, sys
2.10 -from Helpers.Request import MessageBodyStream, get_body_fields, decode_value, get_storage_items, Cookie
2.11 -from Helpers.Response import ConvertingStream
2.12 -from Helpers.Auth import UserInfo
2.13 -from Helpers.Session import SessionStore
2.14 -from Helpers import Environment
2.15 +from WebStack.Helpers.Request import MessageBodyStream, get_body_fields, decode_value, get_storage_items, Cookie
2.16 +from WebStack.Helpers.Response import ConvertingStream
2.17 +from WebStack.Helpers.Auth import UserInfo
2.18 +from WebStack.Helpers.Session import SessionStore
2.19 +from WebStack.Helpers import Environment
2.20 from cgi import parse_qs, FieldStorage
2.21 from Cookie import SimpleCookie
2.22 from StringIO import StringIO
2.23
2.24 -class Transaction(Generic.Transaction):
2.25 +class Transaction(WebStack.Generic.Transaction):
2.26
2.27 """
2.28 CGI transaction interface.
3.1 --- a/WebStack/Generic.py Fri Aug 26 18:08:56 2005 +0000
3.2 +++ b/WebStack/Generic.py Fri Aug 26 18:10:52 2005 +0000
3.3 @@ -35,7 +35,7 @@
3.4 """
3.5
3.6 import urllib
3.7 -from WebStack.Helpers.Request import Cookie
3.8 +from WebStack.Helpers.Request import Cookie, parse_header_value, ContentType, HeaderValue
3.9
3.10 class EndOfResponse(Exception):
3.11
3.12 @@ -43,71 +43,6 @@
3.13
3.14 pass
3.15
3.16 -class HeaderValue:
3.17 -
3.18 - "A container for header information."
3.19 -
3.20 - def __init__(self, principal_value, **attributes):
3.21 -
3.22 - """
3.23 - Initialise the container with the given 'principal_value' and optional
3.24 - keyword attributes representing the key=value pairs which accompany the
3.25 - 'principal_value'.
3.26 - """
3.27 -
3.28 - self.principal_value = principal_value
3.29 - self.attributes = attributes
3.30 -
3.31 - def __getattr__(self, name):
3.32 - if self.attributes.has_key(name):
3.33 - return self.attributes[name]
3.34 - else:
3.35 - raise AttributeError, name
3.36 -
3.37 - def __str__(self):
3.38 -
3.39 - """
3.40 - Format the header value object, producing a string suitable for the
3.41 - response header field.
3.42 - """
3.43 -
3.44 - l = []
3.45 - if self.principal_value:
3.46 - l.append(self.principal_value)
3.47 - for name, value in self.attributes.items():
3.48 - l.append("; ")
3.49 - l.append("%s=%s" % (name, value))
3.50 -
3.51 - # Make sure that only ASCII is used.
3.52 -
3.53 - return "".join(l).encode("US-ASCII")
3.54 -
3.55 -class ContentType(HeaderValue):
3.56 -
3.57 - "A container for content type information."
3.58 -
3.59 - def __init__(self, media_type, charset=None, **attributes):
3.60 -
3.61 - """
3.62 - Initialise the container with the given 'media_type', an optional
3.63 - 'charset', and optional keyword attributes representing the key=value
3.64 - pairs which qualify content types.
3.65 - """
3.66 -
3.67 - if charset is not None:
3.68 - attributes["charset"] = charset
3.69 - HeaderValue.__init__(self, media_type, **attributes)
3.70 -
3.71 - def __getattr__(self, name):
3.72 - if name == "media_type":
3.73 - return self.principal_value
3.74 - elif name == "charset":
3.75 - return self.attributes.get("charset")
3.76 - elif self.attributes.has_key(name):
3.77 - return self.attributes[name]
3.78 - else:
3.79 - raise AttributeError, name
3.80 -
3.81 class Transaction:
3.82
3.83 """
3.84 @@ -138,23 +73,9 @@
3.85 particular header.
3.86 """
3.87
3.88 - if header_value_str is None:
3.89 - return header_class(None)
3.90 -
3.91 - l = header_value_str.split(";")
3.92 - attributes = {}
3.93 -
3.94 - # Find the attributes.
3.95 + # Now uses the WebStack.Helpers.Request function of the same name.
3.96
3.97 - principal_value, attributes_str = l[0].strip(), l[1:]
3.98 -
3.99 - for attribute_str in attributes_str:
3.100 - t = attribute_str.split("=")
3.101 - if len(t) > 1:
3.102 - name, value = t[0].strip(), t[1].strip()
3.103 - attributes[name] = value
3.104 -
3.105 - return header_class(principal_value, **attributes)
3.106 + return parse_header_value(header_class, header_value_str)
3.107
3.108 def parse_content_type(self, content_type_field):
3.109
4.1 --- a/WebStack/JavaServlet.py Fri Aug 26 18:08:56 2005 +0000
4.2 +++ b/WebStack/JavaServlet.py Fri Aug 26 18:10:52 2005 +0000
4.3 @@ -20,25 +20,29 @@
4.4 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
4.5 """
4.6
4.7 -import Generic
4.8 +import WebStack.Generic
4.9 from StringIO import StringIO
4.10 -from Helpers.Request import Cookie, get_body_fields, get_storage_items, get_fields_from_query_string, filter_fields
4.11 +from WebStack.Helpers.Request import Cookie, FileContent, get_body_fields, \
4.12 + get_storage_items, get_fields_from_query_string, filter_fields, \
4.13 + HeaderValue
4.14 import javax.servlet.http
4.15 +import jarray
4.16
4.17 -# Form data decoding.
4.18 +# Java API form data decoding.
4.19
4.20 import javax.mail.internet
4.21 import javax.mail
4.22 import java.util
4.23 import java.net
4.24 -from WebStack.Generic import HeaderValue
4.25
4.26 class Stream:
4.27
4.28 """
4.29 - Wrapper around java.io.BufferedReader.
4.30 + Wrapper around java.io.ServletInputStream.
4.31 """
4.32
4.33 + bufsize = 100
4.34 +
4.35 def __init__(self, stream):
4.36
4.37 "Initialise the stream with the given underlying 'stream'."
4.38 @@ -61,13 +65,28 @@
4.39
4.40 "Read a line from the stream, returning it as a string."
4.41
4.42 - line = self.stream.readLine()
4.43 - if line is not None:
4.44 - return line + "\n"
4.45 + characters = StringIO()
4.46 + a = jarray.zeros(self.bufsize, 'b')
4.47 + while 1:
4.48 + nread = self.stream.readLine(a, 0, self.bufsize)
4.49 + if nread != -1:
4.50 + self._copy(a, characters, nread)
4.51 + if nread != self.bufsize:
4.52 + return characters.getvalue()
4.53 +
4.54 + def _unsigned(self, i):
4.55 + if i < 0:
4.56 + return chr(256 + i)
4.57 else:
4.58 - return ""
4.59 + return chr(i)
4.60
4.61 -class Transaction(Generic.Transaction):
4.62 + def _copy(self, source, target, length):
4.63 + i = 0
4.64 + while i < length:
4.65 + target.write(self._unsigned(source[i]))
4.66 + i += 1
4.67 +
4.68 +class Transaction(WebStack.Generic.Transaction):
4.69
4.70 """
4.71 Java Servlet transaction interface.
4.72 @@ -129,7 +148,7 @@
4.73 Returns the request stream for the transaction.
4.74 """
4.75
4.76 - return Stream(self.request.getReader())
4.77 + return Stream(self.request.getInputStream())
4.78
4.79 def get_request_method(self):
4.80
4.81 @@ -333,7 +352,7 @@
4.82 if self.message_fields is not None:
4.83 return self.message_fields
4.84 else:
4.85 - fields = self.message_fields = self._get_fields_from_message()
4.86 + fields = self.message_fields = self._get_fields_from_message(encoding)
4.87 else:
4.88 fields = {}
4.89 parameter_map = self.request.getParameterMap()
4.90 @@ -545,7 +564,7 @@
4.91
4.92 # Special Java-specific methods.
4.93
4.94 - def _get_fields_from_message(self):
4.95 + def _get_fields_from_message(self, encoding):
4.96
4.97 "Get fields from a multipart message."
4.98
4.99 @@ -556,7 +575,7 @@
4.100 str_buffer = java.io.StringWriter()
4.101 fp = self.get_request_stream()
4.102 boundary = fp.readline()
4.103 - str_buffer.write('Content-Type: multipart/mixed; boundary="%s"\n\n' % boundary[2:-1])
4.104 + str_buffer.write('Content-Type: multipart/mixed; boundary="%s"\n\n' % boundary[2:-2])
4.105 str_buffer.write(boundary)
4.106 str_buffer.write(fp.read())
4.107 str_buffer.close()
4.108 @@ -566,9 +585,9 @@
4.109 input_stream = java.io.StringBufferInputStream(str_buffer.toString())
4.110 message = javax.mail.internet.MimeMessage(session, input_stream)
4.111 content = message.getContent()
4.112 - return self._get_fields_from_multipart(content)
4.113 + return self._get_fields_from_multipart(content, encoding)
4.114
4.115 - def _get_fields_from_multipart(self, content):
4.116 + def _get_fields_from_multipart(self, content, encoding):
4.117
4.118 "Get fields from multipart 'content'."
4.119
4.120 @@ -593,14 +612,28 @@
4.121 # Store and optionally convert the field.
4.122
4.123 if disposition.name is not None:
4.124 - if not fields.has_key(disposition.name[1:-1]):
4.125 - fields[disposition.name[1:-1]] = []
4.126 - fields[disposition.name[1:-1]].append(subcontent)
4.127 + field_name = disposition.name[1:-1]
4.128 +
4.129 + # Using properly decoded header values.
4.130 +
4.131 + if part.getHeader("Content-Type") is not None:
4.132 + headers = {}
4.133 + for header in part.getAllHeaders():
4.134 + headers[header.getName()] = self.parse_header_value(HeaderValue, header.getValue())
4.135 + field_value = FileContent(subcontent, headers)
4.136 + else:
4.137 + field_value = self.decode_path(subcontent, encoding)
4.138 +
4.139 + # Store the entry in the fields dictionary.
4.140 +
4.141 + if not fields.has_key(field_name):
4.142 + fields[field_name] = []
4.143 + fields[field_name].append(field_value)
4.144
4.145 # Otherwise, descend deeper into the multipart hierarchy.
4.146
4.147 else:
4.148 - fields.update(self._get_fields_from_multipart(subcontent))
4.149 + fields.update(self._get_fields_from_multipart(subcontent, encoding))
4.150
4.151 return fields
4.152
5.1 --- a/WebStack/ModPython.py Fri Aug 26 18:08:56 2005 +0000
5.2 +++ b/WebStack/ModPython.py Fri Aug 26 18:10:52 2005 +0000
5.3 @@ -20,9 +20,10 @@
5.4 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
5.5 """
5.6
5.7 -import Generic
5.8 -from Helpers.Request import get_body_field, decode_value, filter_fields, Cookie
5.9 -from Helpers.Response import ConvertingStream
5.10 +import WebStack.Generic
5.11 +from WebStack.Helpers.Request import get_body_field, decode_value, \
5.12 + filter_fields, Cookie, FileContent, parse_headers
5.13 +from WebStack.Helpers.Response import ConvertingStream
5.14 from mod_python.util import parse_qs, FieldStorage
5.15 from mod_python import apache
5.16
5.17 @@ -38,11 +39,11 @@
5.18 try:
5.19 from mod_python import Session
5.20 except ImportError:
5.21 - from Helpers.Session import SessionStore
5.22 + from WebStack.Helpers.Session import SessionStore
5.23 import os
5.24 Session = None
5.25
5.26 -class Transaction(Generic.Transaction):
5.27 +class Transaction(WebStack.Generic.Transaction):
5.28
5.29 """
5.30 mod_python transaction interface.
5.31 @@ -289,7 +290,7 @@
5.32 # Detect and store file uploads.
5.33
5.34 if field.filename:
5.35 - fields[field_name].append(field.value)
5.36 + fields[field_name].append(FileContent(field.value, parse_headers(field.headers)))
5.37 else:
5.38 fields[field_name].append(get_body_field(field.value, encoding))
5.39
6.1 --- a/WebStack/Twisted.py Fri Aug 26 18:08:56 2005 +0000
6.2 +++ b/WebStack/Twisted.py Fri Aug 26 18:10:52 2005 +0000
6.3 @@ -20,14 +20,14 @@
6.4 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
6.5 """
6.6
6.7 -import Generic
6.8 -from Helpers.Auth import UserInfo
6.9 -from Helpers.Request import Cookie, decode_value, filter_fields
6.10 -from Helpers.Response import ConvertingStream
6.11 -from Helpers.Session import SessionStore
6.12 +import WebStack.Generic
6.13 +from WebStack.Helpers.Auth import UserInfo
6.14 +from WebStack.Helpers.Request import Cookie, decode_value, filter_fields
6.15 +from WebStack.Helpers.Response import ConvertingStream
6.16 +from WebStack.Helpers.Session import SessionStore
6.17 from cgi import parse_qs
6.18
6.19 -class Transaction(Generic.Transaction):
6.20 +class Transaction(WebStack.Generic.Transaction):
6.21
6.22 """
6.23 Twisted transaction interface.
7.1 --- a/WebStack/WSGI.py Fri Aug 26 18:08:56 2005 +0000
7.2 +++ b/WebStack/WSGI.py Fri Aug 26 18:10:52 2005 +0000
7.3 @@ -20,18 +20,18 @@
7.4 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
7.5 """
7.6
7.7 -import Generic
7.8 +import WebStack.Generic
7.9 import os, sys
7.10 -from Helpers.Request import MessageBodyStream, get_body_fields, decode_value, get_storage_items, Cookie
7.11 -from Helpers.Response import ConvertingStream
7.12 -from Helpers.Auth import UserInfo
7.13 -from Helpers.Session import SessionStore
7.14 -from Helpers import Environment
7.15 +from WebStack.Helpers.Request import MessageBodyStream, get_body_fields, decode_value, get_storage_items, Cookie
7.16 +from WebStack.Helpers.Response import ConvertingStream
7.17 +from WebStack.Helpers.Auth import UserInfo
7.18 +from WebStack.Helpers.Session import SessionStore
7.19 +from WebStack.Helpers import Environment
7.20 from cgi import parse_qs, FieldStorage
7.21 from Cookie import SimpleCookie
7.22 from StringIO import StringIO
7.23
7.24 -class Transaction(Generic.Transaction):
7.25 +class Transaction(WebStack.Generic.Transaction):
7.26
7.27 """
7.28 WSGI transaction interface.
8.1 --- a/WebStack/Webware.py Fri Aug 26 18:08:56 2005 +0000
8.2 +++ b/WebStack/Webware.py Fri Aug 26 18:10:52 2005 +0000
8.3 @@ -20,14 +20,14 @@
8.4 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
8.5 """
8.6
8.7 -import Generic
8.8 +import WebStack.Generic
8.9 from cgi import parse_qs
8.10 import StringIO
8.11 -from Helpers import Environment
8.12 -from Helpers.Request import Cookie, get_body_field_or_file, decode_value, filter_fields
8.13 -from Helpers.Response import ConvertingStream
8.14 +from WebStack.Helpers import Environment
8.15 +from WebStack.Helpers.Request import Cookie, get_body_field_or_file, decode_value, filter_fields
8.16 +from WebStack.Helpers.Response import ConvertingStream
8.17
8.18 -class Transaction(Generic.Transaction):
8.19 +class Transaction(WebStack.Generic.Transaction):
8.20
8.21 """
8.22 Webware transaction interface.
9.1 --- a/WebStack/Zope.py Fri Aug 26 18:08:56 2005 +0000
9.2 +++ b/WebStack/Zope.py Fri Aug 26 18:10:52 2005 +0000
9.3 @@ -25,14 +25,14 @@
9.4 baggage.
9.5 """
9.6
9.7 -import Generic
9.8 -from Helpers import Environment
9.9 -from Helpers.Request import Cookie, get_body_field_or_file, decode_value, filter_fields
9.10 -from Helpers.Response import ConvertingStream
9.11 -from Helpers.Auth import UserInfo
9.12 +import WebStack.Generic
9.13 +from WebStack.Helpers import Environment
9.14 +from WebStack.Helpers.Request import Cookie, get_body_field_or_file, decode_value, filter_fields
9.15 +from WebStack.Helpers.Response import ConvertingStream
9.16 +from WebStack.Helpers.Auth import UserInfo
9.17 import cgi
9.18
9.19 -class Transaction(Generic.Transaction):
9.20 +class Transaction(WebStack.Generic.Transaction):
9.21
9.22 """
9.23 Zope transaction interface.