#include "common.h"
#include "../daemon/httprequest.h"
#include "../daemon/log.h"
#include "../util/pblock.h"
#include "../util/util.h"
#include "../../ucx/map.h"
static UcxMap *var_names;
enum SAFVarNames {
COMMONSAF_INSERT_CLIENT =
1,
COMMONSAF_INSERT_VARS,
COMMONSAF_INSERT_REQPB,
COMMONSAF_INSERT_HEADERS,
COMMONSAF_INSERT_SRVHDRS,
COMMONSAF_SET_CLIENT,
COMMONSAF_SET_VARS,
COMMONSAF_SET_REQPB,
COMMONSAF_SET_HEADERS,
COMMONSAF_SET_SRVHDRS,
COMMONSAF_REMOVE_CLIENT,
COMMONSAF_REMOVE_VARS,
COMMONSAF_REMOVE_REQPB,
COMMONSAF_REMOVE_HEADERS,
COMMONSAF_REMOVE_SRVHDRS,
COMMONSAF_ABORT,
COMMONSAF_NOACTION,
COMMONSAF_ERROR,
COMMONSAF_ESCAPE,
COMMONSAF_FIND_PATHINFO_FORWARD,
COMMONSAF_HTTP_DOWNGRADE,
COMMONSAF_HTTP_UPGRADE,
COMMONSAF_KEEP_ALIVE,
COMMONSAF_NAME,
COMMONSAF_SENTHDRS,
COMMONSAF_STOP,
COMMONSAF_URL
};
#define COMMONSAF_RET_DEF 0
#define COMMONSAF_RET_NOACTION 1
#define COMMONSAF_RET_STOP 2
#define COMMONSAF_REQ_ABORTED -
1
#define COMMONSAF_RET_ERROR -
2
void common_saf_init() {
var_names = ucx_map_new(
32);
ucx_map_cstr_put(var_names,
"insert-client", (
intptr_t)
COMMONSAF_INSERT_CLIENT);
ucx_map_cstr_put(var_names,
"insert-vars", (
intptr_t)
COMMONSAF_INSERT_VARS);
ucx_map_cstr_put(var_names,
"insert-reqpb", (
intptr_t)
COMMONSAF_INSERT_REQPB);
ucx_map_cstr_put(var_names,
"insert-headers", (
intptr_t)
COMMONSAF_INSERT_HEADERS);
ucx_map_cstr_put(var_names,
"insert-srvhdrs", (
intptr_t)
COMMONSAF_INSERT_SRVHDRS);
ucx_map_cstr_put(var_names,
"set-client", (
intptr_t)
COMMONSAF_SET_CLIENT);
ucx_map_cstr_put(var_names,
"set-vars", (
intptr_t)
COMMONSAF_SET_VARS);
ucx_map_cstr_put(var_names,
"set-reqpb", (
intptr_t)
COMMONSAF_SET_REQPB);
ucx_map_cstr_put(var_names,
"set-headers", (
intptr_t)
COMMONSAF_SET_HEADERS);
ucx_map_cstr_put(var_names,
"set-srvhdrs", (
intptr_t)
COMMONSAF_SET_SRVHDRS);
ucx_map_cstr_put(var_names,
"remove-client", (
intptr_t)
COMMONSAF_REMOVE_CLIENT);
ucx_map_cstr_put(var_names,
"remove-vars", (
intptr_t)
COMMONSAF_REMOVE_VARS);
ucx_map_cstr_put(var_names,
"remove-reqpb", (
intptr_t)
COMMONSAF_REMOVE_REQPB);
ucx_map_cstr_put(var_names,
"remove-headers", (
intptr_t)
COMMONSAF_REMOVE_HEADERS);
ucx_map_cstr_put(var_names,
"remove-srvhdrs", (
intptr_t)
COMMONSAF_REMOVE_SRVHDRS);
ucx_map_cstr_put(var_names,
"abort", (
intptr_t)
COMMONSAF_ABORT);
ucx_map_cstr_put(var_names,
"noaction", (
intptr_t)
COMMONSAF_NOACTION);
ucx_map_cstr_put(var_names,
"error", (
intptr_t)
COMMONSAF_ERROR);
ucx_map_cstr_put(var_names,
"escape", (
intptr_t)
COMMONSAF_ESCAPE);
ucx_map_cstr_put(var_names,
"find-pathinfo-forward", (
intptr_t)
COMMONSAF_FIND_PATHINFO_FORWARD);
ucx_map_cstr_put(var_names,
"http-downgrade", (
intptr_t)
COMMONSAF_HTTP_DOWNGRADE);
ucx_map_cstr_put(var_names,
"http-upgrade", (
intptr_t)
COMMONSAF_HTTP_UPGRADE);
ucx_map_cstr_put(var_names,
"keep-alive", (
intptr_t)
COMMONSAF_KEEP_ALIVE);
ucx_map_cstr_put(var_names,
"name", (
intptr_t)
COMMONSAF_NAME);
}
int print_message(pblock *pb, Session *sn, Request *rq) {
char *msg = pblock_findval(
"msg", pb);
if(msg) {
log_ereport(
LOG_INFORM,
"%s", msg);
}
return REQ_NOACTION;
}
static void var_set(
char *value, pblock *pb, WSBool insert) {
sstr_t n;
sstr_t v;
v.ptr =
NULL;
n.ptr = value;
int i;
int len = strlen(value);
for(i=
1;i<len;i++) {
if(value[i] ==
'=') {
n.length = i;
v = sstrsubs(sstrn(value, len), i +
1);
break;
}
}
if(!v.ptr || v.length ==
0) {
log_ereport(
LOG_MISCONFIG,
"set-variable: string ''%s'' has not name=value format",
value);
return;
}
if(!insert) {
}
pblock_nvlinsert(n.ptr, n.length, v.ptr, v.length, pb);
}
static int set_var(Session *sn, Request *rq,
char *var,
char *value) {
intptr_t v = (
intptr_t)ucx_map_cstr_get(var_names, var);
switch(v) {
default:
break;
case COMMONSAF_INSERT_CLIENT: var_set(value, sn->client,
TRUE);
break;
case COMMONSAF_INSERT_VARS: var_set(value, rq->vars,
TRUE);
break;
case COMMONSAF_INSERT_REQPB: var_set(value, rq->reqpb,
TRUE);
break;
case COMMONSAF_INSERT_HEADERS: var_set(value, rq->headers,
TRUE);
break;
case COMMONSAF_INSERT_SRVHDRS: var_set(value, rq->srvhdrs,
TRUE);
break;
case COMMONSAF_SET_CLIENT: var_set(value, sn->client,
FALSE);
break;
case COMMONSAF_SET_VARS: var_set(value, rq->vars,
FALSE);
break;
case COMMONSAF_SET_REQPB: var_set(value, rq->reqpb,
FALSE);
break;
case COMMONSAF_SET_HEADERS: var_set(value, rq->headers,
FALSE);
break;
case COMMONSAF_SET_SRVHDRS: var_set(value, rq->srvhdrs,
FALSE);
break;
case COMMONSAF_REMOVE_CLIENT: pblock_remove(value, sn->client);
break;
case COMMONSAF_REMOVE_VARS: pblock_remove(value, rq->vars);
break;
case COMMONSAF_REMOVE_HEADERS: pblock_remove(value, rq->headers);
break;
case COMMONSAF_REMOVE_SRVHDRS: pblock_remove(value, rq->srvhdrs);
break;
case COMMONSAF_ABORT:
return COMMONSAF_REQ_ABORTED;
case COMMONSAF_NOACTION:
return COMMONSAF_RET_NOACTION;
case COMMONSAF_ERROR: {
int len = strlen(value);
WSBool isnum =
TRUE;
int i;
for(i=
0;i<len;i++) {
if(!isdigit(value[i])) {
isnum =
FALSE;
break;
}
}
int64_t status;
int ret = util_strtoint(value, &status);
if(status <
100 || ret >
999 || !ret) {
log_ereport(
LOG_MISCONFIG,
"set-variable: error value must contain a 3-digit http status code");
protocol_status(sn, rq,
500,
NULL);
return COMMONSAF_RET_ERROR;
}
char *msg = isnum ?
NULL : sstrtrim(sstr(value + i)).ptr;
protocol_status(sn, rq, (
int)status, msg);
return COMMONSAF_REQ_ABORTED;
}
case COMMONSAF_ESCAPE:
break;
case COMMONSAF_FIND_PATHINFO_FORWARD:
break;
case COMMONSAF_HTTP_DOWNGRADE:
break;
case COMMONSAF_HTTP_UPGRADE:
break;
case COMMONSAF_KEEP_ALIVE: {
rq->rq_attr.keep_alive = util_getboolean(var,
0);
break;
}
case COMMONSAF_NAME: {
pblock_kvinsert(pb_key_name, value, strlen(value), rq->vars);
break;
}
case COMMONSAF_SENTHDRS:
break;
case COMMONSAF_STOP:
return COMMONSAF_RET_STOP;
case COMMONSAF_URL:
break;
}
return COMMONSAF_RET_DEF;
}
int set_variable(pblock *pb, Session *sn, Request *rq) {
int ret =
REQ_NOACTION;
int set =
0;
for(
int i=
0;i<pb->hsize;i++) {
pb_entry *entry = pb->ht[i];
while(entry) {
int r = set_var(sn, rq, entry->param->name, entry->param->value);
switch(r) {
default:
case COMMONSAF_RET_DEF:
break;
case COMMONSAF_RET_NOACTION: set =
1; ret =
REQ_NOACTION;
break;
case COMMONSAF_RET_STOP: set =
1; ret =
REQ_PROCEED;
break;
case COMMONSAF_REQ_ABORTED: ret = set ? ret :
REQ_ABORTED;
break;
case COMMONSAF_RET_ERROR:
return REQ_ABORTED;
}
entry = entry->next;
}
}
return ret;
}