forked from seba/servefile
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.
This commit is contained in:
parent
b11710da39
commit
ee18c3e52e
125
servefile
125
servefile
|
@ -12,8 +12,10 @@ import base64
|
||||||
import cgi
|
import cgi
|
||||||
import BaseHTTPServer
|
import BaseHTTPServer
|
||||||
import datetime
|
import datetime
|
||||||
|
import mimetypes
|
||||||
import urllib
|
import urllib
|
||||||
import os
|
import os
|
||||||
|
import posixpath
|
||||||
import re
|
import re
|
||||||
import SocketServer
|
import SocketServer
|
||||||
import socket
|
import socket
|
||||||
|
@ -286,6 +288,119 @@ class TarFileHandler(FileBaseHandler):
|
||||||
return ".tar.bz2"
|
return ".tar.bz2"
|
||||||
raise ValueError("Unknown compression mode '%s'." % TarFileHandler.compression)
|
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 = """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Index of %(path)s</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Index of %(path)s</h1>
|
||||||
|
<table summary="Directory Listing" cellpadding="0" cellspacing="0">
|
||||||
|
<thead><tr><th class="n">Name</th><th class="m">Last Modified</th><th class="s">Size</th><th class="t">Type</th></tr></thead>
|
||||||
|
""" % {'path': posixpath.normpath(urllib.unquote(self.path))}
|
||||||
|
footer = """</table>
|
||||||
|
<address>servefile %(version)s</address>
|
||||||
|
</body>
|
||||||
|
</html>""" % {'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("""
|
||||||
|
<tr>
|
||||||
|
<td><a href="%s">%s</a></td>
|
||||||
|
<td>%s</td>
|
||||||
|
<td>%s</td>
|
||||||
|
<td>%s</td>
|
||||||
|
</tr>
|
||||||
|
""" % (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):
|
class FilePutter(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||||
""" Simple HTTP Server which allows uploading to a specified directory
|
""" Simple HTTP Server which allows uploading to a specified directory
|
||||||
either via multipart/form-data or POST/PUT requests containing the file.
|
either via multipart/form-data or POST/PUT requests containing the file.
|
||||||
|
@ -665,7 +780,7 @@ class ServeFile():
|
||||||
self.dirCreated = True
|
self.dirCreated = True
|
||||||
try:
|
try:
|
||||||
os.mkdir(self.target)
|
os.mkdir(self.target)
|
||||||
except IOError, OSError:
|
except (IOError, OSError):
|
||||||
raise ServeFileException("Error: Could not create directory '%s' for uploads." % (self.target,) )
|
raise ServeFileException("Error: Could not create directory '%s' for uploads." % (self.target,) )
|
||||||
else:
|
else:
|
||||||
raise ServeFileException("Error: Upload directory already exists and is a file.")
|
raise ServeFileException("Error: Upload directory already exists and is a file.")
|
||||||
|
@ -673,12 +788,8 @@ class ServeFile():
|
||||||
FilePutter.maxUploadSize = self.maxUploadSize
|
FilePutter.maxUploadSize = self.maxUploadSize
|
||||||
handler = FilePutter
|
handler = FilePutter
|
||||||
elif self.serveMode == self.MODE_LISTDIR:
|
elif self.serveMode == self.MODE_LISTDIR:
|
||||||
try:
|
handler = DirListingHandler
|
||||||
os.chdir(self.target)
|
handler.targetDir = self.target
|
||||||
except OSError:
|
|
||||||
raise ServeFileException("Error: Could not change directory to '%s'." % self.target)
|
|
||||||
handler = SimpleHTTPServer.SimpleHTTPRequestHandler
|
|
||||||
|
|
||||||
|
|
||||||
if self.auth:
|
if self.auth:
|
||||||
# do authentication
|
# do authentication
|
||||||
|
|
Loading…
Reference in New Issue