#include "common.h"
#include "../daemon/httprequest.h"
#include "../daemon/log.h"
#include "../util/pblock.h"
#include "../util/util.h"
#include <cx/map.h>
#include <cx/hash_map.h>
static CxMap *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 = cxHashMapCreate(cxDefaultAllocator,
CX_STORE_POINTERS,
32);
cxMapPut(var_names, cx_hash_key_str(
"insert-client"), (
void*)(
intptr_t)
COMMONSAF_INSERT_CLIENT);
cxMapPut(var_names, cx_hash_key_str(
"insert-vars"), (
void*)(
intptr_t)
COMMONSAF_INSERT_VARS);
cxMapPut(var_names, cx_hash_key_str(
"insert-reqpb"), (
void*)(
intptr_t)
COMMONSAF_INSERT_REQPB);
cxMapPut(var_names, cx_hash_key_str(
"insert-headers"), (
void*)(
intptr_t)
COMMONSAF_INSERT_HEADERS);
cxMapPut(var_names, cx_hash_key_str(
"insert-srvhdrs"), (
void*)(
intptr_t)
COMMONSAF_INSERT_SRVHDRS);
cxMapPut(var_names, cx_hash_key_str(
"set-client"), (
void*)(
intptr_t)
COMMONSAF_SET_CLIENT);
cxMapPut(var_names, cx_hash_key_str(
"set-vars"), (
void*)(
intptr_t)
COMMONSAF_SET_VARS);
cxMapPut(var_names, cx_hash_key_str(
"set-reqpb"), (
void*)(
intptr_t)
COMMONSAF_SET_REQPB);
cxMapPut(var_names, cx_hash_key_str(
"set-headers"), (
void*)(
intptr_t)
COMMONSAF_SET_HEADERS);
cxMapPut(var_names, cx_hash_key_str(
"set-srvhdrs"), (
void*)(
intptr_t)
COMMONSAF_SET_SRVHDRS);
cxMapPut(var_names, cx_hash_key_str(
"remove-client"), (
void*)(
intptr_t)
COMMONSAF_REMOVE_CLIENT);
cxMapPut(var_names, cx_hash_key_str(
"remove-vars"), (
void*)(
intptr_t)
COMMONSAF_REMOVE_VARS);
cxMapPut(var_names, cx_hash_key_str(
"remove-reqpb"), (
void*)(
intptr_t)
COMMONSAF_REMOVE_REQPB);
cxMapPut(var_names, cx_hash_key_str(
"remove-headers"), (
void*)(
intptr_t)
COMMONSAF_REMOVE_HEADERS);
cxMapPut(var_names, cx_hash_key_str(
"remove-srvhdrs"), (
void*)(
intptr_t)
COMMONSAF_REMOVE_SRVHDRS);
cxMapPut(var_names, cx_hash_key_str(
"abort"), (
void*)(
intptr_t)
COMMONSAF_ABORT);
cxMapPut(var_names, cx_hash_key_str(
"noaction"), (
void*)(
intptr_t)
COMMONSAF_NOACTION);
cxMapPut(var_names, cx_hash_key_str(
"error"), (
void*)(
intptr_t)
COMMONSAF_ERROR);
cxMapPut(var_names, cx_hash_key_str(
"escape"), (
void*)(
intptr_t)
COMMONSAF_ESCAPE);
cxMapPut(var_names, cx_hash_key_str(
"find-pathinfo-forward"), (
void*)(
intptr_t)
COMMONSAF_FIND_PATHINFO_FORWARD);
cxMapPut(var_names, cx_hash_key_str(
"http-downgrade"), (
void*)(
intptr_t)
COMMONSAF_HTTP_DOWNGRADE);
cxMapPut(var_names, cx_hash_key_str(
"http-upgrade"), (
void*)(
intptr_t)
COMMONSAF_HTTP_UPGRADE);
cxMapPut(var_names, cx_hash_key_str(
"keep-alive"), (
void*)(
intptr_t)
COMMONSAF_KEEP_ALIVE);
cxMapPut(var_names, cx_hash_key_str(
"name"), (
void*)(
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) {
cxstring n;
cxstring 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 = cx_strsubs(cx_strn(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,
const char *var,
char *value) {
intptr_t v = (
intptr_t)cxMapGet(var_names, cx_hash_key_str(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: {
char *end;
long status = strtol(value, &end,
10);
if(status <
100 || status >
999) {
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;
}
const char *msg =
NULL;
while(isspace(*end)) {
end++;
}
if(*end !=
'\0') {
msg = end;
}
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;
}