1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include "objconf.h"
30 #include "logging.h"
31
32 #include <string.h>
33
34 #include <cx/utils.h>
35
36
37
38
39
40
41
42
43
44 ObjectConfig *load_object_config(
char *file) {
45 FILE *in = fopen(file,
"r");
46 if(in ==
NULL) {
47 return NULL;
48 }
49
50 ObjectConfig *conf = malloc(
sizeof(ObjectConfig));
51 conf->parser.parse = objconf_parse;
52 conf->file = file;
53
54 conf->levels =
NULL;
55 conf->objects = cxLinkedListCreate(cxDefaultAllocator,
NULL,
CX_STORE_POINTERS);
56
57
58 int r = cfg_parse_basic_file((ConfigParser*)conf, in);
59 if(r !=
0) {
60
61 return NULL;
62 }
63
64 fclose(in);
65
66 return conf;
67 }
68
69 ObjectConfig2* objectconf_load(
const char *file) {
70 CxMempool *mp = cxBasicMempoolCreate(
512);
71 if(!mp) {
72 return NULL;
73 }
74
75
76 ConfigParser2 parser;
77 memset(&parser,
0,
sizeof(ConfigParser2));
78 parser.mp = mp;
79 parser.filename = file;
80 parser.delim =
"()/*%";
81 parser.validateDirective = objectconf_validate_directive;
82 parser.validateObjBegin = objectconf_validate_objbegin;
83 parser.validateObjEnd = objectconf_validate_objend;
84 parser.allow_hierarchy =
1;
85
86 ConfigNode *obj_config = serverconfig_load_file(&parser, file);
87 if(!obj_config) {
88 cxMempoolDestroy(mp);
89 return NULL;
90 }
91
92 ObjectConfig2 *conf = cxMalloc(mp->allocator,
sizeof(ObjectConfig2));
93 if(!conf) {
94 cxMempoolDestroy(mp);
95 return NULL;
96 }
97
98 conf->mp = mp;
99 conf->root = obj_config;
100
101 return conf;
102 }
103
104 void objectconf_free(ObjectConfig2 *objconf) {
105 cxMempoolDestroy(objconf->mp);
106 }
107
108 int objectconf_validate_directive(ConfigParser2 *parser, ConfigNode *node) {
109
110
111
112
113
114
115
116 const char *objnames[] = {
"Object",
"Client",
"If",
"ElseIf",
"Else" };
117 size_t typeindex;
118 if(!serverconfig_validate_directive_name(node, objnames,
5, &typeindex)) {
119 return 0;
120 }
121
122
123 const char *dirtypes[] = {
"AuthTrans",
"NameTrans",
"PathCheck",
"ObjectType",
"Service",
"AddLog",
"Error" };
124 if(serverconfig_validate_directive_name(node, dirtypes,
7, &typeindex)) {
125 return 1;
126 }
127
128
129 ConfigParam *param_err;
130 if(serverconfig_check_param_names(node, ¶m_err)) {
131 return 1;
132 }
133
134
135 cxstring fn = serverconfig_directive_get_arg(node, cx_str(
"fn"));
136 if(fn.length ==
0) {
137 return 1;
138 }
139
140 return 0;
141 }
142
143 static int validate_else_node(ConfigNode *node) {
144
145 ConfigNode *prev = serverconfig_previous_dir_or_obj(node);
146 const char *allowed_prev_types[] = {
"If",
"ElseIf" };
147 size_t typeindex;
148 if(serverconfig_validate_directive_name(prev, allowed_prev_types,
2, &typeindex)) {
149 return 1;
150 }
151
152
153 return node->args ?
1 :
0;
154 }
155
156 static int validate_elseif_node(ConfigNode *node) {
157
158
159
160 const char *allowed_prev_types[] = {
"If",
"ElseIf" };
161 size_t typeindex;
162 ConfigNode *prev = serverconfig_previous_dir_or_obj(node);
163 while(prev) {
164 if(serverconfig_validate_directive_name(prev, allowed_prev_types,
2, &typeindex)) {
165 return 1;
166 }
167
168 if(typeindex ==
0) {
169 return 0;
170 }
171
172 prev = serverconfig_previous_dir_or_obj(node);
173 }
174
175 return 1;
176 }
177
178 int objectconf_validate_objbegin(ConfigParser2 *parser, ConfigNode *node) {
179
180 const char *objnames[] = {
"Object",
"Client",
"If",
"ElseIf",
"Else" };
181 size_t typeindex;
182 if(serverconfig_validate_directive_name(node, objnames,
5, &typeindex)) {
183 return 1;
184 }
185
186
187 if(typeindex ==
4) {
188
189 return validate_else_node(node);
190 }
191
192
193 if(typeindex ==
3 && validate_elseif_node(node)) {
194 return 1;
195 }
196
197
198
199 if(typeindex ==
0) {
200
201 ConfigParam *err;
202 if(serverconfig_check_param_names(node, &err)) {
203 return 1;
204 }
205 return 0;
206 }
207
208
209 return node->args ?
0 :
1;
210 }
211
212 int objectconf_validate_objend(ConfigParser2 *parser, ConfigNode *node) {
213 return 0;
214 }
215
216
217 void free_object_config(ObjectConfig *conf) {
218
219 if(conf->levels) {
220
221 }
222
223
224
225 free(conf);
226 }
227
228
229
230 int objconf_parse(
void *p, ConfigLine *begin, ConfigLine *end, cxmutstr line) {
231 ObjectConfig *conf = p;
232
233 begin->type = cfg_get_line_type(line);
234 switch(begin->type) {
235 case LINE_BEGIN_TAG: {
236 ConfigTag *tag = cfg_parse_begin_tag(line, conf->parser.mp);
237 if(tag ==
NULL) {
238 ws_cfg_log(
LOG_FAILURE,
"Parse error in %s", conf->file);
239 exit(-
1);
240 }
241 tag->begin = begin;
242 tag->end = end;
243 tag->type_num = cfg_get_tag_type(cx_strcast(tag->name));
244
245 if(objconf_on_begin_tag(conf, tag) !=
0) {
246 fprintf(stderr,
"1error\n");
247 exit(-
1);
248 }
249 break;
250 }
251 case LINE_END_TAG: {
252 cxmutstr tag = cfg_get_end_tag_name(line);
253 if(objconf_on_end_tag(conf, tag) !=
0) {
254 fprintf(stderr,
"2error\n");
255 exit(-
1);
256 }
257
258 break;
259 }
260 case LINE_DIRECTIVE: {
261 ConfigDirective *dir = cfg_parse_directive(
262 line,
263 conf->parser.mp);
264 dir->begin = begin;
265 dir->end = end;
266 if(objconf_on_directive(conf, dir) !=
0) {
267 fprintf(stderr,
"3error\n");
268 exit(-
1);
269 }
270 }
271 }
272 return 0;
273 }
274
275 int objconf_on_begin_tag(ObjectConfig *conf, ConfigTag *tag) {
276 CxAllocator *mp = conf->parser.mp;
277 if(tag->type_num !=
TAG_OBJECT) {
278 ConfigParserLevel *l = conf->levels;
279 if(l->tag->type_num !=
TAG_OBJECT) {
280 tag->parent = l->tag;
281 }
282 }
283
284
285 switch(tag->type_num) {
286 case TAG_OBJECT: {
287 ConfigObject *obj =
OBJ_NEW_N(mp, ConfigObject);
288 obj->begin = tag->begin;
289 obj->end = tag->end;
290
291 obj->name = cfg_param_get(tag->param, cx_str(
"name"));
292 obj->ppath = cfg_param_get(tag->param, cx_str(
"ppath"));
293
294 conf->obj = obj;
295
296 cxListAdd(conf->objects, obj);
297
298
299 ConfigParserLevel *lvl =
OBJ_NEW(mp, ConfigParserLevel);
300 lvl->iftag =
NULL;
301 lvl->levelnum =
1;
302 lvl->tag = tag;
303 lvl->next =
NULL;
304
305 CFG_LEVEL_PREPEND(&conf->levels, lvl);
306
307 break;
308 }
309 case TAG_IF: {
310
311 ConfigParserLevel *last_lvl = conf->levels;
312
313 ConfigParserLevel *lvl =
OBJ_NEW(mp, ConfigParserLevel);
314
315 lvl->iftag =
NULL;
316 lvl->levelnum = last_lvl->levelnum +
1;
317 lvl->tag = tag;
318
319 CFG_LEVEL_PREPEND(&conf->levels, lvl);
320 last_lvl->iftag = tag;
321
322 break;
323 }
324 case TAG_ELSEIF: {
325 }
326 case TAG_ELSE: {
327
328 ConfigParserLevel *last_lvl = conf->levels;
329 tag->iftag = last_lvl->iftag;
330
331 ConfigParserLevel *lvl =
OBJ_NEW(
332 conf->parser.mp,
333 ConfigParserLevel);
334
335 lvl->iftag = last_lvl->tag;
336 lvl->levelnum = last_lvl->levelnum +
1;
337 lvl->tag = tag;
338
339 CFG_LEVEL_PREPEND(&conf->levels, lvl);
340
341 break;
342 }
343 case TAG_CLIENT: {
344
345
346
347
348 break;
349 }
350 default: {
351 ws_cfg_log(
LOG_FAILURE,
"objconf: unknown tag");
352 return 1;
353 }
354 }
355
356 return 0;
357 }
358
359 int objconf_on_end_tag(ObjectConfig *conf, cxmutstr tagname) {
360 int type = cfg_get_tag_type(cx_strcast(tagname));
361 if(type == -
1) {
362 ws_cfg_log(
LOG_FAILURE,
"objconf: unknown tag");
363 return 1;
364 }
else {
365 if(type ==
TAG_OBJECT) {
366 conf->obj =
NULL;
367 }
368
369
370
371
372
373
374
375
376 conf->levels = conf->levels->next;
377 }
378
379 return 0;
380 }
381
382 int objconf_on_directive(ObjectConfig *conf, ConfigDirective *dir) {
383 ConfigParserLevel *lvl = conf->levels;
384
385
386
387 if(lvl->tag->type_num !=
TAG_OBJECT) {
388 dir->condition = lvl->tag;
389 }
390
391
392
393
394
395
396
397
398
399 ConfigDirectiveList *dir_entry = cxMalloc(conf->parser.mp,
sizeof(ConfigDirectiveList));
400 dir_entry->directive = dir;
401 dir_entry->next =
NULL;
402 CFG_DIRECTIVES_ADD(&conf->obj->directives[dir->type_num], dir_entry);
403
404 return 0;
405 }
406
407