Merge branch 'master' into python3
authorFredrik Tolf <fredrik@dolda2000.com>
Wed, 14 Mar 2012 20:34:22 +0000 (21:34 +0100)
committerFredrik Tolf <fredrik@dolda2000.com>
Wed, 14 Mar 2012 20:34:22 +0000 (21:34 +0100)
Conflicts:
wrw/__init__.py

1  2 
wrw/__init__.py
wrw/form.py
wrw/req.py

diff --combined wrw/__init__.py
@@@ -1,6 -1,7 +1,7 @@@
  __all__ = ["wsgiwrap", "restart", "cookie", "formdata"]
  
 -import proto
 -from util import wsgiwrap, formparams, persession, sessiondata, autodirty, manudirty
 -from dispatch import restart
 -import cookie
 -from form import formdata
++from . import proto
 +from .util import wsgiwrap, formparams, persession, sessiondata, autodirty, manudirty
 +from .dispatch import restart
 +from . import cookie
 +from .form import formdata
diff --combined wrw/form.py
@@@ -1,4 -1,5 +1,5 @@@
  import cgi
 -import proto
++from . import proto
  
  __all__ = ["formdata"]
  
@@@ -31,10 -32,148 +32,148 @@@ class formwrap(object)
          return list(iter())
  
      def keys(self):
 -        return self.cf.keys()
 +        return list(self.cf.keys())
  
      def values(self):
          return [val for key, val in self.items()]
  
+ class badmultipart(Exception):
+     pass
+ class formpart(object):
+     def __init__(self, form):
+         self.form = form
+         self.buf = ""
+         self.eof = False
+         self.head = {}
+     def parsehead(self):
+         pass
+     def fillbuf(self, sz):
+         req = self.form.req
+         mboundary = "\r\n--" + self.form.boundary + "\r\n"
+         lboundary = "\r\n--" + self.form.boundary + "--\r\n"
+         while not self.eof:
+             p = self.form.buf.find(mboundary)
+             if p >= 0:
+                 self.buf += self.form.buf[:p]
+                 self.form.buf = self.form.buf[p + len(mboundary):]
+                 self.eof = True
+                 break
+             p = self.form.buf.find(lboundary)
+             if p >= 0:
+                 self.buf += self.form.buf[:p]
+                 self.form.buf = self.form.buf[p + len(lboundary):]
+                 self.eof = True
+                 self.form.eof = True
+                 break
+             self.buf += self.form.buf[:-len(lboundary)]
+             self.form.buf = self.form.buf[-len(lboundary):]
+             if sz >= 0 and len(self.buf) >= sz:
+                 break
+             while len(self.form.buf) <= len(lboundary):
+                 ret = req.env["wsgi.input"].read(8192)
+                 if ret == "":
+                     raise badmultipart("Missing last multipart boundary")
+                 self.form.buf += ret
+     def read(self, limit = -1):
+         self.fillbuf(limit)
+         if limit >= 0:
+             ret = self.buf[:limit]
+             self.buf = self.buf[limit:]
+         else:
+             ret = self.buf
+             self.buf = ""
+         return ret
+     def readline(self, limit = -1):
+         last = 0
+         while True:
+             p = self.buf.find('\n', last)
+             if p < 0:
+                 if self.eof:
+                     ret = self.buf
+                     self.buf = ""
+                     return ret
+                 last = len(self.buf)
+                 self.fillbuf(last + 128)
+             else:
+                 ret = self.buf[:p + 1]
+                 self.buf = self.buf[p + 1:]
+                 return ret
+     def close(self):
+         self.fillbuf(-1)
+     def __enter__(self):
+         return self
+     def __exit__(self, *excinfo):
+         return False
+     def parsehead(self):
+         def headline():
+             ln = self.readline(256)
+             if ln[-1] != '\n':
+                 raise badmultipart("Too long header line in part")
+             return ln.rstrip()
+         ln = headline()
+         while True:
+             if ln == "":
+                 break
+             buf = ln
+             while True:
+                 ln = headline()
+                 if not ln[1:].isspace():
+                     break
+                 buf += ln.lstrip()
+             p = buf.find(':')
+             if p < 0:
+                 raise badmultipart("Malformed multipart header line")
+             self.head[buf[:p].strip().lower()] = buf[p + 1:].lstrip()
+         val, par = proto.pmimehead(self.head.get("content-disposition", ""))
+         if val != "form-data":
+             raise badmultipart("Unexpected Content-Disposition in form part: %r" % val)
+         if not "name" in par:
+             raise badmultipart("Missing name in form part")
+         self.name = par["name"]
+         self.filename = par.get("filename")
+         val, par = proto.pmimehead(self.head.get("content-type", ""))
+         self.ctype = val
+         self.charset = par.get("charset")
+         encoding = self.head.get("content-transfer-encoding", "binary")
+         if encoding != "binary":
+             raise badmultipart("Form part uses unexpected transfer encoding: %r" % encoding)
+ class multipart(object):
+     def __init__(self, req):
+         val, par = proto.pmimehead(req.ihead.get("Content-Type", ""))
+         if req.method != "POST" or val != "multipart/form-data":
+             raise badmultipart("Request is not a multipart form")
+         if "boundary" not in par:
+             raise badmultipart("Multipart form lacks boundary")
+         self.boundary = par["boundary"]
+         self.req = req
+         self.buf = "\r\n"
+         self.eof = False
+         self.lastpart = formpart(self)
+         self.lastpart.close()
+     def __iter__(self):
+         return self
+     def next(self):
+         if not self.lastpart.eof:
+             raise RuntimeError("All form parts must be read entirely")
+         if self.eof:
+             raise StopIteration()
+         self.lastpart = formpart(self)
+         self.lastpart.parsehead()
+         return self.lastpart
  def formdata(req):
      return req.item(formwrap)
diff --combined wrw/req.py
@@@ -17,7 -17,7 +17,7 @@@ class headdict(object)
          del self.dict[key.lower()]
  
      def __iter__(self):
 -        return iter((list[0] for list in self.dict.itervalues()))
 +        return iter((list[0] for list in self.dict.values()))
      
      def get(self, key, default = ""):
          if key.lower() in self.dict:
@@@ -62,6 -62,7 +62,7 @@@ class request(object)
  class origrequest(request):
      def __init__(self, env):
          self.env = env
+         self.method = env["REQUEST_METHOD"].upper()
          self.uriname = env["SCRIPT_NAME"]
          self.filename = env.get("SCRIPT_FILENAME")
          self.uri = env["REQUEST_URI"]
@@@ -136,6 -137,7 +137,7 @@@ class copyrequest(request)
          self.parent = p
          self.top = p.topreq()
          self.env = p.env
+         self.method = p.method
          self.uriname = p.uriname
          self.filename = p.filename
          self.uri = p.uri