| Index: sky/tools/staticdirindex.py
|
| diff --git a/sky/tools/staticdirindex.py b/sky/tools/staticdirindex.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..35eded7fbf10e59d23f0c8f800c90cb9c9df528a
|
| --- /dev/null
|
| +++ b/sky/tools/staticdirindex.py
|
| @@ -0,0 +1,120 @@
|
| +# From http://tools.cherrypy.org/wiki/staticdirindex
|
| +# CherryPy code is covered under a BSD License:
|
| +# https://bitbucket.org/cherrypy/cherrypy/src/697c7af588b8/cherrypy/LICENSE.txt
|
| +
|
| +import os
|
| +import re
|
| +import stat
|
| +import urllib
|
| +import cherrypy
|
| +from cherrypy.lib import cptools, http
|
| +
|
| +# Undercover kludge to wrap staticdir
|
| +from cherrypy.lib.static import staticdir
|
| +
|
| +def staticdirindex(section, dir, root="", match="", content_types=None,
|
| + index="", indexlistermatch="", indexlister=None, **kwargs):
|
| + """Serve a directory index listing for a dir.
|
| +
|
| + Compatibility alert: staticdirindex is built on and is dependent on
|
| + staticdir and its configurations. staticdirindex only works effectively
|
| + in locations where staticdir is also configured. staticdirindex is
|
| + coded to allow easy integration with staticdir, if demand warrants.
|
| +
|
| + indexlister must be configured, or no function is performed.
|
| + indexlister should be a callable that accepts the following parameters:
|
| + section: same as for staticdir (and implicitly calculated for it)
|
| + dir: same as for staticdir, but already combined with root
|
| + path: combination of section and dir
|
| +
|
| + Other parameters that are configured for staticdirindex will be passed
|
| + on to indexlister.
|
| +
|
| + Should use priorty > than that of staticdir, so that only directories not
|
| + served by staticdir, call staticdirindex.
|
| +
|
| +"""
|
| + # first call old staticdir, and see if it does anything
|
| + sdret = staticdir( section, dir, root, match, content_types, index )
|
| + if sdret:
|
| + return True
|
| +
|
| + # if not, then see if we are configured to do anything
|
| + if indexlister is None:
|
| + return False
|
| +
|
| + req = cherrypy.request
|
| + response = cherrypy.response
|
| +
|
| + match = indexlistermatch
|
| +
|
| + # N.B. filename ending in a slash or not does not imply a directory
|
| + # the following block of code directly copied from static.py staticdir
|
| + if match and not re.search(match, cherrypy.request.path_info):
|
| + return False
|
| +
|
| + # Allow the use of '~' to refer to a user's home directory.
|
| + dir = os.path.expanduser(dir)
|
| +
|
| + # If dir is relative, make absolute using "root".
|
| + if not os.path.isabs(dir):
|
| + if not root:
|
| + msg = "Static dir requires an absolute dir (or root)."
|
| + raise ValueError(msg)
|
| + dir = os.path.join(root, dir)
|
| +
|
| + # Determine where we are in the object tree relative to 'section'
|
| + # (where the static tool was defined).
|
| + if section == 'global':
|
| + section = "/"
|
| + section = section.rstrip(r"\/")
|
| + branch = cherrypy.request.path_info[len(section) + 1:]
|
| + branch = urllib.unquote(branch.lstrip(r"\/"))
|
| +
|
| + # If branch is "", filename will end in a slash
|
| + filename = os.path.join(dir, branch)
|
| +
|
| + # There's a chance that the branch pulled from the URL might
|
| + # have ".." or similar uplevel attacks in it. Check that the final
|
| + # filename is a child of dir.
|
| + if not os.path.normpath(filename).startswith(os.path.normpath(dir)):
|
| + raise cherrypy.HTTPError(403) # Forbidden
|
| + # the above block of code directly copied from static.py staticdir
|
| + # N.B. filename ending in a slash or not does not imply a directory
|
| +
|
| + # Check if path is a directory.
|
| +
|
| + path = filename
|
| + # The following block of code copied from static.py serve_file
|
| +
|
| + # If path is relative, users should fix it by making path absolute.
|
| + # That is, CherryPy should not guess where the application root is.
|
| + # It certainly should *not* use cwd (since CP may be invoked from a
|
| + # variety of paths). If using tools.static, you can make your relative
|
| + # paths become absolute by supplying a value for "tools.static.root".
|
| + if not os.path.isabs(path):
|
| + raise ValueError("'%s' is not an absolute path." % path)
|
| +
|
| + try:
|
| + st = os.stat(path)
|
| + except OSError:
|
| + # The above block of code copied from static.py serve_file
|
| +
|
| + return False
|
| +
|
| + if stat.S_ISDIR(st.st_mode):
|
| +
|
| + # Set the Last-Modified response header, so that
|
| + # modified-since validation code can work.
|
| + response.headers['Last-Modified'] = http.HTTPDate(st.st_mtime)
|
| + cptools.validate_since()
|
| + response.body = indexlister( section=section, dir=dir, path=path,
|
| + **kwargs )
|
| + response.headers['Content-Type'] = 'text/html'
|
| + req.is_index = True
|
| + return True
|
| +
|
| + return False
|
| +
|
| +# Replace the real staticdir with our version
|
| +cherrypy.tools.staticdir = cherrypy._cptools.HandlerTool( staticdirindex )
|
|
|