# Copyright 2008-2009 LShift Ltd# Author(s):# Paul Crowley <paul@lshift.net>## This software may be used and distributed according to the terms# of the GNU General Public License, incorporated herein by reference.import sysimport reimport osimport os.pathallowedchars = "A-Za-z0-9_-"def globmatcher(pattern): p = "[^/]*".join(re.escape(c) for c in pattern.split("*")) # ** means "match recursively" ie "ignore directories" rex = re.compile(p.replace("[^/]*[^/]*", ".*") + "$") # None matches everything return lambda x: x is None or rex.match(x) is not Nonedef 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 cclass Ruleset(object): '''Class representing the rules in a rule file''' levels = ["init", "write", "read", "deny"] def __init__(self): self.rules = [] self.preset = {} def add(self, action, conditions): self.rules.append((action, conditions)) def set(self, **kw): self.preset.update(kw) def get(self, k): return self.preset.get(k, None) def matchrule(self, kw): d = self.preset.copy() d.update(kw) for a, c in self.rules: if c(d): return a return None def allow(self, level, **kw): a = self.matchrule(kw) return a in self.levels and self.levels.index(a) <= self.levels.index(level) def readfile(self, fn): try: f = open(fn) try: for l in f: l = l.strip() if len(l) == 0 or l.startswith("#"): continue l = l.split() self.add(l[0], rule([c.split("=", 1) for c in l[1:]])) finally: f.close() except Exception, e: print >> sys.stderr, "Failure reading rules file:", erules = Ruleset()