try: from mod_python import apache, util except ImportError: from dummy import apache, util import py from base import handler_decorator class OPTIONS(handler_decorator): def __init__(self, options=['GET', 'HEAD', 'POST']): self.options = options def handler(self, orghandler, request): if request.method == 'OPTIONS': request.headers_out['Allow'] = ','.join(self.options) request.set_content_length(0) return apache.OK if request.method not in self.options: # XXX do we want to let Apache handle this by itself? request.headers_out['Allow'] = ','.join(self.options) return apache.HTTP_NOT_IMPLEMENTED return orghandler(request) class PUTsupport(handler_decorator): BLOCKSIZE = 1024 def __init__(self, condition=lambda r: True, defaultindexes=['index.rst', 'index.txt', 'index.html'], defaultcreate='index.rst', usesvn=False): self.condition = condition self.defaultindexes = defaultindexes self.defaultcreate = defaultcreate self.usesvn = usesvn def handler(self, orghandler, request): if request.method == 'PUT': if self.usesvn: fpath = py.path.svnwc(request.filename) else: fpath = py.path.local(request.filename) if fpath.check(dir=True): for di in self.defaultindexes: if (fpath / di).check(): fpath = fpath / di break else: fpath = fpath / self.defaultcreate created = not fpath.check() clen = int(request.headers_in['Content-Length']) remaining = clen fp = fpath.open('w') try: while remaining > 0: chunksize = self.BLOCKSIZE if chunksize > remaining: chunksize = remaining fp.write(request.read(chunksize)) remaining -= chunksize finally: fp.close() if created: if self.usesvn: # do an 'svn add' fpath.add() request.status = apache.HTTP_CREATED return apache.OK return apache.HTTP_NO_CONTENT else: return orghandler(request) class auth(handler_decorator): """tests for credentials if not correct returns templess.node, else passes input on 1:1 """ def __init__(self, template, userdb, realm, condition=lambda r: True): self.template = template self.userdb = userdb self.realm = realm self.condition = condition def handler(self, orghandler, request): from templess import templess from base64 import decodestring if not self.condition(request): return orghandler(request) # have to decode here ourselves, for some unknown reason mod_python # only does this if the authentication is triggered from config... auth = request.headers_in.get('Authorization') user = None pw = None if auth is not None: decoded = decodestring(auth.split(' ')[1]) user = decoded.split(':')[0] pw = ':'.join(decoded.split(':')[1:]) if not user or not pw or self.userdb.get(user, '') != pw: # unauthorized, use basic auth to get creds request.content_type = 'text/html; charset=UTF-8' request.status = apache.HTTP_UNAUTHORIZED request.headers_out['WWW-Authenticate'] = 'Basic %s' % ( self.realm,) tpath = py.path.local(self.template) t = templess.template(tpath.open()) return t.render({ 'uri': request.uri, }) request.user = user request.password = pw return orghandler(request) class redirect(handler_decorator): """HTTP redirect support""" def __init__(self, from_path, to_url, status=apache.HTTP_MOVED_PERMANENTLY): self.from_path = from_path self.to_url = to_url self.status = status def handler(self, orghandler, request): if request.uri == self.from_path: to_url = self.to_url request.status = self.status request.content_type = 'text/plain' request.headers_out['Location'] = self.to_url request.write('Moved permanently') return apache.OK return orghandler(request)