/*
 * Configuration condition preprocessor
 *
 * Copyright 2000-2021 Willy Tarreau <w@1wt.eu>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 *
 */

#include <haproxy/api.h>
#include <haproxy/arg.h>
#include <haproxy/cfgcond.h>
#include <haproxy/global.h>
#include <haproxy/tools.h>

/* supported condition predicates */
const struct cond_pred_kw cond_predicates[] = {
	{ "defined",          CFG_PRED_DEFINED,         ARG1(1, STR)         },
	{ "feature",          CFG_PRED_FEATURE,         ARG1(1, STR)         },
	{ "streq",            CFG_PRED_STREQ,           ARG2(2, STR, STR)    },
	{ "strneq",           CFG_PRED_STRNEQ,          ARG2(2, STR, STR)    },
	{ "version_atleast",  CFG_PRED_VERSION_ATLEAST, ARG1(1, STR)         },
	{ "version_before",   CFG_PRED_VERSION_BEFORE,  ARG1(1, STR)         },
	{ NULL, CFG_PRED_NONE, 0 }
};

/* looks up a cond predicate matching the keyword in <str>, possibly followed
 * by a parenthesis. Returns a pointer to it or NULL if not found.
 */
const struct cond_pred_kw *cfg_lookup_cond_pred(const char *str)
{
	const struct cond_pred_kw *ret;
	int len = strcspn(str, " (");

	for (ret = &cond_predicates[0]; ret->word; ret++) {
		if (len != strlen(ret->word))
			continue;
		if (strncmp(str, ret->word, len) != 0)
			continue;
		return ret;
	}
	return NULL;
}

/* Frees <term> and its args. NULL is supported and does nothing. */
void cfg_free_cond_term(struct cfg_cond_term *term)
{
	if (!term)
		return;

	if (term->type == CCTT_PAREN) {
		cfg_free_cond_expr(term->expr);
		term->expr = NULL;
	}

	free_args(term->args);
	free(term->args);
	free(term);
}

/* Parse an indirect input text as a possible config condition term.
 * Returns <0 on parsing error, 0 if the parser is desynchronized, or >0 on
 * success. <term> is allocated and filled with the parsed info, and <text>
 * is updated on success to point to the first unparsed character, or is left
 * untouched on failure. On success, the caller must free <term> using
 * cfg_free_cond_term(). An error will be set in <err> on error, and only
 * in this case. In this case the first bad character will be reported in
 * <errptr>. <maxdepth> corresponds to the maximum recursion depth permitted,
 * it is decremented on each recursive call and the parsing will fail one
 * reaching <= 0.
 */
