-import time
+import time, calendar, collections, binascii, base64
statusinfo = {
400: ("Bad Request", "Invalid HTTP request."),
return None
tz = int(tz[1:])
tz = (((tz / 100) * 60) + (tz % 100)) * 60
- return time.mktime(time.strptime(dstr, "%a, %d %b %Y %H:%M:%S")) - tz - time.altzone
+ return calendar.timegm(time.strptime(dstr, "%a, %d %b %Y %H:%M:%S")) - tz
def pmimehead(hstr):
def pws(p):
</body>
</html>
""" % (title, title, htmlq(msg))
+ buf = buf.encode("us-ascii")
startreq("%i %s" % (code, title), [("Content-Type", "text/html"), ("Content-Length", str(len(buf)))])
return [buf]
def urlq(url):
+ if isinstance(url, str):
+ url = url.encode("utf-8")
ret = ""
- invalid = "&=#?/\"'"
+ invalid = b"%;&=#?/\"'"
for c in url:
- if c in invalid or (ord(c) <= 32):
- ret += "%%%02X" % ord(c)
+ if c in invalid or (c <= 32) or (c >= 128):
+ ret += "%%%02X" % c
else:
- ret += c
+ ret += chr(c)
return ret
class urlerror(ValueError):
raise Exception("Malformed local part when reconstructing URL")
return siteurl(req) + req.uriname[1:]
-def requrl(req):
+def requrl(req, qs=True):
s = siteurl(req)
if req.uri[0] != '/':
raise Exception("Malformed local part when reconstructing URL")
- return siteurl(req) + req.uri[1:]
+ pf = req.uri[1:]
+ if not qs:
+ p = pf.find('?')
+ if not p < 0:
+ pf = pf[:p]
+ return siteurl(req) + pf
def parstring(pars={}, **augment):
buf = ""
del augment[key]
else:
val = pars[key]
+ if val is None:
+ continue
if buf != "": buf += "&"
buf += urlq(key) + "=" + urlq(str(val))
- for key in augment:
+ for key, val in augment.items():
+ if val is None:
+ continue
if buf != "": buf += "&"
- buf += urlq(key) + "=" + urlq(str(augment[key]))
+ buf += urlq(key) + "=" + urlq(str(val))
return buf
def parurl(url, pars={}, **augment):
qs = parstring(pars, **augment)
if qs != "":
- return url + "?" + qs
+ return url + ("&" if "?" in url else "?") + qs
else:
return url
+
+# Wrap these, since binascii is a bit funky. :P
+def enhex(bs):
+ return base64.b16encode(bs).decode("us-ascii")
+def unhex(es):
+ if not isinstance(es, collections.ByteString):
+ try:
+ es = es.encode("us-ascii")
+ except UnicodeError:
+ raise binascii.Error("non-ascii character in hex-string")
+ return base64.b16decode(es)
+def enb32(bs):
+ return base64.b32encode(bs).decode("us-ascii")
+def unb32(es):
+ if not isinstance(es, collections.ByteString):
+ try:
+ es = es.encode("us-ascii")
+ except UnicodeError:
+ raise binascii.Error("non-ascii character in base32-string")
+ if (len(es) % 8) != 0:
+ es += b"=" * (8 - (len(es) % 8))
+ es = es.upper() # The whole point of Base32 is that it's case-insensitive :P
+ return base64.b32decode(es)
+def enb64(bs):
+ return base64.b64encode(bs).decode("us-ascii")
+def unb64(es):
+ if not isinstance(es, collections.ByteString):
+ try:
+ es = es.encode("us-ascii")
+ except UnicodeError:
+ raise binascii.Error("non-ascii character in base64-string")
+ if (len(es) % 4) != 0:
+ es += b"=" * (4 - (len(es) % 4))
+ return base64.b64decode(es)