#include "common.h"
#include "send.h"

extern int debug;

/* 
 *	Routines for dealing with the rewrite rules.
 */

/* globals */
typedef struct rule rule;

#define NSUBEXP 10
struct rule {
	String *matchre;	/* address match */
	String *repl1;		/* first replacement String */
	String *repl2;		/* second replacement String */
	d_status type;		/* type of rule */
	Reprog *program;
	Resub subexp[NSUBEXP];
	rule *next;
};
static rule *rulep;
static rule *rlastp;

/* predeclared */
static String *substitute(String *, Resub *, message *);
static rule *findrule(String *, int);


/*
 *  Get the next token from `line'.  The symbol `\l' is replaced by
 *  the name of the local system.
 */
extern String *
rule_parse(String *line, char *system, int *backl)
{
	String *token;
	String *expanded;
	char *cp;

	token = s_parse(line, 0);
	if(token == 0)
		return(token);
	if(strchr(s_to_c(token), '\\')==0)
		return(token);
	expanded = s_new();
	for(cp = s_to_c(token); *cp; cp++) {
		if(*cp == '\\') switch(*++cp) {
		case 'l':
			s_append(expanded, system);
			*backl = 1;
			break;
		case '\\':
			s_putc(expanded, '\\');
			break;
		default:
			s_putc(expanded, '\\');
			s_putc(expanded, *cp);
			break;
		} else
			s_putc(expanded, *cp);
	}
	s_free(token);
	s_terminate(expanded);
	return(expanded);
}

static int
getrule(String *line, String *type, char *system)
{
	rule	*rp;
	String	*re;
	int	backl;

	backl = 0;

	/* get a rule */
	re = rule_parse(s_restart(line), system, &backl);
	if(re == 0)
		return 0;
	rp = (rule *)malloc(sizeof(rule));
	if(rp == 0) {
		perror("getrules:");
		exit(1);
	}
	rp->next = 0;
	s_tolower(re);
	rp->matchre = s_new();
	s_append(rp->matchre, s_to_c(re));
	s_restart(rp->matchre);
	s_free(re);
	s_parse(line, s_restart(type));
	rp->repl1 = rule_parse(line, system, &backl);
	rp->repl2 = rule_parse(line, system, &backl);
	rp->program = 0;
	if(strcmp(s_to_c(type), "|") == 0)
		rp->type = d_pipe;
	else if(strcmp(s_to_c(type), ">>") == 0)
		rp->type = d_cat;
	else if(strcmp(s_to_c(type), "alias") == 0)
		rp->type = d_alias;
	else if(strcmp(s_to_c(type), "translate") == 0)
		rp->type = d_translate;
	else if(strcmp(s_to_c(type), "auth") == 0)
		rp->type = d_auth;
	else {
		s_free(rp->matchre);
		s_free(rp->repl1);
		s_free(rp->repl2);
		free((char *)rp);
		fprint(2,"illegal rewrite rule: %s\n", s_to_c(line));
		return 0;
	}
	if(rulep == 0)
		rulep = rlastp = rp;
	else
		rlastp = rlastp->next = rp;
	return backl;
}

/*
 *  rules are of the form:
 *	<reg exp> <String> <repl exp> [<repl exp>]
 */
extern int
getrules(void)
{
	Biobuf	*rfp;
	String	*line;
	String	*type;
	String	*file;

	file = abspath("rewrite", unsharp(UPASLIB), (String *)0);
	rfp = sysopen(s_to_c(file), "r", 0);
	if(rfp == 0) {
		rulep = 0;
		return -1;
	}
	rlastp = 0;
	line = s_new();
	type = s_new();
	while(s_getline(rfp, s_restart(line)))
		if(getrule(line, type, thissys) && altthissys)
			getrule(s_restart(line), type, altthissys);
	s_free(type);
	s_free(line);
	s_free(file);
	sysclose(rfp);
	return 0;
}

/* look up a matching rule */
static rule *
findrule(String *addrp, int authorized)
{
	rule *rp;
	static rule defaultrule;

	if(rulep == 0)
		return &defaultrule;
	for (rp = rulep; rp != 0; rp = rp->next) {
		if(rp->type==d_auth && authorized)
			continue;
		if(rp->program == 0)
			rp->program = regcomp(rp->matchre->base);
		if(rp->program == 0)
			continue;
		memset(rp->subexp, 0, sizeof(rp->subexp));
		if(debug)
			print("matching %s aginst %s\n", s_to_c(addrp), rp->matchre->base);
		if(regexec(rp->program, s_to_c(addrp), rp->subexp, NSUBEXP))
		if(s_to_c(addrp) == rp->subexp[0].s.sp)
		if((s_to_c(addrp) + strlen(s_to_c(addrp))) == rp->subexp[0].e.ep)
			return rp;
	}
	return 0;
}

/*  Transforms the address into a command.
 *  Returns:	-1 ifaddress not matched by reules
 *		 0 ifaddress matched and ok to forward
 *		 1 ifaddress matched and not ok to forward
 */
extern int
rewrite(dest *dp, message *mp)
{
	rule *rp;		/* rewriting rule */
	String *lower;		/* lower case version of destination */

	/*
	 *  Rewrite the address.  Matching is case insensitive.
	 */
	lower = s_clone(dp->addr);
	s_tolower(s_restart(lower));
	rp = findrule(lower, dp->authorized);
	if(rp == 0){
		s_free(lower);
		return -1;
	}
	strcpy(s_to_c(lower), s_to_c(dp->addr));
	dp->repl1 = substitute(rp->repl1, rp->subexp, mp);
	dp->repl2 = substitute(rp->repl2, rp->subexp, mp);
	dp->status = rp->type;
	if(debug){
		print("\t->");
		if(dp->repl1)
			print("%s", s_to_c(dp->repl1));
		if(dp->repl2)
			print("%s", s_to_c(dp->repl2));
		print("\n");
	}
	s_free(lower);
	return 0;
}

static String *
substitute(String *source, Resub *subexp, message *mp)
{
	int i;
	char *s;
	char *sp;
	String *stp;
	
	if(source == 0)
		return 0;
	sp = s_to_c(source);

	/* someplace to put it */
	stp = s_new();

	/* do the substitution */
	while (*sp != '\0') {
		if(*sp == '\\') {
			switch (*++sp) {
			case '0': case '1': case '2': case '3': case '4':
			case '5': case '6': case '7': case '8': case '9':
				i = *sp-'0';
				if(subexp[i].s.sp != 0)
					for (s = subexp[i].s.sp;
					     s < subexp[i].e.ep;
					     s++)
						s_putc(stp, *s);
				break;
			case '\\':
				s_putc(stp, '\\');
				break;
			case '\0':
				sp--;
				break;
			case 's':
				for(s = s_to_c(mp->replyaddr); *s; s++)
					s_putc(stp, *s);
				break;
			case 'p':
				if(mp->bulk)
					s = "bulk";
				else
					s = "normal";
				for(;*s; s++)
					s_putc(stp, *s);
				break;
			default:
				s_putc(stp, *sp);
				break;
			}
		} else if(*sp == '&') {				
			if(subexp[0].s.sp != 0)
				for (s = subexp[0].s.sp;
				     s < subexp[0].e.ep; s++)
					s_putc(stp, *s);
		} else
			s_putc(stp, *sp);
		sp++;
	}
	s_terminate(stp);

	return s_restart(stp);
}

extern void
regerror(char* s)
{
	fprint(2, "rewrite: %s\n", s);
}

extern void
dumprules(void)
{
	rule *rp;

	for (rp = rulep; rp != 0; rp = rp->next) {
		fprint(2, "'%s'", rp->matchre->base);
		switch (rp->type) {
		case d_pipe:
			fprint(2, " |");
			break;
		case d_cat:
			fprint(2, " >>");
			break;
		case d_alias:
			fprint(2, " alias");
			break;
		case d_translate:
			fprint(2, " translate");
			break;
		default:
			fprint(2, " UNKNOWN");
			break;
		}
		fprint(2, " '%s'", rp->repl1 ? rp->repl1->base:"...");
		fprint(2, " '%s'\n", rp->repl2 ? rp->repl2->base:"...");
	}
}

