//
//protocfg.c
//
//
//
//-UserX 2001/12/09

#include <string.h>
#include "base/strarray.h"
#include "base/str.h"
#include "net/protocfg.h"

StringIntPair pipelist[] = {
		{"crypt", PL_CRYPT},
		{"steady", PL_STEADY},
		{"spurt", PL_SPURT},
		{"backward", PL_BACK},
		{NULL, -1}
	};

StringIntPair pipefacelist[] = {
		{"raw", PFL_RAW},
		{"core", PFL_CORE},
		{"virc", PFL_VIRC},
		{NULL, -1}
	};

StringIntPair pipemasqlist[] = {
		{"test", PML_TEST},
		{NULL, -1}
	};

StringArrayHandle *filtergood = NULL;
StringArrayHandle *filterbad = NULL;

char *protocolmasqhost = "127.0.0.1";
char *protocolmasqtansport = "tcp";
int protocolmasqport = 1818;


void protocolAddGood(void *extra, char *filter) {
	if(isStringBlank(filter)) {
		return;
	}
	if(filtergood == NULL) {
		//filtergood = makeStringArray();
		filtergood = saMake();
	}
	saAppendCopy(filtergood, filter);
}

void protocolGetGood(void *extra, StringArrayHandle **sa) {
	*sa = saCopy(filtergood);
}

void protocolClearGood(void *extra) {
	if(filtergood != NULL) {
		saFree(filtergood);
	}
	filtergood = NULL;
}

void protocolAddBad(void *extra, char *filter) {
	if(isStringBlank(filter)) {
		return;
	}
	if(filterbad == NULL) {
		//filterbad = makeStringArray();
		filterbad = saMake();
	}
	saAppendCopy(filterbad, filter);
}

void protocolGetBad(void *extra, StringArrayHandle **sa) {
	*sa = saCopy(filterbad);
}

void protocolClearBad(void *extra) {
	if(filtergood != NULL) {
		saFree(filterbad);
	}
	filterbad = NULL;
}

int protocolFilterTestDo(StringArrayHandle *saf, StringArrayHandle *sap, int of, int op) {
	int v;
	for(; of < saf->size && op < sap->size; of++, op++) {
		if(strcasecmp(saf->data[of], "*") == 0) { //wildcard matches zero or more protocols
			of++;
			for(; op < sap->size; op++) {
				v = protocolFilterTestDo(saf, sap, of, op);
				if(v != 0) {
					return v;
				}
			}
			return 0;
		} 
		if(strcasecmp(saf->data[of], "+") == 0) { //wildcard matches one or more protocols
			of++;
			for(op++; op < sap->size; op++) {
				v = protocolFilterTestDo(saf, sap, of, op);
				if(v != 0) {
					return v;
				}
			}
			return 0;
		}
		if(strcasecmp(saf->data[of], "?") == 0) { //wildcard matches zero or one protocols
			of++;
			v = protocolFilterTestDo(saf, sap, of, op);
			if(v != 0) {
				return v;
			}
			op++;
			v = protocolFilterTestDo(saf, sap, of, op);
			if(v != 0) {
				return v;
			}
			return 0;
		}
		if(strcasecmp(saf->data[of], ".") == 0) { //wildcard matches any one protocol
			of++;
			op++;
			continue;
		}
		if(saf->data[of][0] == '!') { //must not match this one
			if(strcasecmp(saf->data[of] + 1, sap->data[op]) == 0) {
				return 0;
			}
		} else { //normal matching
			if(strcasecmp(saf->data[of], sap->data[op]) != 0) {
				return 0;
			}
		}
	}
	if(of >= saf->size && op >= sap->size) {
		return 1;
	}
	return 0;
}

//returns non-zero if protocol matches the filter.
int protocolFilterTest(char *filter, char *protocol) {
	StringArrayHandle *saf;
	StringArrayHandle *sap;
	int v;

	if(isStringBlank(filter) || isStringBlank(protocol)) {
		return 0;
	}

	saf = saMakeFromSplitString(filter, ":");
	sap = saMakeFromSplitString(protocol, ":");

	v = protocolFilterTestDo(saf, sap, 0, 0);

	//freeStringArray(saf);
	//freeStringArray(sap);
	saFree(saf);
	saFree(sap);

	return v;

}

//return non-zero if the protocol passes the filters
int protocolFilter(char *protocol) {
	int i;
	if(filterbad != NULL) {
		for(i = 0; i < filterbad->size; i++) {
			if(protocolFilterTest(filterbad->data[i], protocol) != 0) {
				return 0;
			}
		}
	}
	if(filtergood != NULL) {
		for(i = 0; i < filtergood->size; i++) {
			if(protocolFilterTest(filtergood->data[i], protocol) != 0) {
				return 1;
			}
		}
	} else {
		return 1;
	}
	return 0;
}


