|
6 | 6 | """ |
7 | 7 |
|
8 | 8 |
|
9 | | -__version__ = "0.3" |
| 9 | +__version__ = "0.4" |
10 | 10 |
|
11 | 11 |
|
12 | 12 | import os |
13 | 13 | import string |
14 | 14 | import posixpath |
15 | 15 | import BaseHTTPServer |
16 | 16 | import urllib |
| 17 | +import cgi |
| 18 | +from StringIO import StringIO |
17 | 19 |
|
18 | 20 |
|
19 | 21 | class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): |
@@ -57,16 +59,62 @@ def send_head(self): |
57 | 59 |
|
58 | 60 | """ |
59 | 61 | path = self.translate_path(self.path) |
| 62 | + f = None |
60 | 63 | if os.path.isdir(path): |
61 | | - self.send_error(403, "Directory listing not supported") |
62 | | - return None |
| 64 | + for index in "index.html", "index.htm": |
| 65 | + index = os.path.join(path, index) |
| 66 | + if os.path.exists(index): |
| 67 | + path = index |
| 68 | + break |
| 69 | + else: |
| 70 | + return self.list_directory(path) |
| 71 | + ctype = self.guess_type(path) |
| 72 | + if ctype.startswith('text/'): |
| 73 | + mode = 'r' |
| 74 | + else: |
| 75 | + mode = 'rb' |
63 | 76 | try: |
64 | | - f = open(path, 'rb') |
| 77 | + f = open(path, mode) |
65 | 78 | except IOError: |
66 | 79 | self.send_error(404, "File not found") |
67 | 80 | return None |
68 | 81 | self.send_response(200) |
69 | | - self.send_header("Content-type", self.guess_type(path)) |
| 82 | + self.send_header("Content-type", ctype) |
| 83 | + self.end_headers() |
| 84 | + return f |
| 85 | + |
| 86 | + def list_directory(self, path): |
| 87 | + """Helper to produce a directory listing (absent index.html). |
| 88 | +
|
| 89 | + Return value is either a file object, or None (indicating an |
| 90 | + error). In either case, the headers are sent, making the |
| 91 | + interface the same as for send_head(). |
| 92 | +
|
| 93 | + """ |
| 94 | + try: |
| 95 | + list = os.listdir(path) |
| 96 | + except os.error: |
| 97 | + self.send_error(404, "No permission to list directory"); |
| 98 | + return None |
| 99 | + list.sort(lambda a, b: cmp(a.lower(), b.lower())) |
| 100 | + f = StringIO() |
| 101 | + f.write("<h2>Directory listing for %s</h2>\n" % self.path) |
| 102 | + f.write("<hr>\n<ul>\n") |
| 103 | + for name in list: |
| 104 | + fullname = os.path.join(path, name) |
| 105 | + displayname = linkname = name = cgi.escape(name) |
| 106 | + # Append / for directories or @ for symbolic links |
| 107 | + if os.path.isdir(fullname): |
| 108 | + displayname = name + "/" |
| 109 | + linkname = name + os.sep |
| 110 | + if os.path.islink(fullname): |
| 111 | + displayname = name + "@" |
| 112 | + # Note: a link to a directory displays with @ and links with / |
| 113 | + f.write('<li><a href="%s">%s</a>\n' % (linkname, displayname)) |
| 114 | + f.write("</ul>\n<hr>\n") |
| 115 | + f.seek(0) |
| 116 | + self.send_response(200) |
| 117 | + self.send_header("Content-type", "text/html") |
70 | 118 | self.end_headers() |
71 | 119 | return f |
72 | 120 |
|
|
0 commit comments