new recursive function to convert objconf (preparation for nsapi conditions)

Tue, 08 Nov 2022 22:35:18 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Tue, 08 Nov 2022 22:35:18 +0100
changeset 420
0b42a35d6add
parent 419
f1d29785ad2d
child 421
437562f5681d

new recursive function to convert objconf (preparation for nsapi conditions)

src/server/daemon/config.c file | annotate | diff | comparison | revisions
src/server/util/object.c file | annotate | diff | comparison | revisions
src/server/util/object.h file | annotate | diff | comparison | revisions
--- 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);
 

mercurial