int cfg_parse_cond_term(const char **text, struct cfg_cond_term **term, char **err, const char **errptr, int maxdepth)
{
	struct cfg_cond_term *t;
	const char *in = *text;
	const char *end_ptr;
	int err_arg;
	int nbargs;
	char *end;
	long val;

	while (*in == ' ' || *in == '\t')
		in++;

	if (!*in) /* empty term does not parse */
		return 0;

	*term = NULL;
	if (maxdepth <= 0)
		goto fail0;

	t = *term = calloc(1, sizeof(**term));
	if (!t) {
		memprintf(err, "memory allocation error while parsing conditional expression '%s'", *text);
		goto fail1;
	}

	t->type = CCTT_NONE;
	t->args = NULL;
	t->neg  = 0;

	/* !<term> negates the term. White spaces permitted */
	while (*in == '!') {
		t->neg = !t->neg;
		do { in++; } while (*in == ' ' || *in == '\t');
	}

	val = strtol(in, &end, 0);
	if (end != in) {
		t->type = val ? CCTT_TRUE : CCTT_FALSE;
		*text = end;
		return 1;
	}

	/* Try to parse '(' EXPR ')' */
	if (*in == '(') {
		int ret;

		t->type = CCTT_PAREN;
		t->args = NULL;

		do { in++; } while (*in == ' ' || *in == '\t');
		ret = cfg_parse_cond_expr(&in, &t->expr, err, errptr, maxdepth - 1);
		if (ret == -1)
			goto fail2;
		if (ret == 0)
			goto fail0;

		/* find the closing ')' */
		while (*in == ' ' || *in == '\t')
			in++;
		if (*in != ')') {
			memprintf(err, "expected ')' after conditional expression '%s'", *text);
			goto fail1;
		}
		do { in++; } while (*in == ' ' || *in == '\t');
		*text = in;
		return 1;
	}

	/* below we'll likely all make_arg_list() so we must return only via
	 * the <done> label which frees the arg list.
	 */
	t->pred = cfg_lookup_cond_pred(in);
	if (t->pred) {
		t->type = CCTT_PRED;
		nbargs = make_arg_list(in + strlen(t->pred->word), -1,
		                       t->pred->arg_mask, &t->args, err,
		                       &end_ptr, &err_arg, NULL);
		if (nbargs < 0) {
			memprintf(err, "%s in argument %d of predicate '%s' used in conditional expression", *err, err_arg, t->pred->word);
			if (errptr)
				*errptr = end_ptr;
			goto fail2;
		}
		*text = end_ptr;
		return 1;
	}

 fail0:
	memprintf(err, "unparsable conditional expression '%s'", *text);
 fail1:
	if (errptr)
		*errptr = *text;
 fail2:
	cfg_free_cond_term(*term);
	*term = NULL;
	return -1;
}

/* evaluate a condition term on a .if/.elif line. The condition was already
 * parsed in <term>. Returns -1 on error (in which case err is filled with a
 * message, and only in this case), 0 if the condition is false, 1 if it's
 * true.
 */
int cfg_eval_cond_term(const struct cfg_cond_term *term, char **err)
{
	int ret = -1;

	if (term->type == CCTT_FALSE)
		ret = 0;
	else if (term->type == CCTT_TRUE)
		ret = 1;
	else if (term->type == CCTT_PRED) {
		/* here we know we have a valid predicate with valid arguments
		 * placed in term->args (which the caller will free).
		 */
		switch (term->pred->prd) {
		case CFG_PRED_DEFINED:  // checks if arg exists as an environment variable
			ret = getenv(term->args[0].data.str.area) != NULL;
			break;

		case CFG_PRED_FEATURE: { // checks if the arg matches an enabled feature
			const char *p;

			ret = 0; // assume feature not found
			for (p = build_features; (p = strstr(p, term->args[0].data.str.area)); p++) {
				if (p > build_features &&
				    (p[term->args[0].data.str.data] == ' ' ||
				     p[term->args[0].data.str.data] == 0)) {
					if (*(p-1) == '+') {       // e.g. "+OPENSSL"
						ret = 1;
						break;
					}
					else if (*(p-1) == '-') {  // e.g. "-OPENSSL"
						ret = 0;
						break;
					}
					/* it was a sub-word, let's restart from next place */
				}
			}
			break;
		}
		case CFG_PRED_STREQ:    // checks if the two arg are equal
			ret = strcmp(term->args[0].data.str.area, term->args[1].data.str.area) == 0;
			break;

		case CFG_PRED_STRNEQ:   // checks if the two arg are different
			ret = strcmp(term->args[0].data.str.area, term->args[1].data.str.area) != 0;
			break;

		case CFG_PRED_VERSION_ATLEAST: // checks if the current version is at least this one
			ret = compare_current_version(term->args[0].data.str.area) <= 0;
			break;

		case CFG_PRED_VERSION_BEFORE:  // checks if the current version is older than this one
			ret = compare_current_version(term->args[0].data.str.area) > 0;
			break;

		default:
			memprintf(err, "internal error: unhandled conditional expression predicate '%s'", term->pred->word);
			break;
		}
	}
	else if (term->type == CCTT_PAREN) {
		ret = cfg_eval_cond_expr(term->expr, err);
	}
	else {
		memprintf(err, "internal error: unhandled condition term type %d", (int)term->type);
	}

	if (ret >= 0 && term->neg)
		ret = !ret;
	return ret;
}


