src/server/config/objconf.c

changeset 419
f1d29785ad2d
parent 415
d938228c382e
child 425
6440171c257f
equal deleted inserted replaced
418:b7dcc9c4f270 419:f1d29785ad2d
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, &param_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);

mercurial