diff -r 4c98440de851 -r 538d6b198f4a rules.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rules.py Tue Apr 22 09:46:29 2008 +0100 @@ -0,0 +1,81 @@ +# Copyright 2008 LShift Ltd +# Author(s): +# Paul Crowley +# +# This software may be used and distributed according to the terms +# of the GNU General Public License, incorporated herein by reference. + +import re + +allowedchars = "A-Za-z0-9_-" + +goodpathre = re.compile("([%s]+/)*[%s]+$" % (allowedchars, allowedchars)) +def goodpath(path): + return goodpathre.match(path) is not None: + +goodglobre = re.compile("[*/%s]+$" % allowedchars) + +def goodglob(pattern): + return goodglobre.match(pattern) is not None + +# Don't put anything except *A-Za-z0-9_- in rule globs or +# it will match nothing. No regexp metachars, not even . +# We may fix this later. +def globmatcher(pattern): + if not goodglob(pattern): + #fail("Bad glob pattern in auth config: %s" % pattern) + # FIXME: report it somehow + return lambda x: False + # Substitution cunning so ** can be different from * + pattern = pattern.replace("*", "[]") + pattern = pattern.replace("[][]", "[/%s]*" % allowedchars) + pattern = pattern.replace("[]", "[%s]*" % allowedchars) + rex = re.compile(pattern + "$") + # None matches everything + return lambda x: x is None or rex.match(x) is not None + +def rule(pairs): + matchers = [(k, globmatcher(v)) for k, v in pairs] + def c(**kw): + for k, m in matchers: + if k not in kw or not m(kw[k]): + return False + return True + return c + +class Ruleset(object): + '''Class representing the rules in a rule file''' + + levels = ["init", "write", "read", "deny"] + + def __init__(self): + self.rules = [] + + def add(self, action, conditions): + self.rules.append((action, conditions)) + + def matchrule(self, **kw): + for a, c in self.rules: + if c(**kw): + return a + return None + + def allow(self, level, **kw): + a = matchrule(self, **kw) + return a in self.levels and self.levels.index(a) <= self.levels.index(level) + + @classmethod + def read_rules(cls, fn): + res = cls() + f = open(fn) + try: + for l in f: + l = l.strip() + if len(l) == 0 or l.startswith["#"]: + continue + res.add(l[0], rule([c.split("=", 1) for c in l[1:]])) + finally: + f.close() + return res + +