diff options
Diffstat (limited to 'appl/spree/lib/allow.b')
| -rw-r--r-- | appl/spree/lib/allow.b | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/appl/spree/lib/allow.b b/appl/spree/lib/allow.b new file mode 100644 index 00000000..ef088b08 --- /dev/null +++ b/appl/spree/lib/allow.b @@ -0,0 +1,194 @@ +implement Allow; +include "sys.m"; + sys: Sys; +include "draw.m"; +include "sets.m"; + sets: Sets; + Set, set, None: import sets; +include "../spree.m"; + spree: Spree; + Attributes, Range, Object, Clique, Member, rand: import spree; +include "allow.m"; + +Action: adt { + tag: int; + member: ref Member; + action: string; +}; + +actions: list of Action; +clique: ref Clique; + +init(srvmod: Spree, g: ref Clique) +{ + sys = load Sys Sys->PATH; + sets = load Sets Sets->PATH; + (clique, spree) = (g, srvmod); +} + +ILLEGALNAME: con "/"; # illegal char in member names, ahem. +archive(archiveobj: ref Object) +{ + i := 0; + for (al := actions; al != nil; al = tl al) { + a := hd al; + pname: string; + if (a.member != nil) + pname = a.member.name; + else + pname = ILLEGALNAME; + archiveobj.setattr( + "allow" + string i++, + sys->sprint("%d %s %s", a.tag, pname, a.action), + None + ); + } +} + +unarchive(archiveobj: ref Object) +{ + for (i := 0; (s := archiveobj.getattr("allow" + string i)) != nil; i++) { + (n, toks) := sys->tokenize(s, " "); + p: ref Member = nil; + if (hd tl toks != ILLEGALNAME) { + # if the member is no longer around, ignore the action. XXX do we still need to do this? + if ((p = clique.membernamed(hd tl toks)) == nil) + continue; + } + sys->print("allow: adding action %d, %ux, %s\n", int hd toks, p, concat(tl tl toks)); + actions = Action(int hd toks, p, concat(tl tl toks)) :: actions; + } +} + +add(tag: int, member: ref Member, action: string) +{ +# sys->print("allow: add %d, member %ux, action: %s\n", tag, member, action); + actions = (tag, member, action) :: actions; +} + +del(tag: int, member: ref Member) +{ +# sys->print("allow: del %d\n", tag); + na: list of Action; + for (a := actions; a != nil; a = tl a) { + action := hd a; + if (action.tag == tag && (member == nil || action.member == member)) + continue; + na = action :: na; + } + actions = na; +} + +action(member: ref Member, cmd: string): (string, int, list of string) +{ + for (al := actions; al != nil; al = tl al) { + a := hd al; + if (a.member == nil || a.member == member) { + (e, v) := match(member, a.action, cmd); + if (e != nil || v != nil) + return (e, a.tag, v); + } + } + return ("you can't do that", -1, nil); +} + +match(member: ref Member, pat, action: string): (string, list of string) +{ +# sys->print("allow: matching pat: '%s' against action '%s'\n", pat, action); + toks: list of string; + na := len action; + if (na > 0 && action[na - 1] == '\n') + na--; + + (i, j) := (0, 0); + for (;;) { + for (; i < len pat; i++) + if (pat[i] != ' ') + break; + for (; j < na; j++) + if (action[j] != ' ') + break; + for (i1 := i; i1 < len pat; i1++) + if (pat[i1] == ' ') + break; + for (j1 := j; j1 < na; j1++) + if (action[j1] == ' ') + break; + if (i == i1) { + if (j == j1) + break; + return (nil, nil); + } + if (j == j1) { + if (pat == "&") + break; + return (nil, nil); + } + pw := pat[i : i1]; + w := action[j : j1]; + case pw[0] { + '*' => + toks = w :: toks; + '&' => + toks = w :: toks; + pat = "&"; + i1 = 0; + '%' => + (ok, nw) := checkformat(member, pw[1], w); + if (!ok) + return ("invalid field value", nil); + toks = nw :: toks; + * => + if (w != pw) + return (nil, nil); + toks = w :: toks; + } + (i, j) = (i1, j1); + } + return (nil, revs(toks)); +} + +revs(l: list of string): list of string +{ + m: list of string; + for (; l != nil; l = tl l) + m = hd l :: m; + return m; +} + +checkformat(p: ref Member, fmt: int, w: string): (int, string) +{ + case fmt { + 'o' => + # object id + if (isnum(w) && (o := p.obj(int w)) != nil) + return (1, string o.id); + 'd' => + # integer + if (isnum(w)) + return (1, w); + 'p' => + # member id + if (isnum(w) && (member := clique.member(int w)) != nil) + return (1, w); + } + return (0, nil); +} + +isnum(w: string): int +{ + # XXX lazy for the time being... + if (w != nil && ((w[0] >= '0' && w[0] <= '9') || w[0] == '-')) + return 1; + return 0; +} + +concat(v: list of string): string +{ + if (v == nil) + return nil; + s := hd v; + for (v = tl v; v != nil; v = tl v) + s += " " + hd v; + return s; +} |
