From ee18c3e52e913182a95af3ce57afd9e753f9fab7 Mon Sep 17 00:00:00 2001 From: Sebastian Lohff Date: Wed, 20 Jun 2012 22:55:43 +0200 Subject: [PATCH] Replaced SimpleHTTPServer Handler with own handler A directory index looks not that well but isn't influenced by a index.htm(l) and presents more metadata than before. --- servefile | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 118 insertions(+), 7 deletions(-) diff --git a/servefile b/servefile index ad0eddd..8050408 100755 --- a/servefile +++ b/servefile @@ -12,8 +12,10 @@ import base64 import cgi import BaseHTTPServer import datetime +import mimetypes import urllib import os +import posixpath import re import SocketServer import socket @@ -286,6 +288,119 @@ class TarFileHandler(FileBaseHandler): return ".tar.bz2" raise ValueError("Unknown compression mode '%s'." % TarFileHandler.compression) + +class DirListingHandler(FileBaseHandler): + """ DOCUMENTATION MISSING """ + + targetDir = None + + def do_HEAD(self): + self.getFileOrDirectory(head=True) + + def do_GET(self): + self.getFileOrDirectory(head=False) + + def getFileOrDirectory(self, head=False): + path = self.getCleanPath() + + if os.path.isdir(path): + if not self.path.endswith('/'): + self.send_response(301) + self.send_header("Location", self.path + '/') + self.end_headers() + else: + self.sendDirectoryListing(path, head) + elif os.path.isfile(path): + if head: + (response, length) = self.getFileLength(path) + if length < 0: + self.send_response(response) + self.end_headers() + else: + self.send_response(200) + self.sendContentHeaders(self, path, length) + self.end_headers() + else: + self.sendFile(path, head) + else: + self.send_response(404) + self.end_headers() + + def sendDirectoryListing(self, path, head): + print "sending directory listing" + + header = """ + + + Index of %(path)s + + +

Index of %(path)s

+ + + """ % {'path': posixpath.normpath(urllib.unquote(self.path))} + footer = """
NameLast ModifiedSizeType
+
servefile %(version)s
+ +""" % {'version': __version__} + content = [] + for item in [".."] + os.listdir(path): + # create path to item + itemPath = os.path.join(path, item) + + # try to stat file for size, last modified... continue on error + stat = None + try: + stat = os.stat(itemPath) + except IOError: + continue + + # Strings to display on directory listing + lastModifiedDate = datetime.datetime.fromtimestamp(stat.st_mtime) + lastModified = lastModifiedDate.strftime("%Y-%m-%d %H:%M") + fileSize = "%.1f%s" % self.convertSize(stat.st_size) + (fileType, _) = mimetypes.guess_type(itemPath) + if not fileType: + fileType = "-" + + if os.path.isdir(itemPath): + item += "/" + fileType = "Directory" + content.append(""" + + %s + %s + %s + %s + + """ % (urllib.quote(item), item, lastModified, fileSize, fileType)) + + listing = header + "\n".join(content) + footer + + # write listing + self.send_response(200) + self.send_header("Content-Type", "text/html") + if head: + self.end_headers() + return + self.send_header("Content-Length", str(len(listing))) + self.end_headers() + self.wfile.write(listing) + + def convertSize(self, size): + ext = None + for ext in "BKMGT": + if size < 1024.0: + break + size /= 1024.0 + return (size, ext) + + def getCleanPath(self): + urlPath = posixpath.normpath(urllib.unquote(self.path)).strip("/") + path = os.path.join(self.targetDir, urlPath) + return path + + class FilePutter(BaseHTTPServer.BaseHTTPRequestHandler): """ Simple HTTP Server which allows uploading to a specified directory either via multipart/form-data or POST/PUT requests containing the file. @@ -665,7 +780,7 @@ class ServeFile(): self.dirCreated = True try: os.mkdir(self.target) - except IOError, OSError: + except (IOError, OSError): raise ServeFileException("Error: Could not create directory '%s' for uploads." % (self.target,) ) else: raise ServeFileException("Error: Upload directory already exists and is a file.") @@ -673,12 +788,8 @@ class ServeFile(): FilePutter.maxUploadSize = self.maxUploadSize handler = FilePutter elif self.serveMode == self.MODE_LISTDIR: - try: - os.chdir(self.target) - except OSError: - raise ServeFileException("Error: Could not change directory to '%s'." % self.target) - handler = SimpleHTTPServer.SimpleHTTPRequestHandler - + handler = DirListingHandler + handler.targetDir = self.target if self.auth: # do authentication