62 |
62 |
63 fclose(in); |
63 fclose(in); |
64 |
64 |
65 return conf; |
65 return conf; |
66 } |
66 } |
|
67 |
|
68 ObjectConfig2* objectconf_load(const char *file) { |
|
69 CxMempool *mp = cxBasicMempoolCreate(512); |
|
70 if(!mp) { |
|
71 return NULL; |
|
72 } |
|
73 |
|
74 // setup parser |
|
75 ConfigParser2 parser; |
|
76 memset(&parser, 0, sizeof(ConfigParser2)); |
|
77 parser.mp = mp; |
|
78 parser.validateDirective = objectconf_validate_directive; |
|
79 parser.validateObjBegin = objectconf_validate_objbegin; |
|
80 parser.validateObjEnd = objectconf_validate_objend; |
|
81 parser.allow_hierarchy = 1; |
|
82 |
|
83 ConfigNode *obj_config = serverconfig_load_file(&parser, file); |
|
84 if(!obj_config) { |
|
85 cxMempoolDestroy(mp); |
|
86 return NULL; |
|
87 } |
|
88 |
|
89 ObjectConfig2 *conf = cxMalloc(mp->allocator, sizeof(ObjectConfig2)); |
|
90 if(!conf) { |
|
91 cxMempoolDestroy(mp); |
|
92 return NULL; |
|
93 } |
|
94 |
|
95 conf->mp = mp; |
|
96 conf->root = obj_config; |
|
97 |
|
98 return conf; |
|
99 } |
|
100 |
|
101 void objectconf_free(ObjectConfig2 *objconf) { |
|
102 cxMempoolDestroy(objconf->mp); |
|
103 } |
|
104 |
|
105 int objectconf_validate_directive(ConfigParser2 *parser, ConfigNode *node) { |
|
106 // It is possible that this function is called for Objects |
|
107 // if { is on the next line |
|
108 // It may be possible to fix the parser to not do that, but it is fine |
|
109 // to just deal with that here |
|
110 |
|
111 // ignore if node->name is an Object name like |
|
112 // Object, Client, If, Else IfElse |
|
113 const char *objnames[] = { "Object", "Client", "If", "ElseIf", "Else" }; |
|
114 size_t typeindex; |
|
115 if(!serverconfig_validate_directive_name(node, objnames, 5, &typeindex)) { |
|
116 return 0; |
|
117 } |
|
118 |
|
119 // now check directive type |
|
120 const char *dirtypes[] = { "AuthTrans", "NameTrans", "PathCheck", "ObjectType", "Service", "AddLog", "Error" }; |
|
121 if(serverconfig_validate_directive_name(node, dirtypes, 7, &typeindex)) { |
|
122 return 1; |
|
123 } |
|
124 |
|
125 // directives must have parameter names |
|
126 ConfigParam *param_err; |
|
127 if(serverconfig_check_param_names(node, ¶m_err)) { |
|
128 return 1; |
|
129 } |
|
130 |
|
131 // check if the fn parameter exists |
|
132 cxstring fn = serverconfig_directive_get_arg(node, cx_str("fn")); |
|
133 if(fn.length == 0) { |
|
134 return 1; |
|
135 } |
|
136 |
|
137 return 0; |
|
138 } |
|
139 |
|
140 static int validate_else_node(ConfigNode *node) { |
|
141 // previous node must be "If" or "ElseIf" |
|
142 ConfigNode *prev = serverconfig_previous_dir_or_obj(node); |
|
143 const char *allowed_prev_types[] = { "If", "ElseIf" }; |
|
144 size_t typeindex; |
|
145 if(serverconfig_validate_directive_name(prev, allowed_prev_types, 2, &typeindex)) { |
|
146 return 1; // prevous node (not counting space, comments) is not "If" or "Else" |
|
147 } |
|
148 |
|
149 // "Else" must have no args |
|
150 return node->args ? 1 : 0; |
|
151 } |
|
152 |
|
153 static int validate_elseif_node(ConfigNode *node) { |
|
154 // the previous node must be "If" or "IfElse" |
|
155 // in case if "IfElse", we also have to check all previous nodes, until |
|
156 // we find the starting "If" node |
|
157 const char *allowed_prev_types[] = { "If", "ElseIf" }; |
|
158 size_t typeindex; |
|
159 ConfigNode *prev = serverconfig_previous_dir_or_obj(node); |
|
160 while(prev) { |
|
161 if(serverconfig_validate_directive_name(prev, allowed_prev_types, 2, &typeindex)) { |
|
162 return 1; // previous node was not "If" or "ElseIf" |
|
163 } |
|
164 // we found a valid "If" node, the whole construct is valid |
|
165 if(typeindex == 0) { |
|
166 return 0; |
|
167 } |
|
168 |
|
169 prev = serverconfig_previous_dir_or_obj(node); |
|
170 } |
|
171 // at this point we found only "IfElse" nodes, but no "If" node |
|
172 return 1; |
|
173 } |
|
174 |
|
175 int objectconf_validate_objbegin(ConfigParser2 *parser, ConfigNode *node) { |
|
176 // get object type |
|
177 const char *objnames[] = { "Object", "Client", "If", "ElseIf", "Else" }; |
|
178 size_t typeindex; |
|
179 if(serverconfig_validate_directive_name(node, objnames, 5, &typeindex)) { |
|
180 return 1; // unknown object type |
|
181 } |
|
182 |
|
183 // some special requirements for "Else" node |
|
184 if(typeindex == 4) { |
|
185 // type is "Else" |
|
186 return validate_else_node(node); |
|
187 } |
|
188 |
|
189 // check "ElseIf" was used after "If" or "IfElse" |
|
190 if(typeindex == 3 && validate_elseif_node(node)) { |
|
191 return 1; |
|
192 } |
|
193 |
|
194 // only Object must have a name/value arg, other types can have more |
|
195 // complex parameters |
|
196 if(typeindex == 0) { |
|
197 // type is "Object" |
|
198 ConfigParam *err; |
|
199 if(serverconfig_check_param_names(node, &err)) { |
|
200 return 1; |
|
201 } |
|
202 return 0; |
|
203 } |
|
204 |
|
205 // all remaining object types must have arguments, but don't check more |
|
206 return node->args ? 0 : 1; |
|
207 } |
|
208 |
|
209 int objectconf_validate_objend(ConfigParser2 *parser, ConfigNode *node) { |
|
210 return 0; |
|
211 } |
|
212 |
67 |
213 |
68 void free_object_config(ObjectConfig *conf) { |
214 void free_object_config(ObjectConfig *conf) { |
69 // free other lists |
215 // free other lists |
70 if(conf->levels) { |
216 if(conf->levels) { |
71 //ucx_list_free(conf->levels); |
217 //ucx_list_free(conf->levels); |