match_resp.c
#include "httpd.h"
#include "httpd_policy.h"
#define EX_UTILS_NO_FUNCS 1
#include "ex_utils.h"
#include "mk.h"
#include "match_req.h"
static int httpd_match_response_tst_d1(struct Con *, Httpd_req_data *,
Conf_parse *, Conf_token *, int *, int);
static int httpd__match_response_tst_op_d1(Conf_parse *conf, Conf_token *token,
int *matches, int prev_match,
void *passed_data)
{
struct Httpd__policy_req_tst_data *data = passed_data;
struct Con *con = data->con;
Httpd_req_data *req = data->req;
return (httpd_match_response_tst_d1(con, req, conf, token,
matches, prev_match));
}
static int httpd_match_response_tst_d1(struct Con *con, Httpd_req_data *req,
Conf_parse *conf, Conf_token *token,
int *matches, int prev_match)
{
int clist = FALSE;
struct Httpd__policy_req_tst_data data[1];
ASSERT(con && req);
ASSERT(matches);
CONF_SC_TOGGLE_CLIST_VAR(clist);
data->con = con;
data->req = req;
if (token->type >= CONF_TOKEN_TYPE_USER_BEG)
{
unsigned int type = token->type - CONF_TOKEN_TYPE_USER_BEG;
unsigned int nxt = 0;
Vstr_ref *ref = conf_token_get_user_value(conf, token, &nxt);
switch (type)
{
default:
vstr_ref_del(ref);
return (httpd_match_request_tst_d1(con, req, conf, token,
matches, prev_match,
httpd__match_response_tst_op_d1,
data));
}
vstr_ref_del(ref);
if (nxt)
return (conf_parse_num_token(conf, token, nxt));
}
else if (OPT_SERV_SYM_EQ("error-response-code-eq") ||
OPT_SERV_SYM_EQ("error-response-code=="))
{
unsigned int tmp = 0;
OPT_SERV_X_SYM_UINT_BEG(tmp);
else if (OPT_SERV_SYM_EQ("<bad>")) tmp = 400;
else if (OPT_SERV_SYM_EQ("<bad-request>")) tmp = 400;
else if (OPT_SERV_SYM_EQ("<forbidden>")) tmp = 403;
else if (OPT_SERV_SYM_EQ("<not-found>")) tmp = 404;
else if (OPT_SERV_SYM_EQ("<not-acceptable>")) tmp = 406;
else if (OPT_SERV_SYM_EQ("<gone>")) tmp = 410;
OPT_SERV_X_SYM_NUM_END();
*matches = tmp == req->req_error_code;
}
else if (OPT_SERV_SYM_EQ("error-response-detail-eq") ||
OPT_SERV_SYM_EQ("error-response-detail=="))
OPT_SERV_X_CSTR_EQ(req->req_error_xmsg);
else if (OPT_SERV_SYM_EQ("error-user-initiated-eq") ||
OPT_SERV_SYM_EQ("error-user-initiated=="))
{
unsigned int tmp = 0;
OPT_SERV_X_TOGGLE(tmp);
*matches = tmp == req->req_user_return_error_code;
}
else
return (httpd_match_request_tst_d1(con, req, conf, token,
matches, prev_match,
httpd__match_response_tst_op_d1, data));
return (TRUE);
}
static int httpd__policy_response_d0(struct Con *con, struct Httpd_req_data *req,
Conf_parse *conf, Conf_token *token,
int *stop)
{
static int prev_match = TRUE;
unsigned int depth = token->depth_num;
int matches = TRUE;
if (token->type != CONF_TOKEN_TYPE_SLIST)
return (FALSE);
while (conf_token_list_num(token, depth))
{
CONF_SC_PARSE_DEPTH_TOKEN_RET(conf, token, depth, FALSE);
if (!httpd_match_response_tst_d1(con, req, conf, token,
&matches, prev_match))
return (FALSE);
if (!matches)
{
prev_match = FALSE;
return (TRUE);
}
}
--depth;
prev_match = TRUE;
while (conf_token_list_num(token, depth))
{
CONF_SC_PARSE_DEPTH_TOKEN_RET(conf, token, depth, FALSE);
if (!httpd__policy_request_d1(con, req, conf, token, stop))
return (FALSE);
if (*stop || con->evnt->flag_q_closed)
return (TRUE);
}
return (TRUE);
}
int httpd_policy_response(struct Con *con, struct Httpd_req_data *req,
Conf_parse *conf, const Conf_token *beg_token)
{
Conf_token token[1];
Vstr_ref *ref = NULL;
unsigned int num = 0;
if (!beg_token->num)
return (TRUE);
*token = *beg_token;
if (!httpd__match_iter_beg(conf, token, &ref, &num))
return (TRUE);
do
{
int stop = FALSE;
conf_parse_num_token(conf, token, token->num);
assert(token->type == (CONF_TOKEN_TYPE_USER_BEG +
HTTPD_CONF_MAIN_MATCH_RESP));
while (token->type != CONF_TOKEN_TYPE_SLIST)
conf_parse_token(conf, token);
if (!httpd__policy_response_d0(con, req, conf, token, &stop))
goto conf_fail;
if (stop || con->evnt->flag_q_closed)
break;
} while (httpd__match_iter_nxt(conf, token, &ref, &num));
vstr_ref_del(ref);
vstr_del(conf->tmp, 1, conf->tmp->len);
return (TRUE);
conf_fail:
vstr_ref_del(ref);
vstr_del(conf->tmp, 1, conf->tmp->len);
if (!req->user_return_error_code)
{
conf_parse_backtrace(conf->tmp, "<policy-response>", conf, token);
HTTPD_ERR(req, 503);
}
return (FALSE);
}