summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 02f4dc6)
raw | patch | inline | side by side (parent: 02f4dc6)
author | richard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2> | |
Fri, 5 Dec 2003 03:28:38 +0000 (03:28 +0000) | ||
committer | richard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2> | |
Fri, 5 Dec 2003 03:28:38 +0000 (03:28 +0000) |
cleanly and b) served with reasonable modification dates and handling of
if-modified-since.
File serving also sends a content-length now too.
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@2014 57a73879-2fb5-44c3-a270-3262357dd7e2
if-modified-since.
File serving also sends a content-length now too.
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@2014 57a73879-2fb5-44c3-a270-3262357dd7e2
CHANGES.txt | patch | blob | history | |
roundup/backends/blobfiles.py | patch | blob | history | |
roundup/cgi/client.py | patch | blob | history | |
roundup/date.py | patch | blob | history |
diff --git a/CHANGES.txt b/CHANGES.txt
index 069021acb39e5f9e0a4bf9a70d33afd91cb599da..5a8d645af427a020cc3b8b90338359378ad5c093 100644 (file)
--- a/CHANGES.txt
+++ b/CHANGES.txt
- added script for copying user(s) from tracker to tracker (sf patch
828963)
- ignore incoming email with "Precedence: bulk" (sf patch 843489)
+- use HTTP 'Content-Length' header (modified sf patch 844577)
Fixed:
- mysql documentation fixed to note requirement of 4.0+ and InnoDB
index 0008ba60c468aacf0f7bfe91acb97fb23a72d9fa..1a04aae5b3b41e0e6d8a557f23e083578de8b107 100644 (file)
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#
-#$Id: blobfiles.py,v 1.9 2002-09-10 00:11:50 richard Exp $
+#$Id: blobfiles.py,v 1.10 2003-12-05 03:28:38 richard Exp $
'''
This module exports file storage for roundup backends.
Files are stored into a directory hierarchy.
def getfile(self, classname, nodeid, property):
'''Get the content of the file in the database.
'''
+ # try a variety of different filenames - the file could be in the
+ # usual place, or it could be in a temp file pre-commit *or* it
+ # could be in an old-style, backwards-compatible flat directory
filename = self.filename(classname, nodeid, property)
- try:
- return open(filename, 'rb').read()
- except:
- # now try the temp pre-commit filename
- try:
- return open(filename+'.tmp', 'rb').read()
- except:
- # fallback to flat file storage
- filename = self.filename_flat(classname, nodeid, property)
- return open(filename, 'rb').read()
+ flat_filename = self.filename_flat(classname, nodeid, property)
+ for filename in (filename, filename+'.tmp', flat_filename):
+ if os.path.exists(filename):
+ f = open(filename, 'rb')
+ break
+ else:
+ raise IOError, 'content file not found'
+ # snarf the contents and make sure we close the file
+ content = f.read()
+ f.close()
+ return content
def numfiles(self):
'''Get number of files in storage, even across subdirectories.
diff --git a/roundup/cgi/client.py b/roundup/cgi/client.py
index a72ae84c0b5b5272ed4250bee5db20fdc3620905..fe8831371b8590243b153b644e93d7bd4bef0411 100644 (file)
--- a/roundup/cgi/client.py
+++ b/roundup/cgi/client.py
-# $Id: client.py,v 1.148 2003-11-21 22:22:32 jlgijsbers Exp $
+# $Id: client.py,v 1.149 2003-12-05 03:28:38 richard Exp $
__doc__ = """
WWW request handler (also used in the stand-alone server).
if classname != 'file':
raise NotFound, designator
- # we just want to serve up the file named
self.opendb('admin')
file = self.db.file
- self.additional_headers['Content-Type'] = file.get(nodeid, 'type')
- self.write(file.get(nodeid, 'content'))
+
+ mime_type = file.get(nodeid, 'type')
+ content = file.get(nodeid, 'content')
+ lmt = file.get(nodeid, 'activity').timestamp()
+
+ self._serve_file(lmt, mime_type, content)
def serve_static_file(self, file):
+ ''' Serve up the file named from the templates dir
+ '''
+ filename = os.path.join(self.instance.config.TEMPLATES, file)
+
+ # last-modified time
+ lmt = os.stat(filename)[stat.ST_MTIME]
+
+ # detemine meta-type
+ file = str(file)
+ mime_type = mimetypes.guess_type(file)[0]
+ if not mime_type:
+ if file.endswith('.css'):
+ mime_type = 'text/css'
+ else:
+ mime_type = 'text/plain'
+
+ # snarf the content
+ f = open(filename, 'rb')
+ try:
+ content = f.read()
+ finally:
+ f.close()
+
+ self._serve_file(lmt, mime_type, content)
+
+ def _serve_file(self, last_modified, mime_type, content):
+ ''' guts of serve_file() and serve_static_file()
+ '''
ims = None
# see if there's an if-modified-since...
if hasattr(self.request, 'headers'):
elif self.env.has_key('HTTP_IF_MODIFIED_SINCE'):
# cgi will put the header in the env var
ims = self.env['HTTP_IF_MODIFIED_SINCE']
- filename = os.path.join(self.instance.config.TEMPLATES, file)
- lmt = os.stat(filename)[stat.ST_MTIME]
if ims:
ims = rfc822.parsedate(ims)[:6]
lmtt = time.gmtime(lmt)[:6]
if lmtt <= ims:
raise NotModified
- # we just want to serve up the file named
- file = str(file)
- mt = mimetypes.guess_type(file)[0]
- if not mt:
- if file.endswith('.css'):
- mt = 'text/css'
- else:
- mt = 'text/plain'
- self.additional_headers['Content-Type'] = mt
- self.additional_headers['Last-Modifed'] = rfc822.formatdate(lmt)
- self.write(open(filename, 'rb').read())
+ # spit out headers
+ self.additional_headers['Content-Type'] = mime_type
+ self.additional_headers['Content-Length'] = len(content)
+ lmt = rfc822.formatdate(last_modified)
+ self.additional_headers['Last-Modifed'] = lmt
+ self.write(content)
def renderContext(self):
''' Return a PageTemplate for the named page
diff --git a/roundup/date.py b/roundup/date.py
index b07bcf1664a41a34550da3f28f26b9e568c5cb38..49151768aedaf563b78e76c689702609803b671d 100644 (file)
--- a/roundup/date.py
+++ b/roundup/date.py
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#
-# $Id: date.py,v 1.58 2003-12-04 23:06:53 richard Exp $
+# $Id: date.py,v 1.59 2003-12-05 03:28:38 richard Exp $
__doc__ = """
Date, time and time interval handling.
return '%4d%02d%02d%02d%02d%02d'%(self.year, self.month,
self.day, self.hour, self.minute, self.second)
+ def timestamp(self):
+ ''' return a UNIX timestamp for this date '''
+ return calendar.timegm((self.year, self.month, self.day, self.hour,
+ self.minute, self.second, 0, 0, 0))
+
class Interval:
'''
Date intervals are specified using the suffixes "y", "m", and "d". The