-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adjust to new location of datetimeutils.
- Loading branch information
Showing
3 changed files
with
250 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
############################################################################## | ||
# | ||
# Copyright (c) 2002 Zope Corporation and Contributors. | ||
# All Rights Reserved. | ||
# | ||
# This software is subject to the provisions of the Zope Public License, | ||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. | ||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED | ||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS | ||
# FOR A PARTICULAR PURPOSE. | ||
# | ||
############################################################################## | ||
"""File-based browser resources. | ||
$Id$ | ||
""" | ||
|
||
import time | ||
from zope.security.proxy import Proxy | ||
from zope.interface import implements | ||
from zope.datetime import time as timeFromDateTimeString | ||
from zope.publisher.interfaces import NotFound | ||
from zope.publisher.interfaces.browser import IBrowserPublisher | ||
|
||
from zope.app.publisher.browser import BrowserView | ||
from zope.app.publisher.fileresource import File, Image | ||
from zope.app.publisher.browser.resource import Resource | ||
|
||
class FileResource(BrowserView, Resource): | ||
|
||
implements(IBrowserPublisher) | ||
|
||
def publishTraverse(self, request, name): | ||
'''See interface IBrowserPublisher''' | ||
raise NotFound(None, name) | ||
|
||
def browserDefault(self, request): | ||
'''See interface IBrowserPublisher''' | ||
return getattr(self, request.method), () | ||
|
||
# | ||
############################################################ | ||
|
||
# for unit tests | ||
def _testData(self): | ||
f = open(self.context.path, 'rb') | ||
data = f.read() | ||
f.close() | ||
return data | ||
|
||
|
||
def chooseContext(self): | ||
"""Choose the appropriate context""" | ||
return self.context | ||
|
||
|
||
def GET(self): | ||
"""Default document""" | ||
|
||
file = self.chooseContext() | ||
request = self.request | ||
response = request.response | ||
|
||
# HTTP If-Modified-Since header handling. This is duplicated | ||
# from OFS.Image.Image - it really should be consolidated | ||
# somewhere... | ||
header = request.getHeader('If-Modified-Since', None) | ||
if header is not None: | ||
header = header.split(';')[0] | ||
# Some proxies seem to send invalid date strings for this | ||
# header. If the date string is not valid, we ignore it | ||
# rather than raise an error to be generally consistent | ||
# with common servers such as Apache (which can usually | ||
# understand the screwy date string as a lucky side effect | ||
# of the way they parse it). | ||
try: mod_since=long(timeFromDateTimeString(header)) | ||
except: mod_since=None | ||
if mod_since is not None: | ||
if getattr(file, 'lmt', None): | ||
last_mod = long(file.lmt) | ||
else: | ||
last_mod = long(0) | ||
if last_mod > 0 and last_mod <= mod_since: | ||
response.setStatus(304) | ||
return '' | ||
|
||
response.setHeader('Content-Type', file.content_type) | ||
response.setHeader('Last-Modified', file.lmh) | ||
|
||
setCacheControl(response) | ||
f = open(file.path,'rb') | ||
data = f.read() | ||
f.close() | ||
|
||
return data | ||
|
||
def HEAD(self): | ||
file = self.chooseContext() | ||
response = self.request.response | ||
response.setHeader('Content-Type', file.content_type) | ||
response.setHeader('Last-Modified', file.lmh) | ||
setCacheControl(response) | ||
return '' | ||
|
||
|
||
def setCacheControl(response, secs=86400): | ||
# Cache for one day by default | ||
response.setHeader('Cache-Control', 'public,max-age=%s' % secs) | ||
t = time.time() + secs | ||
response.setHeader('Expires', | ||
time.strftime("%a, %d %b %Y %H:%M:%S GMT", | ||
time.gmtime(t))) | ||
|
||
|
||
class FileResourceFactory(object): | ||
|
||
def __init__(self, path, checker, name): | ||
self.__file = File(path, name) | ||
self.__checker = checker | ||
self.__name = name | ||
|
||
def __call__(self, request): | ||
resource = FileResource(self.__file, request) | ||
resource.__Security_checker__ = self.__checker | ||
resource.__name__ = self.__name | ||
return resource | ||
|
||
class ImageResourceFactory(object): | ||
|
||
def __init__(self, path, checker, name): | ||
self.__file = Image(path, name) | ||
self.__checker = checker | ||
self.__name = name | ||
|
||
def __call__(self, request): | ||
resource = FileResource(self.__file, request) | ||
resource.__Security_checker__ = self.__checker | ||
resource.__name__ = self.__name | ||
return resource |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
############################################################################## | ||
# | ||
# Copyright (c) 2003 Zope Corporation and Contributors. | ||
# All Rights Reserved. | ||
# | ||
# This software is subject to the provisions of the Zope Public License, | ||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. | ||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED | ||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS | ||
# FOR A PARTICULAR PURPOSE. | ||
# | ||
############################################################################## | ||
"""Zope-specific request field converters. | ||
$Id$ | ||
""" | ||
from datetime import datetime | ||
|
||
from zope.publisher.browser import registerTypeConverter | ||
from zope.datetime import parse as parseDateTime | ||
|
||
def field2date_via_datetimeutils(v): | ||
"""Converter for request fields marshalled as ':date'. | ||
o TODO: Uses the non-localized and non-tzinfo-aware 'parseDateTime' | ||
utility from zope.datetime; a better alternative | ||
would be more I18N / L10N aware, perhaps even adapting to | ||
the expressed preferences of the user. | ||
""" | ||
if hasattr(v,'read'): | ||
v = v.read() | ||
else: | ||
v = str(v) | ||
|
||
# *Don't* force a timezone if not passed explicitly; leave it as | ||
# "naive" datetime. | ||
year, month, day, hour, minute, second, tzname = parseDateTime(v, local=0) | ||
|
||
# TODO: look up a real tzinfo object using 'tzname' | ||
# | ||
# Option 1: Use 'timezones' module as global registry:: | ||
# | ||
# from zope.app.timezones import getTimezoneInfo | ||
# tzinfo = getTimezoneInfo(tzname) | ||
# | ||
# Option 2: Use a utility (or perhaps a view, for L10N). | ||
# | ||
# tz_lookup = getUtility(ITimezoneLookup) | ||
# tzinfo = tz_lookup(tzname) | ||
# | ||
return datetime(year, month, day, hour, minute, second, | ||
# tzinfo=tzinfo | ||
) | ||
|
||
ZOPE_CONVERTERS = [('date', field2date_via_datetimeutils)] | ||
|
||
def registerZopeConverters(): | ||
|
||
for field_type, converter in ZOPE_CONVERTERS: | ||
registerTypeConverter(field_type, converter) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
############################################################################## | ||
# | ||
# Copyright (c) 2002 Zope Corporation and Contributors. | ||
# All Rights Reserved. | ||
# | ||
# This software is subject to the provisions of the Zope Public License, | ||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. | ||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED | ||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS | ||
# FOR A PARTICULAR PURPOSE. | ||
# | ||
############################################################################## | ||
"""Browser File Resource | ||
$Id$ | ||
""" | ||
import os | ||
import posixpath | ||
|
||
from time import time | ||
|
||
from zope.app.contenttypes import guess_content_type | ||
from zope.datetime import rfc1123_date | ||
|
||
|
||
class File(object): | ||
|
||
def __init__(self, path, name): | ||
self.path = path | ||
|
||
f = open(path, 'rb') | ||
data = f.read() | ||
f.close() | ||
self.content_type, enc = guess_content_type(path, data) | ||
self.__name__ = name | ||
self.lmt = float(os.path.getmtime(path)) or time() | ||
self.lmh = rfc1123_date(self.lmt) | ||
|
||
|
||
class Image(File): | ||
"""Image objects stored in external files.""" | ||
|
||
def __init__(self, path, name): | ||
super(Image, self).__init__(path, name) | ||
if self.content_type in (None, 'application/octet-stream'): | ||
ext = os.path.splitext(self.path)[1] | ||
if ext: | ||
self.content_type = 'image/%s' % ext[1:] |