From: Fredrik Tolf Date: Sun, 3 Nov 2013 14:10:10 +0000 (+0100) Subject: Merge branch 'master' into python3 X-Git-Url: http://git.dolda2000.com/gitweb/?a=commitdiff_plain;h=6d2e09cf5bf8ddfa126ca16d536f6b42e502f0ce;hp=-c;p=wrw.git Merge branch 'master' into python3 --- 6d2e09cf5bf8ddfa126ca16d536f6b42e502f0ce diff --combined wrw/auth.py index 0000000,4ae292d..1858214 mode 000000,100644..100644 --- a/wrw/auth.py +++ b/wrw/auth.py @@@ -1,0 -1,90 +1,98 @@@ + import binascii, hashlib, threading, time -import resp ++from . import resp + + class unauthorized(resp.httperror): + def __init__(self, challenge, message=None, detail=None): - super(unauthorized, self).__init__(401, message, detail) ++ super().__init__(401, message, detail) + if isinstance(challenge, str): + challenge = [challenge] + self.challenge = challenge + + def handle(self, req): + for challenge in self.challenge: + req.ohead.add("WWW-Authenticate", challenge) - return super(unauthorized, self).handle(req) ++ return super().handle(req) + + class forbidden(resp.httperror): + def __init__(self, message=None, detail=None): - super(forbidden, self).__init__(403, message, detail) ++ super().__init__(403, message, detail) + + def parsemech(req): + h = req.ihead.get("Authorization", None) + if h is None: + return None, None + p = h.find(" ") + if p < 0: + return None, None + return h[:p].strip().lower(), h[p + 1:].strip() + + def parsebasic(req): + mech, data = parsemech(req) + if mech != "basic": + return None, None + try: ++ data = data.encode("us-ascii") ++ except UnicodeError: ++ return None, None ++ try: + raw = binascii.a2b_base64(data) + except binascii.Error: + return None, None ++ try: ++ raw = raw.decode("utf-8") ++ except UnicodeError: ++ raw = raw.decode("latin1") + p = raw.find(":") + if p < 0: + return None, None + return raw[:p], raw[p + 1:] + + class basiccache(object): + cachetime = 300 + + def __init__(self, realm, authfn=None): + self._lock = threading.Lock() + self._cache = {} + self.realm = realm + if authfn is not None: + self.auth = authfn + + def _obscure(self, nm, pw): + dig = hashlib.sha256() - dig.update(self.realm) - dig.update(nm) - dig.update(pw) ++ dig.update(self.realm.encode("utf-8")) ++ dig.update(nm.encode("utf-8")) ++ dig.update(pw.encode("utf-8")) + return dig.digest() + + def check(self, req): + nm, pw = parsebasic(req) + if nm is None: + raise unauthorized("Basic Realm=\"%s\"" % self.realm) + pwh = self._obscure(nm, pw) + now = time.time() + with self._lock: + if (nm, pwh) in self._cache: + lock, atime, res, resob = self._cache[nm, pwh] + if now - atime < self.cachetime: + if res == "s": + return resob + elif res == "f": + raise resob + else: + lock = threading.Lock() + self._cache[nm, pwh] = (lock, now, None, None) + with lock: + try: + ret = self.auth(req, nm, pw) - except forbidden, exc: ++ except forbidden as exc: + with self._lock: + self._cache[nm, pwh] = (lock, now, "f", exc) + raise + if ret is None: + raise forbidden() + with self._lock: + self._cache[nm, pwh] = (lock, now, "s", ret) + return ret + + def auth(self, req, nm, pw): + raise Exception("authentication function neither supplied nor overridden") diff --combined wrw/sp/cons.py index cb9d451,1e3d678..99656a3 --- a/wrw/sp/cons.py +++ b/wrw/sp/cons.py @@@ -4,18 -4,18 +4,18 @@@ import xml.dom.minido class node(object): pass -class text(node, unicode): +class text(node, str): def __todom__(self, doc): return doc.createTextNode(self) -class raw(node, unicode): +class raw(node, str): def __todom__(self, doc): raise Exception("Cannot convert raw code to DOM objects") class element(node): def __init__(self, ns, name, ctx): self.ns = ns - self.name = unicode(name) + self.name = str(name) self.ctx = ctx self.attrs = {} self.children = [] @@@ -23,13 -23,13 +23,13 @@@ def __call__(self, *children, **attrs): for child in children: self.ctx.addchild(self, child) - for k, v in attrs.iteritems(): + for k, v in attrs.items(): self.ctx.addattr(self, k, v) return self def __todom__(self, doc): el = doc.createElementNS(self.ns, self.name) - for k, v in self.attrs.iteritems(): + for k, v in self.attrs.items(): el.setAttribute(k, v) for child in self.children: el.appendChild(child.__todom__(doc)) @@@ -40,13 -40,14 +40,13 @@@ return self.__todom__(doc).toxml() class context(object): - charset = sys.getfilesystemencoding() + charset = (sys.getfilesystemencoding() or "ascii") def __init__(self): self.nodeconv = {} - self.nodeconv[str] = lambda ob: text(ob, self.charset) - self.nodeconv[unicode] = text + self.nodeconv[bytes] = lambda ob: text(ob, self.charset) + self.nodeconv[str] = text self.nodeconv[int] = text - self.nodeconv[long] = text self.nodeconv[float] = text def nodefrom(self, ob): @@@ -63,7 -64,7 +63,7 @@@ def addattr(self, node, k, v): if v is not None: - node.attrs[unicode(k)] = unicode(v) + node.attrs[str(k)] = str(v) class constructor(object): def __init__(self, ns, elcls=element, ctx=None):