]> git.proxmox.com Git - mirror_edk2.git/blob - AppPkg/Applications/Python/Python-2.7.10/Lib/SimpleHTTPServer.py
AppPkg/Applications/Python/Python-2.7.10: Initial Checkin part 4/5.
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.10 / Lib / SimpleHTTPServer.py
1 """Simple HTTP Server.
2
3 This module builds on BaseHTTPServer by implementing the standard GET
4 and HEAD requests in a fairly straightforward manner.
5
6 """
7
8
9 __version__ = "0.6"
10
11 __all__ = ["SimpleHTTPRequestHandler"]
12
13 import os
14 import posixpath
15 import BaseHTTPServer
16 import urllib
17 import urlparse
18 import cgi
19 import sys
20 import shutil
21 import mimetypes
22 try:
23 from cStringIO import StringIO
24 except ImportError:
25 from StringIO import StringIO
26
27
28 class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
29
30 """Simple HTTP request handler with GET and HEAD commands.
31
32 This serves files from the current directory and any of its
33 subdirectories. The MIME type for files is determined by
34 calling the .guess_type() method.
35
36 The GET and HEAD requests are identical except that the HEAD
37 request omits the actual contents of the file.
38
39 """
40
41 server_version = "SimpleHTTP/" + __version__
42
43 def do_GET(self):
44 """Serve a GET request."""
45 f = self.send_head()
46 if f:
47 try:
48 self.copyfile(f, self.wfile)
49 finally:
50 f.close()
51
52 def do_HEAD(self):
53 """Serve a HEAD request."""
54 f = self.send_head()
55 if f:
56 f.close()
57
58 def send_head(self):
59 """Common code for GET and HEAD commands.
60
61 This sends the response code and MIME headers.
62
63 Return value is either a file object (which has to be copied
64 to the outputfile by the caller unless the command was HEAD,
65 and must be closed by the caller under all circumstances), or
66 None, in which case the caller has nothing further to do.
67
68 """
69 path = self.translate_path(self.path)
70 f = None
71 if os.path.isdir(path):
72 parts = urlparse.urlsplit(self.path)
73 if not parts.path.endswith('/'):
74 # redirect browser - doing basically what apache does
75 self.send_response(301)
76 new_parts = (parts[0], parts[1], parts[2] + '/',
77 parts[3], parts[4])
78 new_url = urlparse.urlunsplit(new_parts)
79 self.send_header("Location", new_url)
80 self.end_headers()
81 return None
82 for index in "index.html", "index.htm":
83 index = os.path.join(path, index)
84 if os.path.exists(index):
85 path = index
86 break
87 else:
88 return self.list_directory(path)
89 ctype = self.guess_type(path)
90 try:
91 # Always read in binary mode. Opening files in text mode may cause
92 # newline translations, making the actual size of the content
93 # transmitted *less* than the content-length!
94 f = open(path, 'rb')
95 except IOError:
96 self.send_error(404, "File not found")
97 return None
98 try:
99 self.send_response(200)
100 self.send_header("Content-type", ctype)
101 fs = os.fstat(f.fileno())
102 self.send_header("Content-Length", str(fs[6]))
103 self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
104 self.end_headers()
105 return f
106 except:
107 f.close()
108 raise
109
110 def list_directory(self, path):
111 """Helper to produce a directory listing (absent index.html).
112
113 Return value is either a file object, or None (indicating an
114 error). In either case, the headers are sent, making the
115 interface the same as for send_head().
116
117 """
118 try:
119 list = os.listdir(path)
120 except os.error:
121 self.send_error(404, "No permission to list directory")
122 return None
123 list.sort(key=lambda a: a.lower())
124 f = StringIO()
125 displaypath = cgi.escape(urllib.unquote(self.path))
126 f.write('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">')
127 f.write("<html>\n<title>Directory listing for %s</title>\n" % displaypath)
128 f.write("<body>\n<h2>Directory listing for %s</h2>\n" % displaypath)
129 f.write("<hr>\n<ul>\n")
130 for name in list:
131 fullname = os.path.join(path, name)
132 displayname = linkname = name
133 # Append / for directories or @ for symbolic links
134 if os.path.isdir(fullname):
135 displayname = name + "/"
136 linkname = name + "/"
137 if os.path.islink(fullname):
138 displayname = name + "@"
139 # Note: a link to a directory displays with @ and links with /
140 f.write('<li><a href="%s">%s</a>\n'
141 % (urllib.quote(linkname), cgi.escape(displayname)))
142 f.write("</ul>\n<hr>\n</body>\n</html>\n")
143 length = f.tell()
144 f.seek(0)
145 self.send_response(200)
146 encoding = sys.getfilesystemencoding()
147 self.send_header("Content-type", "text/html; charset=%s" % encoding)
148 self.send_header("Content-Length", str(length))
149 self.end_headers()
150 return f
151
152 def translate_path(self, path):
153 """Translate a /-separated PATH to the local filename syntax.
154
155 Components that mean special things to the local file system
156 (e.g. drive or directory names) are ignored. (XXX They should
157 probably be diagnosed.)
158
159 """
160 # abandon query parameters
161 path = path.split('?',1)[0]
162 path = path.split('#',1)[0]
163 # Don't forget explicit trailing slash when normalizing. Issue17324
164 trailing_slash = path.rstrip().endswith('/')
165 path = posixpath.normpath(urllib.unquote(path))
166 words = path.split('/')
167 words = filter(None, words)
168 path = os.getcwd()
169 for word in words:
170 drive, word = os.path.splitdrive(word)
171 head, word = os.path.split(word)
172 if word in (os.curdir, os.pardir): continue
173 path = os.path.join(path, word)
174 if trailing_slash:
175 path += '/'
176 return path
177
178 def copyfile(self, source, outputfile):
179 """Copy all data between two file objects.
180
181 The SOURCE argument is a file object open for reading
182 (or anything with a read() method) and the DESTINATION
183 argument is a file object open for writing (or
184 anything with a write() method).
185
186 The only reason for overriding this would be to change
187 the block size or perhaps to replace newlines by CRLF
188 -- note however that this the default server uses this
189 to copy binary data as well.
190
191 """
192 shutil.copyfileobj(source, outputfile)
193
194 def guess_type(self, path):
195 """Guess the type of a file.
196
197 Argument is a PATH (a filename).
198
199 Return value is a string of the form type/subtype,
200 usable for a MIME Content-type header.
201
202 The default implementation looks the file's extension
203 up in the table self.extensions_map, using application/octet-stream
204 as a default; however it would be permissible (if
205 slow) to look inside the data to make a better guess.
206
207 """
208
209 base, ext = posixpath.splitext(path)
210 if ext in self.extensions_map:
211 return self.extensions_map[ext]
212 ext = ext.lower()
213 if ext in self.extensions_map:
214 return self.extensions_map[ext]
215 else:
216 return self.extensions_map['']
217
218 if not mimetypes.inited:
219 mimetypes.init() # try to read system mime.types
220 extensions_map = mimetypes.types_map.copy()
221 extensions_map.update({
222 '': 'application/octet-stream', # Default
223 '.py': 'text/plain',
224 '.c': 'text/plain',
225 '.h': 'text/plain',
226 })
227
228
229 def test(HandlerClass = SimpleHTTPRequestHandler,
230 ServerClass = BaseHTTPServer.HTTPServer):
231 BaseHTTPServer.test(HandlerClass, ServerClass)
232
233
234 if __name__ == '__main__':
235 test()