/* Frees <expr> and its terms and args. NULL is supported and does nothing. */
void cfg_free_cond_and(struct cfg_cond_and *expr)
{
	struct cfg_cond_and *prev;

	while (expr) {
		cfg_free_cond_term(expr->left);
		prev = expr;
		expr = expr->right;
		free(prev);
	}
}

/* Frees <expr> and its terms and args. NULL is supported and does nothing. */
void cfg_free_cond_expr(struct cfg_cond_expr *expr)
{
	struct cfg_cond_expr *prev;

	while (expr) {
		cfg_free_cond_and(expr->left);
		prev = expr;
		expr = expr->right;
		free(prev);
	}
}

/* Parse an indirect input text as a possible config condition sub-expr.
 * Returns <0 on parsing error, 0 if the parser is desynchronized, or >0 on
 * success. <expr> is filled with the parsed info, and <text> is updated on
 * success to point to the first unparsed character, or is left untouched
 * on failure. On success, the caller will have to free all lower-level
 * allocated structs using cfg_free_cond_expr(). An error will be set in
 * <err> on error, and only in this case. In this case the first bad
 * character will be reported in <errptr>. <maxdepth> corresponds to the
 * maximum recursion depth permitted, it is decremented on each recursive
 * call and the parsing will fail one reaching <= 0.
 */
int cfg_parse_cond_and(const char **text, struct cfg_cond_and **expr, char **err, const char **errptr, int maxdepth)
{
	struct cfg_cond_and *e;
	const char *in = *text;
	int ret = -1;

	if (!*in) /* empty expr does not parse */
		return 0;

	*expr = NULL;
	if (maxdepth <= 0) {
		memprintf(err, "unparsable conditional sub-expression '%s'", in);
		if (errptr)
			*errptr = in;
		goto done;
	}

	e = *expr = calloc(1, sizeof(**expr));
	if (!e) {
		memprintf(err, "memory allocation error while parsing conditional expression '%s'", *text);
		goto done;
	}

	ret = cfg_parse_cond_term(&in, &e->left, err, errptr, maxdepth - 1);
	if (ret == -1) // parse error, error already reported
		goto done;

	if (ret == 0) {
		/* ret == 0, no other way to parse this */
		memprintf(err, "unparsable conditional sub-expression '%s'", in);
		if (errptr)
			*errptr = in;
		ret = -1;
		goto done;
	}

	/* ret=1, we have a term in the left hand set */

	/* find an optionnal '&&' */
	while (*in == ' ' || *in == '\t')
		in++;

	*text = in;
	if (in[0] != '&' || in[1] != '&')
		goto done;

	/* we have a '&&', let's parse the right handset's subexp */
	in += 2;
	while (*in == ' ' || *in == '\t')
		in++;

	ret = cfg_parse_cond_and(&in, &e->right, err, errptr, maxdepth - 1);
	if (ret > 0)
		*text = in;
 done:
	if (ret < 0) {
		cfg_free_cond_and(*expr);
		*expr = NULL;
	}
	return ret;
}

/* Parse an indirect input text as a possible config condition term.
 * Returns <0 on parsing error, 0 if the parser is desynchronized, or >0 on
 * success. <expr> is filled with the parsed info, and <text> is updated on
 * success to point to the first unparsed character, or is left untouched
 * on failure. On success, the caller will have to free all lower-level
 * allocated structs using cfg_free_cond_expr(). An error will be set in
 * <err> on error, and only in this case. In this case the first bad
 * character will be reported in <errptr>. <maxdepth> corresponds to the
 * maximum recursion depth permitted, it is decremented on each recursive call
 * and the parsing will fail one reaching <= 0.
 */
