Added SERVER_NAME as an immediate request variable.
[wrw.git] / wrw / proto.py
CommitLineData
5ef9e488 1statusinfo = {
001ec99e
FT
2 400: ("Bad Request", "Invalid HTTP request."),
3 401: ("Unauthorized", "Authentication must be provided for the requested resource."),
4 403: ("Forbidden", "You are not authorized to request the requested resource."),
5ef9e488 5 404: ("Not Found", "The requested resource was not found."),
001ec99e
FT
6 405: ("Method Not Allowed", "The request method is not recognized or permitted by the requested resource."),
7 500: ("Server Error", "An internal error occurred."),
8 501: ("Not Implemented", "The requested functionality has not been implemented."),
9 503: ("Service Unavailable", "Service is being denied at this time."),
5ef9e488
FT
10 }
11
12def httpdate(ts):
13 return time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime(ts))
14
15def phttpdate(dstr):
16 tz = dstr[-6:]
17 dstr = dstr[:-6]
18 if tz[0] != " " or (tz[1] != "+" and tz[1] != "-") or not tz[2:].isdigit():
19 return None
20 tz = int(tz[1:])
21 tz = (((tz / 100) * 60) + (tz % 100)) * 60
22 return time.mktime(time.strptime(dstr, "%a, %d %b %Y %H:%M:%S")) - tz - time.altzone
23
eed3cf12
FT
24def pmimehead(hstr):
25 def pws(p):
26 while p < len(hstr) and hstr[p].isspace():
27 p += 1
28 return p
29 def token(p, sep):
30 buf = ""
31 p = pws(p)
32 if p >= len(hstr):
33 return "", p
34 if hstr[p] == '"':
35 p += 1
36 while p < len(hstr):
37 if hstr[p] == '\\':
38 p += 1
39 if p < len(hstr):
40 buf += hstr[p]
41 p += 1
42 else:
43 break
44 elif hstr[p] == '"':
45 p += 1
46 break
47 else:
48 buf += hstr[p]
49 p += 1
50 return buf, pws(p)
51 else:
52 while p < len(hstr):
53 if hstr[p] in sep:
54 break
55 buf += hstr[p]
56 p += 1
57 return buf.strip(), pws(p)
58 p = 0
59 val, p = token(p, ";")
60 pars = {}
61 while p < len(hstr):
62 if hstr[p] != ';':
63 break
64 p += 1
65 k, p = token(p, "=")
66 if k == "" or hstr[p:p + 1] != '=':
67 break
68 p += 1
69 v, p = token(p, ';')
ea18777a 70 pars[k.lower()] = v
eed3cf12
FT
71 return val, pars
72
5ef9e488
FT
73def htmlq(html):
74 ret = ""
75 for c in html:
76 if c == "&":
77 ret += "&amp;"
78 elif c == "<":
79 ret += "&lt;"
80 elif c == ">":
81 ret += "&gt;"
82 else:
83 ret += c
84 return ret
85
86def urlq(url):
87 ret = ""
88 for c in url:
89 if c == "&" or c == "=" or c == "#" or c == "?" or c == "/" or (ord(c) <= 32):
90 ret += "%%%02X" % ord(c)
91 else:
92 ret += c
93 return ret
94
bb80acbd
FT
95class urlerror(ValueError):
96 pass
97
98def parseurl(url):
99 p = url.find("://")
100 if p < 0:
101 raise urlerror("Protocol not found in absolute URL `%s'" % url)
102 proto = url[:p]
103 l = url.find("/", p + 3)
104 if l < 0:
105 raise urlerror("Local part not found in absolute URL `%s'" % url)
106 host = url[p + 3:l]
107 local = url[l:]
108 q = local.find("?")
109 if q < 0:
110 query = ""
111 else:
112 query = local[q + 1:]
113 local = local[:q]
114 return proto, host, local, query
115
116def consurl(proto, host, local, query = ""):
117 if len(local) < 1 and local[0] != '/':
118 raise urlerror("Local part of URL must begin with a slash")
119 ret = "%s://%s%s" % (proto, host, local)
120 if len(query) > 0:
121 ret += "?" + query
122 return ret
123
124def appendurl(url, other):
125 if "://" in other:
126 return other
127 proto, host, local, query = parseurl(url)
128 if len(other) > 0 and other[0] == '/':
129 return consurl(proto, host, other)
130 else:
131 p = local.rfind('/')
132 return consurl(proto, host, local[:p + 1] + other)
133
134def requrl(req):
135 host = req.ihead.get("Host", None)
136 if host is None:
137 raise Exception("Could not reconstruct URL because no Host header was sent")
138 proto = "http"
139 if req.https:
140 proto = "https"
141 if req.uri[0] != '/':
142 raise Exception("Malformed local part when reconstructing URL")
143 return "%s://%s%s" % (proto, host, req.uri)
144
5ef9e488
FT
145def parstring(pars = {}, **augment):
146 buf = ""
147 for key in pars:
148 if key in augment:
149 val = augment[key]
150 del augment[key]
151 else:
152 val = pars[key]
153 if buf != "": buf += "&"
154 buf += urlq(key) + "=" + urlq(str(val))
155 for key in augment:
156 if buf != "": buf += "&"
157 buf += urlq(key) + "=" + urlq(str(augment[key]))
158 return buf