durusmail: quixote-users: static file publisher
static file publisher
2002-09-23
static file publisher
Jonathan Corbet
2002-09-23
Just for the hell of it, here's my version of the static directory
publisher.  It looks a lot like Hamish's, except that (1) it has an ugly
hack allowing the presentation of static files with all the LWN frobbery
around it, and (2) I don't let people sneak upward with "..".  You can
still export the world (or a good chunk thereof) by mistake with a symbolic
link, though.

jon

Jonathan Corbet
Executive editor, LWN.net
corbet@lwn.net


#
# Publish a static directory.
#
# $Id: StaticPublisher.py,v 1.2 2002/05/23 16:36:16 corbet Exp $
#
import mimetypes, os.path
from quixote import errors

import presentation
from utils import *


class StaticPublisher:
    _q_exports = [ ]

    def __init__ (self, request, dir):
        self.dir = dir

    #
    # We don't list the directory, just send them away.
    #
    def _q_index (self, request):
        return request.response.redirect (GetRootPage ())

    #
    # Most stuff will go through here, where we move downward.
    #
    def _q_getname (self, request, component):
        #
        # No tricky stuff.
        #
        if component == '..' or component == '.':
            raise errors.TraversalError ('Resource not found',
                                         'None of that silliness')
        #
        # If this is a directory, we move down into it.
        #
        fullpath = self.dir + '/' + component
        if os.path.isdir (fullpath):
            return StaticPublisher (request, fullpath)
        #
        # If it's a file we publish it.
        #
        if os.path.isfile (fullpath):
            return StaticFilePublisher (request, fullpath)
        #
        # Anything else we refuse to deal with.
        #
        raise errors.TraversalError ('Resource not found',
                                     'Trying to publish something weird')


#
# Publish an individual file.
#
class StaticFilePublisher:
    _q_exports = [ ]

    def __init__ (self, request, fname):
        self.file = open (fname, 'r')
        self.mtype = mimetypes.guess_type (fname)[0]
        self.lwn_content = None
        if self.mtype is None:
            if fname[-4:] == '.lwn':
                self.lwn_content = 1
            else:
                self.mtype = 'text/plain'

    def _q_index (self, request):
        #
        # If this is meant to be published in the full LWN frame,
        # make it so.
        #
        if self.lwn_content:
            return self.publish_lwn (request)
        #
        # Otherwise send it out direct.
        #
        request.response.set_header ('content-type', self.mtype)
        return self.file.read ()

    #
    # Publish a file with all the LWN trappings.  Since we're not
    # a template file (not sure why) we need to do it the hard way.
    #
    def publish_lwn (self, request):
        title = self.file.readline ()[:-1]
        page = presentation.StandardPage (request)
        ret = page.Header (title)
        ret += self.file.read ()
        return ret + page.Trailer ()


reply