# HG changeset patch # User paulb # Date 1125079852 0 # Node ID 63cf9982f1b4991083ef42cf33890e8251602001 # Parent 72a74602bbb156f88101ad7019e8599418dc65c9 [project @ 2005-08-26 18:10:52 by paulb] Moved ContentType and HeaderValue to WebStack.Helpers.Request, along with the parse_header_value implementation. Fixed imports to be absolute. Fixed the stream implementation for the JavaServlet support so that the contents of streams are likely to be unaffected by the current character encoding. diff -r 72a74602bbb1 -r 63cf9982f1b4 WebStack/BaseHTTPRequestHandler.py --- a/WebStack/BaseHTTPRequestHandler.py Fri Aug 26 18:08:56 2005 +0000 +++ b/WebStack/BaseHTTPRequestHandler.py Fri Aug 26 18:10:52 2005 +0000 @@ -20,16 +20,16 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA """ -import Generic -from Helpers.Request import MessageBodyStream, get_body_fields, decode_value, get_storage_items, Cookie -from Helpers.Response import ConvertingStream -from Helpers.Auth import UserInfo -from Helpers.Session import SessionStore +import WebStack.Generic +from WebStack.Helpers.Request import MessageBodyStream, get_body_fields, decode_value, get_storage_items, Cookie +from WebStack.Helpers.Response import ConvertingStream +from WebStack.Helpers.Auth import UserInfo +from WebStack.Helpers.Session import SessionStore from cgi import parse_qs, FieldStorage from Cookie import SimpleCookie from StringIO import StringIO -class Transaction(Generic.Transaction): +class Transaction(WebStack.Generic.Transaction): """ BaseHTTPRequestHandler transaction interface. diff -r 72a74602bbb1 -r 63cf9982f1b4 WebStack/CGI.py --- a/WebStack/CGI.py Fri Aug 26 18:08:56 2005 +0000 +++ b/WebStack/CGI.py Fri Aug 26 18:10:52 2005 +0000 @@ -20,18 +20,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA """ -import Generic +import WebStack.Generic import os, sys -from Helpers.Request import MessageBodyStream, get_body_fields, decode_value, get_storage_items, Cookie -from Helpers.Response import ConvertingStream -from Helpers.Auth import UserInfo -from Helpers.Session import SessionStore -from Helpers import Environment +from WebStack.Helpers.Request import MessageBodyStream, get_body_fields, decode_value, get_storage_items, Cookie +from WebStack.Helpers.Response import ConvertingStream +from WebStack.Helpers.Auth import UserInfo +from WebStack.Helpers.Session import SessionStore +from WebStack.Helpers import Environment from cgi import parse_qs, FieldStorage from Cookie import SimpleCookie from StringIO import StringIO -class Transaction(Generic.Transaction): +class Transaction(WebStack.Generic.Transaction): """ CGI transaction interface. diff -r 72a74602bbb1 -r 63cf9982f1b4 WebStack/Generic.py --- a/WebStack/Generic.py Fri Aug 26 18:08:56 2005 +0000 +++ b/WebStack/Generic.py Fri Aug 26 18:10:52 2005 +0000 @@ -35,7 +35,7 @@ """ import urllib -from WebStack.Helpers.Request import Cookie +from WebStack.Helpers.Request import Cookie, parse_header_value, ContentType, HeaderValue class EndOfResponse(Exception): @@ -43,71 +43,6 @@ pass -class HeaderValue: - - "A container for header information." - - def __init__(self, principal_value, **attributes): - - """ - Initialise the container with the given 'principal_value' and optional - keyword attributes representing the key=value pairs which accompany the - 'principal_value'. - """ - - self.principal_value = principal_value - self.attributes = attributes - - def __getattr__(self, name): - if self.attributes.has_key(name): - return self.attributes[name] - else: - raise AttributeError, name - - def __str__(self): - - """ - Format the header value object, producing a string suitable for the - response header field. - """ - - l = [] - if self.principal_value: - l.append(self.principal_value) - for name, value in self.attributes.items(): - l.append("; ") - l.append("%s=%s" % (name, value)) - - # Make sure that only ASCII is used. - - return "".join(l).encode("US-ASCII") - -class ContentType(HeaderValue): - - "A container for content type information." - - def __init__(self, media_type, charset=None, **attributes): - - """ - Initialise the container with the given 'media_type', an optional - 'charset', and optional keyword attributes representing the key=value - pairs which qualify content types. - """ - - if charset is not None: - attributes["charset"] = charset - HeaderValue.__init__(self, media_type, **attributes) - - def __getattr__(self, name): - if name == "media_type": - return self.principal_value - elif name == "charset": - return self.attributes.get("charset") - elif self.attributes.has_key(name): - return self.attributes[name] - else: - raise AttributeError, name - class Transaction: """ @@ -138,23 +73,9 @@ particular header. """ - if header_value_str is None: - return header_class(None) - - l = header_value_str.split(";") - attributes = {} - - # Find the attributes. + # Now uses the WebStack.Helpers.Request function of the same name. - principal_value, attributes_str = l[0].strip(), l[1:] - - for attribute_str in attributes_str: - t = attribute_str.split("=") - if len(t) > 1: - name, value = t[0].strip(), t[1].strip() - attributes[name] = value - - return header_class(principal_value, **attributes) + return parse_header_value(header_class, header_value_str) def parse_content_type(self, content_type_field): diff -r 72a74602bbb1 -r 63cf9982f1b4 WebStack/JavaServlet.py --- a/WebStack/JavaServlet.py Fri Aug 26 18:08:56 2005 +0000 +++ b/WebStack/JavaServlet.py Fri Aug 26 18:10:52 2005 +0000 @@ -20,25 +20,29 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA """ -import Generic +import WebStack.Generic from StringIO import StringIO -from Helpers.Request import Cookie, get_body_fields, get_storage_items, get_fields_from_query_string, filter_fields +from WebStack.Helpers.Request import Cookie, FileContent, get_body_fields, \ + get_storage_items, get_fields_from_query_string, filter_fields, \ + HeaderValue import javax.servlet.http +import jarray -# Form data decoding. +# Java API form data decoding. import javax.mail.internet import javax.mail import java.util import java.net -from WebStack.Generic import HeaderValue class Stream: """ - Wrapper around java.io.BufferedReader. + Wrapper around java.io.ServletInputStream. """ + bufsize = 100 + def __init__(self, stream): "Initialise the stream with the given underlying 'stream'." @@ -61,13 +65,28 @@ "Read a line from the stream, returning it as a string." - line = self.stream.readLine() - if line is not None: - return line + "\n" + characters = StringIO() + a = jarray.zeros(self.bufsize, 'b') + while 1: + nread = self.stream.readLine(a, 0, self.bufsize) + if nread != -1: + self._copy(a, characters, nread) + if nread != self.bufsize: + return characters.getvalue() + + def _unsigned(self, i): + if i < 0: + return chr(256 + i) else: - return "" + return chr(i) -class Transaction(Generic.Transaction): + def _copy(self, source, target, length): + i = 0 + while i < length: + target.write(self._unsigned(source[i])) + i += 1 + +class Transaction(WebStack.Generic.Transaction): """ Java Servlet transaction interface. @@ -129,7 +148,7 @@ Returns the request stream for the transaction. """ - return Stream(self.request.getReader()) + return Stream(self.request.getInputStream()) def get_request_method(self): @@ -333,7 +352,7 @@ if self.message_fields is not None: return self.message_fields else: - fields = self.message_fields = self._get_fields_from_message() + fields = self.message_fields = self._get_fields_from_message(encoding) else: fields = {} parameter_map = self.request.getParameterMap() @@ -545,7 +564,7 @@ # Special Java-specific methods. - def _get_fields_from_message(self): + def _get_fields_from_message(self, encoding): "Get fields from a multipart message." @@ -556,7 +575,7 @@ str_buffer = java.io.StringWriter() fp = self.get_request_stream() boundary = fp.readline() - str_buffer.write('Content-Type: multipart/mixed; boundary="%s"\n\n' % boundary[2:-1]) + str_buffer.write('Content-Type: multipart/mixed; boundary="%s"\n\n' % boundary[2:-2]) str_buffer.write(boundary) str_buffer.write(fp.read()) str_buffer.close() @@ -566,9 +585,9 @@ input_stream = java.io.StringBufferInputStream(str_buffer.toString()) message = javax.mail.internet.MimeMessage(session, input_stream) content = message.getContent() - return self._get_fields_from_multipart(content) + return self._get_fields_from_multipart(content, encoding) - def _get_fields_from_multipart(self, content): + def _get_fields_from_multipart(self, content, encoding): "Get fields from multipart 'content'." @@ -593,14 +612,28 @@ # Store and optionally convert the field. if disposition.name is not None: - if not fields.has_key(disposition.name[1:-1]): - fields[disposition.name[1:-1]] = [] - fields[disposition.name[1:-1]].append(subcontent) + field_name = disposition.name[1:-1] + + # Using properly decoded header values. + + if part.getHeader("Content-Type") is not None: + headers = {} + for header in part.getAllHeaders(): + headers[header.getName()] = self.parse_header_value(HeaderValue, header.getValue()) + field_value = FileContent(subcontent, headers) + else: + field_value = self.decode_path(subcontent, encoding) + + # Store the entry in the fields dictionary. + + if not fields.has_key(field_name): + fields[field_name] = [] + fields[field_name].append(field_value) # Otherwise, descend deeper into the multipart hierarchy. else: - fields.update(self._get_fields_from_multipart(subcontent)) + fields.update(self._get_fields_from_multipart(subcontent, encoding)) return fields diff -r 72a74602bbb1 -r 63cf9982f1b4 WebStack/ModPython.py --- a/WebStack/ModPython.py Fri Aug 26 18:08:56 2005 +0000 +++ b/WebStack/ModPython.py Fri Aug 26 18:10:52 2005 +0000 @@ -20,9 +20,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA """ -import Generic -from Helpers.Request import get_body_field, decode_value, filter_fields, Cookie -from Helpers.Response import ConvertingStream +import WebStack.Generic +from WebStack.Helpers.Request import get_body_field, decode_value, \ + filter_fields, Cookie, FileContent, parse_headers +from WebStack.Helpers.Response import ConvertingStream from mod_python.util import parse_qs, FieldStorage from mod_python import apache @@ -38,11 +39,11 @@ try: from mod_python import Session except ImportError: - from Helpers.Session import SessionStore + from WebStack.Helpers.Session import SessionStore import os Session = None -class Transaction(Generic.Transaction): +class Transaction(WebStack.Generic.Transaction): """ mod_python transaction interface. @@ -289,7 +290,7 @@ # Detect and store file uploads. if field.filename: - fields[field_name].append(field.value) + fields[field_name].append(FileContent(field.value, parse_headers(field.headers))) else: fields[field_name].append(get_body_field(field.value, encoding)) diff -r 72a74602bbb1 -r 63cf9982f1b4 WebStack/Twisted.py --- a/WebStack/Twisted.py Fri Aug 26 18:08:56 2005 +0000 +++ b/WebStack/Twisted.py Fri Aug 26 18:10:52 2005 +0000 @@ -20,14 +20,14 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA """ -import Generic -from Helpers.Auth import UserInfo -from Helpers.Request import Cookie, decode_value, filter_fields -from Helpers.Response import ConvertingStream -from Helpers.Session import SessionStore +import WebStack.Generic +from WebStack.Helpers.Auth import UserInfo +from WebStack.Helpers.Request import Cookie, decode_value, filter_fields +from WebStack.Helpers.Response import ConvertingStream +from WebStack.Helpers.Session import SessionStore from cgi import parse_qs -class Transaction(Generic.Transaction): +class Transaction(WebStack.Generic.Transaction): """ Twisted transaction interface. diff -r 72a74602bbb1 -r 63cf9982f1b4 WebStack/WSGI.py --- a/WebStack/WSGI.py Fri Aug 26 18:08:56 2005 +0000 +++ b/WebStack/WSGI.py Fri Aug 26 18:10:52 2005 +0000 @@ -20,18 +20,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA """ -import Generic +import WebStack.Generic import os, sys -from Helpers.Request import MessageBodyStream, get_body_fields, decode_value, get_storage_items, Cookie -from Helpers.Response import ConvertingStream -from Helpers.Auth import UserInfo -from Helpers.Session import SessionStore -from Helpers import Environment +from WebStack.Helpers.Request import MessageBodyStream, get_body_fields, decode_value, get_storage_items, Cookie +from WebStack.Helpers.Response import ConvertingStream +from WebStack.Helpers.Auth import UserInfo +from WebStack.Helpers.Session import SessionStore +from WebStack.Helpers import Environment from cgi import parse_qs, FieldStorage from Cookie import SimpleCookie from StringIO import StringIO -class Transaction(Generic.Transaction): +class Transaction(WebStack.Generic.Transaction): """ WSGI transaction interface. diff -r 72a74602bbb1 -r 63cf9982f1b4 WebStack/Webware.py --- a/WebStack/Webware.py Fri Aug 26 18:08:56 2005 +0000 +++ b/WebStack/Webware.py Fri Aug 26 18:10:52 2005 +0000 @@ -20,14 +20,14 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA """ -import Generic +import WebStack.Generic from cgi import parse_qs import StringIO -from Helpers import Environment -from Helpers.Request import Cookie, get_body_field_or_file, decode_value, filter_fields -from Helpers.Response import ConvertingStream +from WebStack.Helpers import Environment +from WebStack.Helpers.Request import Cookie, get_body_field_or_file, decode_value, filter_fields +from WebStack.Helpers.Response import ConvertingStream -class Transaction(Generic.Transaction): +class Transaction(WebStack.Generic.Transaction): """ Webware transaction interface. diff -r 72a74602bbb1 -r 63cf9982f1b4 WebStack/Zope.py --- a/WebStack/Zope.py Fri Aug 26 18:08:56 2005 +0000 +++ b/WebStack/Zope.py Fri Aug 26 18:10:52 2005 +0000 @@ -25,14 +25,14 @@ baggage. """ -import Generic -from Helpers import Environment -from Helpers.Request import Cookie, get_body_field_or_file, decode_value, filter_fields -from Helpers.Response import ConvertingStream -from Helpers.Auth import UserInfo +import WebStack.Generic +from WebStack.Helpers import Environment +from WebStack.Helpers.Request import Cookie, get_body_field_or_file, decode_value, filter_fields +from WebStack.Helpers.Response import ConvertingStream +from WebStack.Helpers.Auth import UserInfo import cgi -class Transaction(Generic.Transaction): +class Transaction(WebStack.Generic.Transaction): """ Zope transaction interface.