Merge branch 'master' into python2
authorFredrik Tolf <fredrik@dolda2000.com>
Sun, 8 Nov 2015 03:01:08 +0000 (04:01 +0100)
committerFredrik Tolf <fredrik@dolda2000.com>
Sun, 8 Nov 2015 03:01:19 +0000 (04:01 +0100)
Conflicts:
wrw/auth.py
wrw/form.py
wrw/proto.py
wrw/session.py

wrw/auth.py
wrw/form.py
wrw/proto.py
wrw/session.py
wrw/util.py

index 4ae292d..bb0e0cd 100644 (file)
@@ -1,5 +1,5 @@
 import binascii, hashlib, threading, time
-import resp
+import resp, proto
 
 class unauthorized(resp.httperror):
     def __init__(self, challenge, message=None, detail=None):
@@ -31,7 +31,7 @@ def parsebasic(req):
     if mech != "basic":
         return None, None
     try:
-        raw = binascii.a2b_base64(data)
+        raw = proto.unb64(data)
     except binascii.Error:
         return None, None
     p = raw.find(":")
index da13a4a..76abab6 100644 (file)
@@ -7,9 +7,12 @@ def formparse(req):
     buf = {}
     buf.update(urlparse.parse_qsl(req.query))
     if req.ihead.get("Content-Type") == "application/x-www-form-urlencoded":
-        rbody = req.input.read(2 ** 20)
+        try:
+            rbody = req.input.read(2 ** 20)
+        except IOError as exc:
+            return exc
         if len(rbody) >= 2 ** 20:
-            raise ValueError("x-www-form-urlencoded data is absurdly long")
+            return ValueError("x-www-form-urlencoded data is absurdly long")
         buf.update(urlparse.parse_qsl(rbody))
     return buf
 
@@ -81,7 +84,9 @@ class formpart(object):
                 return ret
 
     def close(self):
-        self.fillbuf(-1)
+        while True:
+            if self.read(8192) == "":
+                break
 
     def __enter__(self):
         return self
@@ -152,5 +157,10 @@ class multipart(object):
         self.lastpart.parsehead()
         return self.lastpart
 
-def formdata(req):
-    return req.item(formparse)
+def formdata(req, onerror=Exception):
+    data = req.item(formparse)
+    if isinstance(data, Exception):
+        if onerror is Exception:
+            raise data
+        return onerror
+    return data
index 3dcf0d7..a67fa19 100644 (file)
@@ -1,4 +1,4 @@
-import time, calendar
+import time, calendar, collections, binascii, base64
 
 statusinfo = {
     400: ("Bad Request", "Invalid HTTP request."),
@@ -105,7 +105,7 @@ def urlq(url):
     if isinstance(url, unicode):
         url = url.encode("utf-8")
     ret = ""
-    invalid = "&=#?/\"'"
+    invalid = ";&=#?/\"'"
     for c in url:
         if c in invalid or (ord(c) <= 32) or (ord(c) >= 128):
             ret += "%%%02X" % ord(c)
@@ -194,3 +194,22 @@ def parurl(url, pars={}, **augment):
         return url + "?" + qs
     else:
         return url
+
+# Wrap these, since binascii is a bit funky. :P
+def enhex(bs):
+    return base64.b16encode(bs)
+def unhex(es):
+    return base64.b16decode(es)
+def enb32(bs):
+    return base64.b32encode(bs)
+def unb32(es):
+    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)
+def unb64(es):
+    if (len(es) % 4) != 0:
+        es += b"=" * (4 - (len(es) % 4))
+    return base64.b64decode(es)
index 0c585a3..476113a 100644 (file)
@@ -1,5 +1,9 @@
 import threading, time, pickle, random, os
+<<<<<<< HEAD
 import cookie, env
+=======
+from . import cookie, env, proto
+>>>>>>> master
 
 __all__ = ["db", "get"]
 
@@ -8,7 +12,7 @@ def gennonce(length):
 
 class session(object):
     def __init__(self, lock, expire=86400 * 7):
-        self.id = gennonce(16).encode("hex")
+        self.id = proto.enhex(gennonce(16))
         self.dict = {}
         self.lock = lock
         self.ctime = self.atime = self.mtime = int(time.time())
index 92b441c..22bce9d 100644 (file)
@@ -10,7 +10,10 @@ def wsgiwrap(callable):
 def formparams(callable):
     spec = inspect.getargspec(callable)
     def wrapper(req):
-        data = form.formdata(req)
+        try:
+            data = form.formdata(req)
+        except IOError:
+            raise resp.httperror(400, "Invalid request", "Form data was incomplete")
         args = dict(data.items())
         args["req"] = req
         if not spec.keywords: