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