Tue, 08 Nov 2022 22:35:18 +0100
new recursive function to convert objconf (preparation for nsapi conditions)
--- a/src/server/daemon/config.c Mon Nov 07 22:30:12 2022 +0100 +++ b/src/server/daemon/config.c Tue Nov 08 22:35:18 2022 +0100 @@ -837,15 +837,139 @@ return ret; } +// condition depth limit, evaluated in recursive convert_objconf_directives calls +#define OBJ_CONF_MAX_CONDITION_DEPTH 500 + + +// convert a condition +static Condition* convert_objconf_condition( + pool_handle_t *pool, + ConfigNode *node, + Condition *prev_condition, + Condition *parent_condition, + int *condition_index) +{ + const char *condnames[] = { "Client", "If", "ElseIf", "Else" }; + size_t typeindex; + if(serverconfig_validate_directive_name(node, condnames, 4, &typeindex)) { + // probably node->name is "Object", but nested objects are not allowed + // maybe there should be a special error message in this case + return NULL; + } + + // "ElseIf" and "Else" require, that a previous "If" or "ElseIf" node exists + if((typeindex == 2 || typeindex == 3) && prev_condition == NULL) { + return 1; + } + Condition *condition = pool_malloc(pool, sizeof(Condition)); + ZERO(condition, sizeof(Condition)); + + condition->index = *condition_index; + condition->parent = parent_condition; + condition->ifnot = prev_condition; + + (*condition_index)++; + return condition; +} + +// add directives to the httpd_object +// node->type can be CONFIG_NODE_DIRECTIVE or CONFIG_NODE_OBJECT +// CONFIG_NODE_DIRECTIVE can translated directly to directive* +// CONFIG_NODE_OBJECT node must be a condition (If/ElseIf/Else/Client) +static int convert_objconf_directives( + pool_handle_t *pool, + const char *file, + httpd_object *obj, + ConfigNode *node, + Condition *parent_condition, + int *condition_index) +{ + // previous condition, if it was the previous node + // this is needed to link the "ElseIf" or "Else" node with the previous + // "If" node + Condition *prev_condition = NULL; + + for(;node;node=node->next) { + if(node->type == CONFIG_NODE_OBJECT) { + Condition *condition = convert_objconf_condition(pool, node, prev_condition, parent_condition, condition_index); + if(!condition) { + return 1; + } + // add children of condition node + if(convert_objconf_directives(pool, file, obj, node->children_begin, condition, condition_index)) { + return 1; + } + + // previous condition is used to link "If" "IfElse" and "Else" + // if the current node is "Else", the if-else block is complete + // and we don't set prev_condition + //prev_condition = !strcmp(node->name.ptr, "Else") ? NULL : condition; + prev_condition = condition; + } else if(node->type == CONFIG_NODE_DIRECTIVE) { + directive *d = pool_malloc(pool, sizeof(directive)); + if(!d) return -1; + d->param = pblock_create_pool(pool, 8); + + d->cond = parent_condition; + + // add params + ConfigParam *param = node->args; + while(param != NULL) { + pblock_nvlinsert( + param->name.ptr, + param->name.length, + param->value.ptr, + param->value.length, + d->param); + param = param->next; + } + + // get function + char *func_name = pblock_findval("fn", d->param); + if(!func_name) { + log_ereport(LOG_MISCONFIG, "%s: Missing fn parameter", file); + return -1; + } + d->func = get_function(func_name); + if(!d->func) { + log_ereport(LOG_MISCONFIG, "func %s not found", func_name); + return -1; + } + + // add function to dtable + int dir_type = cfg_get_directive_type_num(cx_strcast(node->name)); + if(dir_type < 0) { + log_ereport(LOG_MISCONFIG, "unknown directive type %s", node->name); + } + object_add_directive(obj, d, dir_type); + + prev_condition = NULL; + } + } + + return 0; +} + static int convert_objconf(ServerConfiguration *scfg, ObjectConfig2 *cfg, HTTPObjectConfig *conf, cxmutstr file) { pool_handle_t *pool = conf->pool; + int condition_index = 0; + int i = 0; for(ConfigNode *objnode=cfg->root->children_begin;objnode;objnode=objnode->next) { if(objnode->type != CONFIG_NODE_OBJECT) { + if(objnode->type == CONFIG_NODE_DIRECTIVE) { + // error + return 1; + } continue; } + if(strcmp(objnode->name.ptr, "Object")) { + // error: not an object + return 1; + } + // get name and ppath cxmutstr cfg_name = cfg_param_get(objnode->args, cx_str("name")); cxmutstr cfg_ppath = cfg_param_get(objnode->args, cx_str("ppath")); @@ -869,50 +993,10 @@ conf->objects[i] = obj; - // TODO: this doesn't work with If/Else... nodes - // and needs to be rewritten // add directives - for(ConfigNode *dir=objnode->children_begin;dir;dir=dir->next) { - if(dir->type != CONFIG_NODE_DIRECTIVE) { - continue; - } - - directive *d = pool_malloc(pool, sizeof(directive)); - if(!d) return -1; - d->param = pblock_create_pool(pool, 8); - - // add params - ConfigParam *param = dir->args; - while(param != NULL) { - pblock_nvlinsert( - param->name.ptr, - param->name.length, - param->value.ptr, - param->value.length, - d->param); - param = param->next; - } - - // get function - char *func_name = pblock_findval("fn", d->param); - if(!func_name) { - log_ereport(LOG_MISCONFIG, "%s: Missing fn parameter", file.ptr); - return -1; - } - d->func = get_function(func_name); - if(!d->func) { - log_ereport(LOG_MISCONFIG, "func %s not found", func_name); - return -1; - } - - // add function to dtable - int dir_type = cfg_get_directive_type_num(cx_strcast(dir->name)); - if(dir_type < 0) { - log_ereport(LOG_MISCONFIG, "unknown directive type %s", dir->name); - } - object_add_directive(obj, d, dir_type); - } - + if(convert_objconf_directives(pool, file.ptr, obj, objnode->children_begin, NULL, &condition_index)) { + return 1; + } // next i++;
--- a/src/server/util/object.c Mon Nov 07 22:30:12 2022 +0100 +++ b/src/server/util/object.c Tue Nov 08 22:35:18 2022 +0100 @@ -109,26 +109,6 @@ context->last_req_code = REQ_NOACTION; } - -Condition* condition_from_str(pool_handle_t *pool, char *expr, size_t len) { - Condition *cond = pool_malloc(pool, sizeof(Condition)); - cond->expression = NULL; - cond->parent = NULL; - cond->index = 0; - - printf("Expression: {"); - fwrite(expr, len, 1, stdout); - printf("}\n"); - - cond->expression = expression_from_str(pool, expr, len); - - return cond; -} - -Expression* expression_from_str(pool_handle_t *pool, char *expr, size_t len) { - return NULL; -} - int condition_evaluate(Condition *condition, Session *sn, Request *rq) { return 1; }
--- a/src/server/util/object.h Mon Nov 07 22:30:12 2022 +0100 +++ b/src/server/util/object.h Tue Nov 08 22:35:18 2022 +0100 @@ -86,7 +86,9 @@ struct Condition { Condition *parent; + Condition *ifnot; Expression *expression; + int depth; int index; // used by NSAPIContext to link expression with result }; @@ -167,8 +169,6 @@ */ void nsapi_context_next_stage(NSAPIContext *context); -Condition* condition_from_str(pool_handle_t *pool, char *expr, size_t len); -Expression* expression_from_str(pool_handle_t *pool, char *expr, size_t len); int condition_evaluate(Condition *condition, Session *sn, Request *rq);