--- a/src/server/safs/common.c Thu Jan 26 18:53:52 2017 +0100 +++ b/src/server/safs/common.c Sat Jan 28 10:38:34 2017 +0100 @@ -31,12 +31,202 @@ #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) { - printf("%s\n", 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) { + // TODO + } + 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; +}