Commit | Line | Data |
---|---|---|
5ef9e488 FT |
1 | statusinfo = { |
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 | ||
8 | def httpdate(ts): | |
9 | return time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime(ts)) | |
10 | ||
11 | def 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 | ||
20 | def htmlq(html): | |
21 | ret = "" | |
22 | for c in html: | |
23 | if c == "&": | |
24 | ret += "&" | |
25 | elif c == "<": | |
26 | ret += "<" | |
27 | elif c == ">": | |
28 | ret += ">" | |
29 | else: | |
30 | ret += c | |
31 | return ret | |
32 | ||
33 | def 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 |
42 | class urlerror(ValueError): |
43 | pass | |
44 | ||
45 | def 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 | ||
63 | def 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 | ||
71 | def 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 | ||
81 | def 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 |
92 | def 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 |