| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 |
"""Directory listing.""" |
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
import os |
|---|
| 8 |
import urllib |
|---|
| 9 |
import stat |
|---|
| 10 |
import time |
|---|
| 11 |
|
|---|
| 12 |
|
|---|
| 13 |
from twisted.web2 import iweb, resource, http, http_headers |
|---|
| 14 |
|
|---|
| 15 |
def formatFileSize(size): |
|---|
| 16 |
if size < 1024: |
|---|
| 17 |
return '%i' % size |
|---|
| 18 |
elif size < (1024**2): |
|---|
| 19 |
return '%iK' % (size / 1024) |
|---|
| 20 |
elif size < (1024**3): |
|---|
| 21 |
return '%iM' % (size / (1024**2)) |
|---|
| 22 |
else: |
|---|
| 23 |
return '%iG' % (size / (1024**3)) |
|---|
| 24 |
|
|---|
| 25 |
class DirectoryLister(resource.Resource): |
|---|
| 26 |
def __init__(self, pathname, dirs=None, |
|---|
| 27 |
contentTypes={}, |
|---|
| 28 |
contentEncodings={}, |
|---|
| 29 |
defaultType='text/html'): |
|---|
| 30 |
self.contentTypes = contentTypes |
|---|
| 31 |
self.contentEncodings = contentEncodings |
|---|
| 32 |
self.defaultType = defaultType |
|---|
| 33 |
|
|---|
| 34 |
self.dirs = dirs |
|---|
| 35 |
self.path = pathname |
|---|
| 36 |
resource.Resource.__init__(self) |
|---|
| 37 |
|
|---|
| 38 |
def data_listing(self, request, data): |
|---|
| 39 |
if self.dirs is None: |
|---|
| 40 |
directory = os.listdir(self.path) |
|---|
| 41 |
directory.sort() |
|---|
| 42 |
else: |
|---|
| 43 |
directory = self.dirs |
|---|
| 44 |
|
|---|
| 45 |
files = [] |
|---|
| 46 |
|
|---|
| 47 |
for path in directory: |
|---|
| 48 |
url = urllib.quote(path, '/') |
|---|
| 49 |
fullpath = os.path.join(self.path, path) |
|---|
| 50 |
try: |
|---|
| 51 |
st = os.stat(fullpath) |
|---|
| 52 |
except OSError: |
|---|
| 53 |
continue |
|---|
| 54 |
if stat.S_ISDIR(st.st_mode): |
|---|
| 55 |
url = url + '/' |
|---|
| 56 |
files.append({ |
|---|
| 57 |
'link': url, |
|---|
| 58 |
'linktext': path + "/", |
|---|
| 59 |
'size': '', |
|---|
| 60 |
'type': '-', |
|---|
| 61 |
'lastmod': time.strftime("%Y-%b-%d %H:%M", time.localtime(st.st_mtime)) |
|---|
| 62 |
}) |
|---|
| 63 |
else: |
|---|
| 64 |
from twisted.web2.static import getTypeAndEncoding |
|---|
| 65 |
mimetype, encoding = getTypeAndEncoding( |
|---|
| 66 |
path, |
|---|
| 67 |
self.contentTypes, self.contentEncodings, self.defaultType) |
|---|
| 68 |
|
|---|
| 69 |
filesize = st.st_size |
|---|
| 70 |
files.append({ |
|---|
| 71 |
'link': url, |
|---|
| 72 |
'linktext': path, |
|---|
| 73 |
'size': formatFileSize(filesize), |
|---|
| 74 |
'type': mimetype, |
|---|
| 75 |
'lastmod': time.strftime("%Y-%b-%d %H:%M", time.localtime(st.st_mtime)) |
|---|
| 76 |
}) |
|---|
| 77 |
|
|---|
| 78 |
return files |
|---|
| 79 |
|
|---|
| 80 |
def __repr__(self): |
|---|
| 81 |
return '<DirectoryLister of %r>' % self.path |
|---|
| 82 |
|
|---|
| 83 |
__str__ = __repr__ |
|---|
| 84 |
|
|---|
| 85 |
|
|---|
| 86 |
def render(self, request): |
|---|
| 87 |
title = "Directory listing for %s" % urllib.unquote(request.path) |
|---|
| 88 |
|
|---|
| 89 |
s= """<html><head><title>%s</title><style> |
|---|
| 90 |
th, .even td, .odd td { padding-right: 0.5em; font-family: monospace} |
|---|
| 91 |
.even-dir { background-color: #efe0ef } |
|---|
| 92 |
.even { background-color: #eee } |
|---|
| 93 |
.odd-dir {background-color: #f0d0ef } |
|---|
| 94 |
.odd { background-color: #dedede } |
|---|
| 95 |
.icon { text-align: center } |
|---|
| 96 |
.listing { |
|---|
| 97 |
margin-left: auto; |
|---|
| 98 |
margin-right: auto; |
|---|
| 99 |
width: 50%%; |
|---|
| 100 |
padding: 0.1em; |
|---|
| 101 |
} |
|---|
| 102 |
|
|---|
| 103 |
body { border: 0; padding: 0; margin: 0; background-color: #efefef;} |
|---|
| 104 |
h1 {padding: 0.1em; background-color: #777; color: white; border-bottom: thin white dashed;} |
|---|
| 105 |
</style></head><body><div class="directory-listing"><h1>%s</h1>""" % (title,title) |
|---|
| 106 |
s+="<table>" |
|---|
| 107 |
s+="<tr><th>Filename</th><th>Size</th><th>Last Modified</th><th>File Type</th></tr>" |
|---|
| 108 |
even = False |
|---|
| 109 |
for row in self.data_listing(request, None): |
|---|
| 110 |
s+='<tr class="%s">' % (even and 'even' or 'odd',) |
|---|
| 111 |
s+='<td><a href="%(link)s">%(linktext)s</a></td><td align="right">%(size)s</td><td>%(lastmod)s</td><td>%(type)s</td></tr>' % row |
|---|
| 112 |
even = not even |
|---|
| 113 |
|
|---|
| 114 |
s+="</table></div></body></html>" |
|---|
| 115 |
response = http.Response(200, {}, s) |
|---|
| 116 |
response.headers.setHeader("content-type", http_headers.MimeType('text', 'html')) |
|---|
| 117 |
return response |
|---|
| 118 |
|
|---|
| 119 |
__all__ = ['DirectoryLister'] |
|---|