Added some URL manipulation functions to wrw.proto.
[wrw.git] / wrw / proto.py
CommitLineData
5ef9e488
FT
1statusinfo = {
2 400: ("Bad Request", "Your issued HTTP request is invalid."),
3 403: ("Forbidden", "You are not authorized to view the requested resource."),
4 404: ("Not Found", "The requested resource was not found."),
5 500: ("Server Error", "An internal error occurred.")
6 }
7
8def httpdate(ts):
9 return time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime(ts))
10
11def phttpdate(dstr):
12 tz = dstr[-6:]
13 dstr = dstr[:-6]
14 if tz[0] != " " or (tz[1] != "+" and tz[1] != "-") or not tz[2:].isdigit():
15 return None
16 tz = int(tz[1:])
17 tz = (((tz / 100) * 60) + (tz % 100)) * 60
18 return time.mktime(time.strptime(dstr, "%a, %d %b %Y %H:%M:%S")) - tz - time.altzone
19
20def htmlq(html):
21 ret = ""
22 for c in html:
23 if c == "&":
24 ret += "&"
25 elif c == "<":
26 ret += "&lt;"
27 elif c == ">":
28 ret += "&gt;"
29 else:
30 ret += c
31 return ret
32
33def urlq(url):
34 ret = ""
35 for c in url:
36 if c == "&" or c == "=" or c == "#" or c == "?" or c == "/" or (ord(c) <= 32):
37 ret += "%%%02X" % ord(c)
38 else:
39 ret += c
40 return ret
41
bb80acbd
FT
42class urlerror(ValueError):
43 pass
44
45def parseurl(url):
46 p = url.find("://")
47 if p < 0:
48 raise urlerror("Protocol not found in absolute URL `%s'" % url)
49 proto = url[:p]
50 l = url.find("/", p + 3)
51 if l < 0:
52 raise urlerror("Local part not found in absolute URL `%s'" % url)
53 host = url[p + 3:l]
54 local = url[l:]
55 q = local.find("?")
56 if q < 0:
57 query = ""
58 else:
59 query = local[q + 1:]
60 local = local[:q]
61 return proto, host, local, query
62
63def consurl(proto, host, local, query = ""):
64 if len(local) < 1 and local[0] != '/':
65 raise urlerror("Local part of URL must begin with a slash")
66 ret = "%s://%s%s" % (proto, host, local)
67 if len(query) > 0:
68 ret += "?" + query
69 return ret
70
71def appendurl(url, other):
72 if "://" in other:
73 return other
74 proto, host, local, query = parseurl(url)
75 if len(other) > 0 and other[0] == '/':
76 return consurl(proto, host, other)
77 else:
78 p = local.rfind('/')
79 return consurl(proto, host, local[:p + 1] + other)
80
81def requrl(req):
82 host = req.ihead.get("Host", None)
83 if host is None:
84 raise Exception("Could not reconstruct URL because no Host header was sent")
85 proto = "http"
86 if req.https:
87 proto = "https"
88 if req.uri[0] != '/':
89 raise Exception("Malformed local part when reconstructing URL")
90 return "%s://%s%s" % (proto, host, req.uri)
91
5ef9e488
FT
92def parstring(pars = {}, **augment):
93 buf = ""
94 for key in pars:
95 if key in augment:
96 val = augment[key]
97 del augment[key]
98 else:
99 val = pars[key]
100 if buf != "": buf += "&"
101 buf += urlq(key) + "=" + urlq(str(val))
102 for key in augment:
103 if buf != "": buf += "&"
104 buf += urlq(key) + "=" + urlq(str(augment[key]))
105 return buf