forsyth20121205-174063a80cc13 years agoHistory
194 lines · 3.9 KB · Brainfuck
RawDownload
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;}