1.1 --- a/WebStack/Resources/Static.py Sun Jan 15 23:54:02 2006 +0000
1.2 +++ b/WebStack/Resources/Static.py Sun Jan 15 23:54:16 2006 +0000
1.3 @@ -3,7 +3,7 @@
1.4 """
1.5 Resources for serving static content.
1.6
1.7 -Copyright (C) 2004, 2005 Paul Boddie <paul@boddie.org.uk>
1.8 +Copyright (C) 2004, 2005, 2006 Paul Boddie <paul@boddie.org.uk>
1.9
1.10 This library is free software; you can redistribute it and/or
1.11 modify it under the terms of the GNU Lesser General Public
1.12 @@ -27,24 +27,40 @@
1.13
1.14 "A resource serving the contents of a filesystem directory."
1.15
1.16 - def __init__(self, directory, media_types=None, unrecognised_media_type="application/data", urlencoding="utf-8"):
1.17 + def __init__(self, directory, media_types=None,
1.18 + unrecognised_media_type="application/data", content_types=None,
1.19 + unrecognised_content_type=None, default_encoding=None,
1.20 + urlencoding="utf-8"):
1.21
1.22 """
1.23 Initialise the resource to serve files from the given 'directory'.
1.24
1.25 + The optional 'content_types' dictionary can be used to map filename
1.26 + extensions to content types, where extensions consist of the part of a
1.27 + name after a "." character (such as "txt", "html"), and where content
1.28 + types are typically WebStack.Generic.ContentType objects.
1.29 +
1.30 The optional 'media_types' dictionary can be used to map filename
1.31 extensions to media types, where extensions consist of the part of a
1.32 name after a "." character (such as "txt", "html"), and where media
1.33 types are the usual content descriptions (such as "text/plain" and
1.34 "text/html").
1.35
1.36 - If 'media_types' contains a mapping from None to a media type, then
1.37 - this mapping is used when no extension is present on a requested
1.38 - resource name.
1.39 + If 'content_types' or 'media_types' contain a mapping from None to a
1.40 + content or media type, then this mapping is used when no extension is
1.41 + present on a requested resource name.
1.42
1.43 - Where no media type can be found for a resource, a predefined media
1.44 - type is set which can be overridden by specifying a value for the
1.45 - optional 'unrecognised_media_type' parameter.
1.46 + Where no content or media type can be found for a resource, a
1.47 + predefined media type is set which can be overridden by specifying a
1.48 + value for the optional 'unrecognised_media_type' or for the
1.49 + 'unrecognised_content_type' parameter - the latter overriding the former
1.50 + if specified.
1.51 +
1.52 + The optional 'default_encoding' is used to specify the character
1.53 + encoding used in any content type produced from a media type (or for
1.54 + the unrecognised media type). If set to None (as is the default), no
1.55 + encoding declaration is produced for file content associated with media
1.56 + types.
1.57
1.58 The optional 'urlencoding' is used to decode "URL encoded" character
1.59 values in the request path, and overrides the default encoding wherever
1.60 @@ -52,8 +68,11 @@
1.61 """
1.62
1.63 self.directory = directory
1.64 + self.content_types = content_types or {}
1.65 self.media_types = media_types or {}
1.66 self.unrecognised_media_type = unrecognised_media_type
1.67 + self.unrecognised_content_type = unrecognised_content_type
1.68 + self.default_encoding = default_encoding
1.69 self.urlencoding = urlencoding
1.70
1.71 def respond(self, trans):
1.72 @@ -67,7 +86,9 @@
1.73 # Test for the file's existence.
1.74
1.75 pathname = os.path.abspath(os.path.join(self.directory, filename))
1.76 - if not (pathname.startswith(os.path.join(self.directory, "/")) and os.path.exists(pathname) and os.path.isfile(pathname)):
1.77 + if not (pathname.startswith(os.path.join(self.directory, "/")) and \
1.78 + os.path.exists(pathname) and os.path.isfile(pathname)):
1.79 +
1.80 self.not_found(trans, filename)
1.81
1.82 # Get the extension.
1.83 @@ -76,17 +97,23 @@
1.84
1.85 if len(extension_parts) > 1:
1.86 extension = extension_parts[-1]
1.87 + content_type = self.content_types.get(extension)
1.88 media_type = self.media_types.get(extension)
1.89 else:
1.90 + content_type = self.content_types.get(None)
1.91 media_type = self.media_types.get(None)
1.92
1.93 # Set the content type.
1.94 - # NOTE: Add other parts of the content type such as character encodings.
1.95
1.96 - if media_type is not None:
1.97 - trans.set_content_type(ContentType(media_type))
1.98 + if content_type is not None:
1.99 + trans.set_content_type(content_type)
1.100 + elif media_type is not None:
1.101 + trans.set_content_type(ContentType(media_type, self.default_encoding))
1.102 + elif self.unrecognised_content_type is not None:
1.103 + trans.set_content_type(self.unrecognised_content_type)
1.104 else:
1.105 - trans.set_content_type(ContentType(self.unrecognised_media_type))
1.106 + trans.set_content_type(
1.107 + ContentType(self.unrecognised_media_type, self.default_encoding))
1.108
1.109 # Write the file to the client.
1.110