int cfg_parse_cond_expr(const char **text, struct cfg_cond_expr **expr, char **err, const char **errptr, int maxdepth)
{
	struct cfg_cond_expr *e;
	const char *in = *text;
	int ret = -1;

	if (!*in) /* empty expr does not parse */
		return 0;

	*expr = NULL;
	if (maxdepth <= 0) {
		memprintf(err, "unparsable conditional expression '%s'", in);
		if (errptr)
			*errptr = in;
		goto done;
	}

	e = *expr = calloc(1, sizeof(**expr));
	if (!e) {
		memprintf(err, "memory allocation error while parsing conditional expression '%s'", *text);
		goto done;
	}

	ret = cfg_parse_cond_and(&in, &e->left, err, errptr, maxdepth - 1);
	if (ret == -1) // parse error, error already reported
		goto done;

	if (ret == 0) {
		/* ret == 0, no other way to parse this */
		memprintf(err, "unparsable conditional expression '%s'", in);
		if (errptr)
			*errptr = in;
		ret = -1;
		goto done;
	}

	/* ret=1, we have a sub-expr in the left hand set */

	/* find an optionnal '||' */
	while (*in == ' ' || *in == '\t')
		in++;

	*text = in;
	if (in[0] != '|' || in[1] != '|')
		goto done;

	/* we have a '||', let's parse the right handset's subexp */
	in += 2;
	while (*in == ' ' || *in == '\t')
		in++;

	ret = cfg_parse_cond_expr(&in, &e->right, err, errptr, maxdepth - 1);
	if (ret > 0)
		*text = in;
 done:
	if (ret < 0) {
		cfg_free_cond_expr(*expr);
		*expr = NULL;
	}
	return ret;
}

/* evaluate an sub-expression on a .if/.elif line. The expression is valid and
 * was already parsed in <expr>. Returns -1 on error (in which case err is
 * filled with a message, and only in this case), 0 if the condition is false,
 * 1 if it's true.
 */
int cfg_eval_cond_and(struct cfg_cond_and *expr, char **err)
{
	int ret;

	/* AND: loop on terms and sub-exp's terms as long as they're TRUE
	 * (stop on FALSE and ERROR).
	 */
	while ((ret = cfg_eval_cond_term(expr->left, err)) > 0 && expr->right)
		expr = expr->right;
	return ret;
}

/* evaluate an expression on a .if/.elif line. The expression is valid and was
 * already parsed in <expr>. Returns -1 on error (in which case err is filled
 * with a message, and only in this case), 0 if the condition is false, 1 if
 * it's true.
 */
int cfg_eval_cond_expr(struct cfg_cond_expr *expr, char **err)
{
	int ret;

	/* OR: loop on sub-exps as long as they're FALSE (stop on TRUE and ERROR) */
	while ((ret = cfg_eval_cond_and(expr->left, err)) == 0 && expr->right)
		expr = expr->right;
	return ret;
}

/* evaluate a condition on a .if/.elif line. The condition is already tokenized
 * in <err>. Returns -1 on error (in which case err is filled with a message,
 * and only in this case), 0 if the condition is false, 1 if it's true. If
 * <errptr> is not NULL, it's set to the first invalid character on error.
 */
int cfg_eval_condition(char **args, char **err, const char **errptr)
{
	struct cfg_cond_expr *expr = NULL;
	const char *text = args[0];
	int ret = -1;

	if (!*text) /* note: empty = false */
		return 0;

	ret = cfg_parse_cond_expr(&text, &expr, err, errptr, MAX_CFG_RECURSION);
	if (ret != 0) {
		if (ret == -1) // parse error, error already reported
			goto done;
		while (*text == ' ' || *text == '\t')
			text++;

		if (*text) {
			ret = -1;
			memprintf(err, "unexpected character '%c' at the end of conditional expression '%s'",
				  *text, args[0]);
			goto fail;
		}

		ret = cfg_eval_cond_expr(expr, err);
		goto done;
	}

	/* ret == 0, no other way to parse this */
	ret = -1;
	memprintf(err, "unparsable conditional expression '%s'", args[0]);
 fail:
	if (errptr)
		*errptr = text;
 done:
	cfg_free_cond_expr(expr);
	return ret;
}
