146 |
148 |
147 ServerConfiguration *serverconfig = pool_calloc(pool, 1, sizeof(ServerConfiguration)); |
149 ServerConfiguration *serverconfig = pool_calloc(pool, 1, sizeof(ServerConfiguration)); |
148 serverconfig->ref = 1; |
150 serverconfig->ref = 1; |
149 serverconfig->pool = pool; |
151 serverconfig->pool = pool; |
150 |
152 |
151 UcxAllocator allocator = util_pool_allocator(serverconfig->pool); |
153 CxAllocator *allocator = pool_allocator(serverconfig->pool); |
152 serverconfig->a = pool_malloc(pool, sizeof(UcxAllocator)); |
154 serverconfig->a = allocator; |
153 *serverconfig->a = allocator; |
155 |
154 |
156 serverconfig->listeners = cxPointerLinkedListCreate(serverconfig->a, cx_cmp_ptr); |
155 serverconfig->listeners = NULL; |
157 serverconfig->logfiles = cxPointerLinkedListCreate(serverconfig->a, cx_cmp_ptr); |
156 serverconfig->host_vs = ucx_map_new_a(serverconfig->a, 16); |
158 serverconfig->host_vs = cxHashMapCreate(serverconfig->a, 16); |
157 serverconfig->authdbs = ucx_map_new_a(serverconfig->a, 16); |
159 serverconfig->authdbs = cxHashMapCreate(serverconfig->a, 16); |
158 serverconfig->resources = ucx_map_new_a(serverconfig->a, 16); |
160 serverconfig->resources = cxHashMapCreate(serverconfig->a, 16); |
159 serverconfig->dav = ucx_map_new_a(serverconfig->a, 16); |
161 serverconfig->dav = cxHashMapCreate(serverconfig->a, 16); |
160 |
162 |
161 // STAGE 1 load_server_conf: |
163 // STAGE 1 load_server_conf: |
162 // At stage 1 we load the file and get the Runtime infos for changing |
164 // At stage 1 we load the file and get the Runtime infos for changing |
163 // the uid, which must be done before most steps. |
165 // the uid, which must be done before most steps. |
164 // Before the uid can be changed, we also need to bind listeners, |
166 // Before the uid can be changed, we also need to bind listeners, |
166 // |
168 // |
167 // Runtime |
169 // Runtime |
168 // Listener (dependencies: Threadpool, EventHandler) |
170 // Listener (dependencies: Threadpool, EventHandler) |
169 |
171 |
170 // load Runtime config |
172 // load Runtime config |
171 UcxList *list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("Runtime")); |
173 CxList *list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, cx_str("Runtime")); |
172 UCX_FOREACH(elm, list) { |
174 CxIterator iter = cxListIterator(list, 0); |
173 ConfigNode *runtimeobj = elm->data; |
175 cx_foreach(ConfigNode *, runtimeobj, iter) { |
174 if(cfg_handle_runtime(serverconfig, runtimeobj)) { |
176 if(cfg_handle_runtime(serverconfig, runtimeobj)) { |
175 // error |
177 // error |
176 return NULL; |
178 return NULL; |
177 } |
179 } |
178 } |
180 } |
179 ucx_list_free(list); |
181 cxListDestroy(list); |
180 |
182 |
181 // load threadpool config |
183 // load threadpool config |
182 log_ereport(LOG_DEBUG, "apply config: Threadpool"); |
184 log_ereport(LOG_DEBUG, "apply config: Threadpool"); |
183 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("Threadpool")); |
185 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, cx_str("Threadpool")); |
184 UCX_FOREACH(elm, list) { |
186 iter = cxListIterator(list, 0); |
185 if(cfg_handle_threadpool(serverconfig, elm->data)) { |
187 cx_foreach(ConfigNode *, elm, iter) { |
|
188 if(cfg_handle_threadpool(serverconfig, elm)) { |
186 return NULL; |
189 return NULL; |
187 } |
190 } |
188 } |
191 } |
189 ucx_list_free(list); |
192 cxListDestroy(list); |
190 // check thread pool config |
193 // check thread pool config |
191 if(check_thread_pool_cfg() != 0) { |
194 if(check_thread_pool_cfg() != 0) { |
192 /* critical error */ |
195 /* critical error */ |
193 return NULL; |
196 return NULL; |
194 } |
197 } |
195 |
198 |
196 // load eventhandler config |
199 // load eventhandler config |
197 log_ereport(LOG_DEBUG, "apply config: EventHandler"); |
200 log_ereport(LOG_DEBUG, "apply config: EventHandler"); |
198 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("EventHandler")); |
201 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, cx_str("EventHandler")); |
199 UCX_FOREACH(elm, list) { |
202 iter = cxListIterator(list, 0); |
200 if(cfg_handle_eventhandler(serverconfig, elm->data)) { |
203 cx_foreach(ConfigNode *, elm, iter) { |
|
204 if(cfg_handle_eventhandler(serverconfig, elm)) { |
201 // error |
205 // error |
202 return NULL; |
206 return NULL; |
203 } |
207 } |
204 } |
208 } |
205 // check event handler config |
209 // check event handler config |
206 if(check_event_handler_cfg() != 0) { |
210 if(check_event_handler_cfg() != 0) { |
207 /* critical error */ |
211 /* critical error */ |
208 return NULL; |
212 return NULL; |
209 } |
213 } |
210 ucx_list_free(list); |
214 cxListDestroy(list); |
211 |
215 |
212 // load Listener config |
216 // load Listener config |
213 log_ereport(LOG_DEBUG, "apply config: Listener"); |
217 log_ereport(LOG_DEBUG, "apply config: Listener"); |
214 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("Listener")); |
218 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, cx_str("Listener")); |
215 UCX_FOREACH(elm, list) { |
219 iter = cxListIterator(list, 0); |
216 ConfigNode *scfgobj = elm->data; |
220 cx_foreach(ConfigNode *, scfgobj, iter) { |
217 if(cfg_handle_listener(serverconfig, scfgobj)) { |
221 if(cfg_handle_listener(serverconfig, scfgobj)) { |
218 return NULL; |
222 return NULL; |
219 } |
223 } |
220 } |
224 } |
221 ucx_list_free(list); |
225 cxListDestroy(list); |
222 |
226 |
223 // we return here, to let the webserver use the runtime info to |
227 // we return here, to let the webserver use the runtime info to |
224 // change the uid if needed |
228 // change the uid if needed |
225 return serverconfig; |
229 return serverconfig; |
226 } |
230 } |
240 * Listener (we set the VirtualServer later) |
244 * Listener (we set the VirtualServer later) |
241 * VirtualServer (dependencies: Listener) |
245 * VirtualServer (dependencies: Listener) |
242 */ |
246 */ |
243 |
247 |
244 // init logfile first |
248 // init logfile first |
245 UcxList *list; |
249 CxList *list; |
246 |
250 |
247 log_ereport(LOG_DEBUG, "apply config: LogFile"); |
251 log_ereport(LOG_DEBUG, "apply config: LogFile"); |
248 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("LogFile")); |
252 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, cx_str("LogFile")); |
249 if(list) { |
253 CxIterator iter = cxListIterator(list, 0); |
250 ConfigNode *logobj = list->data; |
254 cx_foreach(ConfigNode *, logobj, iter) { |
251 if(!logobj) { |
255 if(!logobj) { |
252 // error |
256 // error |
253 return NULL; // TODO: fix memory leak |
257 cxListDestroy(list); |
|
258 return NULL; |
254 } |
259 } |
255 |
260 |
256 int ret = cfg_handle_logfile(serverconfig, logobj); |
261 int ret = cfg_handle_logfile(serverconfig, logobj); |
257 if(ret != 0) { |
262 if(ret != 0) { |
258 // cannot initialize log file |
263 // cannot initialize log file |
259 return NULL; // TODO: fix memory leak |
264 cxListDestroy(list); |
260 } |
265 return NULL; |
261 } else { |
266 } |
262 // horrible error |
267 } |
263 return NULL; |
268 cxListDestroy(list); |
264 } |
|
265 ucx_list_free(list); |
|
266 |
269 |
267 log_ereport(LOG_DEBUG, "apply config: AccessLog"); |
270 log_ereport(LOG_DEBUG, "apply config: AccessLog"); |
268 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("AccessLog")); |
271 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, cx_str("AccessLog")); |
269 UCX_FOREACH(elm, list) { |
272 iter = cxListIterator(list, 0); |
270 ConfigNode *scfgobj = elm->data; |
273 cx_foreach(ConfigNode *, scfgobj, iter) { |
271 if(cfg_handle_accesslog(serverconfig, scfgobj)) { |
274 if(cfg_handle_accesslog(serverconfig, scfgobj)) { |
272 return NULL; |
275 return NULL; |
273 } |
276 } |
274 } |
277 } |
275 ucx_list_free(list); |
278 cxListDestroy(list); |
276 |
279 |
277 log_ereport(LOG_DEBUG, "apply config: AuthDB"); |
280 log_ereport(LOG_DEBUG, "apply config: AuthDB"); |
278 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("AuthDB")); |
281 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, cx_str("AuthDB")); |
279 UCX_FOREACH(elm, list) { |
282 iter = cxListIterator(list, 0); |
280 ConfigNode *scfgobj = elm->data; |
283 cx_foreach(ConfigNode *, scfgobj, iter) { |
281 if(cfg_handle_authdb(serverconfig, scfgobj)) { |
284 if(cfg_handle_authdb(serverconfig, scfgobj)) { |
282 return NULL; |
285 return NULL; |
283 } |
286 } |
284 } |
287 } |
285 ucx_list_free(list); |
288 cxListDestroy(list); |
286 |
289 |
287 log_ereport(LOG_DEBUG, "apply config: VirtualServer"); |
290 log_ereport(LOG_DEBUG, "apply config: VirtualServer"); |
288 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("VirtualServer")); |
291 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, cx_str("VirtualServer")); |
289 UCX_FOREACH(elm, list) { |
292 iter = cxListIterator(list, 0); |
290 ConfigNode *scfgobj = elm->data; |
293 cx_foreach(ConfigNode *, scfgobj, iter) { |
291 if(cfg_handle_vs(serverconfig, scfgobj)) { |
294 if(cfg_handle_vs(serverconfig, scfgobj)) { |
292 return NULL; |
295 return NULL; |
293 } |
296 } |
294 } |
297 } |
295 ucx_list_free(list); |
298 cxListDestroy(list); |
296 |
299 |
297 log_ereport(LOG_DEBUG, "apply config: ResourcePool"); |
300 log_ereport(LOG_DEBUG, "apply config: ResourcePool"); |
298 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("ResourcePool")); |
301 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, cx_str("ResourcePool")); |
299 UCX_FOREACH(elm, list) { |
302 iter = cxListIterator(list, 0); |
300 ConfigNode *scfgobj = elm->data; |
303 cx_foreach(ConfigNode *, scfgobj, iter) { |
301 if(cfg_handle_resourcepool(serverconfig, scfgobj)) { |
304 if(cfg_handle_resourcepool(serverconfig, scfgobj)) { |
302 return NULL; |
305 return NULL; |
303 } |
306 } |
304 } |
307 } |
|
308 cxListDestroy(list); |
305 |
309 |
306 log_ereport(LOG_DEBUG, "apply config: Dav"); |
310 log_ereport(LOG_DEBUG, "apply config: Dav"); |
307 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("Dav")); |
311 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, cx_str("Dav")); |
308 UCX_FOREACH(elm, list) { |
312 iter = cxListIterator(list, 0); |
309 ConfigNode *scfgobj = elm->data; |
313 cx_foreach(ConfigNode *, scfgobj, iter) { |
310 if(cfg_handle_dav(serverconfig, scfgobj)) { |
314 if(cfg_handle_dav(serverconfig, scfgobj)) { |
311 return NULL; |
315 return NULL; |
312 } |
316 } |
313 } |
317 } |
|
318 cxListDestroy(list); |
314 |
319 |
315 // set VirtualServer for all listeners |
320 // set VirtualServer for all listeners |
316 UcxList *ls = serverconfig->listeners; |
321 CxList *ls = serverconfig->listeners; |
317 while(ls) { |
322 iter = cxListIterator(ls, 0); |
318 HttpListener *listener = ls->data; |
323 cx_foreach(HttpListener *, listener, iter) { |
319 |
324 cxstring vsname = cx_str(listener->default_vs.vs_name); |
320 sstr_t vsname = sstr(listener->default_vs.vs_name); |
|
321 |
325 |
322 // search for VirtualServer |
326 // search for VirtualServer |
323 //int b = 0; |
327 //int b = 0; |
324 UcxMapIterator iter = ucx_map_iterator(serverconfig->host_vs); |
328 CxIterator map_iter = cxMapIteratorValues(serverconfig->host_vs); |
325 VirtualServer *vs; |
329 cx_foreach(VirtualServer *, vs, map_iter) { |
326 UCX_MAP_FOREACH(key, vs, iter) { |
330 if(!cx_strcmp(vsname, (cxstring){vs->name.ptr, vs->name.length})) { |
327 if(!sstrcmp(vsname, vs->name)) { |
|
328 listener->default_vs.vs = vs; |
331 listener->default_vs.vs = vs; |
329 break; |
332 break; |
330 } |
333 } |
331 } |
334 } |
332 |
|
333 ls = ls->next; |
|
334 } |
335 } |
335 |
336 |
336 serverconfig_free(serverconf); |
337 serverconfig_free(serverconf); |
337 |
338 |
338 return serverconfig; |
339 return serverconfig; |
353 void init_server_config_parser() { |
354 void init_server_config_parser() { |
354 |
355 |
355 } |
356 } |
356 |
357 |
357 int cfg_handle_runtime(ServerConfiguration *cfg, ConfigNode *obj) { |
358 int cfg_handle_runtime(ServerConfiguration *cfg, ConfigNode *obj) { |
358 scstr_t user = serverconfig_directive_value(obj, SC("User")); |
359 cxstring user = serverconfig_directive_value(obj, cx_str("User")); |
359 if(user.ptr) { |
360 if(user.ptr) { |
360 cfg->user = sstrdup_a(cfg->a, user); |
361 cfg->user = cx_strdup_a(cfg->a, user); |
361 } |
362 } |
362 scstr_t tmp = serverconfig_directive_value(obj, SC("Temp")); |
363 cxstring tmp = serverconfig_directive_value(obj, cx_str("Temp")); |
363 if(tmp.ptr) { |
364 if(tmp.ptr) { |
364 cfg->tmp = sstrdup_a(cfg->a, tmp); |
365 cfg->tmp = cx_strdup_a(cfg->a, tmp); |
365 } else { |
366 } else { |
366 // TODO: do this check after all config loading is done |
367 // TODO: do this check after all config loading is done |
367 log_ereport(LOG_MISCONFIG, "no temporary directory specified"); |
368 log_ereport(LOG_MISCONFIG, "no temporary directory specified"); |
368 return -1; |
369 return -1; |
369 } |
370 } |
370 |
371 |
371 // mime file |
372 // mime file |
372 scstr_t mf = serverconfig_directive_value(obj, SC("MimeFile")); |
373 cxstring mf = serverconfig_directive_value(obj, cx_str("MimeFile")); |
373 scstr_t base = SC("config/"); |
374 cxstring base = cx_str("config/"); |
374 sstr_t file = sstrcat(2, base, mf); |
375 cxmutstr file = cx_strcat(2, base, mf); |
375 |
376 |
376 if(mime_conf_load(cfg, file)) { |
377 if(mime_conf_load(cfg, file)) { |
377 return -1; |
378 return -1; |
378 } |
379 } |
379 |
380 |
380 free(file.ptr); |
381 free(file.ptr); |
381 return 0; |
382 return 0; |
382 } |
383 } |
383 |
384 |
384 int cfg_handle_logfile(ServerConfiguration *cfg, ConfigNode *obj) { |
385 int cfg_handle_logfile(ServerConfiguration *cfg, ConfigNode *obj) { |
385 scstr_t file = serverconfig_directive_value(obj, SC("File")); |
386 cxstring file = serverconfig_directive_value(obj, cx_str("File")); |
386 scstr_t lvl = serverconfig_directive_value(obj, SC("Level")); |
387 cxstring lvl = serverconfig_directive_value(obj, cx_str("Level")); |
387 |
388 |
388 int err = 0; |
389 int err = 0; |
389 if(file.ptr == NULL) { |
390 if(file.ptr == NULL) { |
390 err = 1; |
391 err = 1; |
391 log_ereport(LOG_MISCONFIG, "LogFile: parameter missing: File"); |
392 log_ereport(LOG_MISCONFIG, "LogFile: parameter missing: File"); |
513 } |
514 } |
514 |
515 |
515 int cfg_handle_accesslog(ServerConfiguration *cfg, ConfigNode *obj) { |
516 int cfg_handle_accesslog(ServerConfiguration *cfg, ConfigNode *obj) { |
516 // TODO: use a name to identify the log file |
517 // TODO: use a name to identify the log file |
517 |
518 |
518 scstr_t file = serverconfig_directive_value(obj, SC("File")); |
519 cxstring file = serverconfig_directive_value(obj, cx_str("File")); |
519 if(file.ptr == NULL) { |
520 if(file.ptr == NULL) { |
520 return 0; |
521 return 0; |
521 } |
522 } |
522 sstr_t format; |
523 cxmutstr format; |
523 format.ptr = NULL; |
524 format.ptr = NULL; |
524 format.length = 0; |
525 format.length = 0; |
525 |
526 |
526 //AccessLog *log = get_access_log(file, format); |
527 //AccessLog *log = get_access_log(file, format); |
527 LogFile *log_file = get_access_log_file(file); |
528 LogFile *log_file = get_access_log_file(file); |
528 if(!log_file) { |
529 if(!log_file) { |
529 // TODO: error/warning |
530 // TODO: error/warning |
530 return 0; |
531 return 0; |
531 } |
532 } |
532 AccessLog *log = pool_malloc(cfg->pool, sizeof(AccessLog)); |
533 AccessLog *log = pool_malloc(cfg->pool, sizeof(AccessLog)); |
533 log->file = sstrdup_a(cfg->a, file); |
534 log->file = cx_strdup_a(cfg->a, file); |
534 log->format = format; |
535 log->format = format; |
535 log->log = log_file; |
536 log->log = log_file; |
536 cfg->logfiles = ucx_list_append_a(cfg->a, cfg->logfiles, log); |
537 cxListAdd(cfg->logfiles, log); |
537 |
538 |
538 if(!cfg->default_log) { |
539 if(!cfg->default_log) { |
539 cfg->default_log = log; |
540 cfg->default_log = log; |
540 } |
541 } |
541 |
542 |
542 return 0; |
543 return 0; |
543 } |
544 } |
544 |
545 |
545 int cfg_handle_authdb(ServerConfiguration *cfg, ConfigNode *obj) { |
546 int cfg_handle_authdb(ServerConfiguration *cfg, ConfigNode *obj) { |
546 scstr_t name = serverconfig_directive_value(obj, SC("Name")); |
547 cxstring name = serverconfig_directive_value(obj, cx_str("Name")); |
547 scstr_t type = serverconfig_directive_value(obj, SC("Type")); |
548 cxstring type = serverconfig_directive_value(obj, cx_str("Type")); |
548 |
549 |
549 AuthDB *authdb = NULL; |
550 AuthDB *authdb = NULL; |
550 |
551 |
551 if(!sstrcmp(type, sstr("ldap"))) { |
552 if(!cx_strcmp(type, cx_str("ldap"))) { |
552 LDAPConfig conf; |
553 LDAPConfig conf; |
553 |
554 |
554 scstr_t host = serverconfig_directive_value(obj, SC("Host")); |
555 cxstring host = serverconfig_directive_value(obj, cx_str("Host")); |
555 scstr_t port = serverconfig_directive_value( obj, SC("Port")); |
556 cxstring port = serverconfig_directive_value( obj, cx_str("Port")); |
556 scstr_t basedn = serverconfig_directive_value(obj, SC("BaseDN")); |
557 cxstring basedn = serverconfig_directive_value(obj, cx_str("BaseDN")); |
557 scstr_t binddn = serverconfig_directive_value(obj, SC("BindDN")); |
558 cxstring binddn = serverconfig_directive_value(obj, cx_str("BindDN")); |
558 scstr_t basepw = serverconfig_directive_value(obj, SC("BindPW")); |
559 cxstring basepw = serverconfig_directive_value(obj, cx_str("BindPW")); |
559 |
560 |
560 conf.hostname = sstrdup_a(cfg->a, host).ptr; |
561 conf.hostname = cx_strdup_a(cfg->a, host).ptr; |
561 conf.port = atoi(port.ptr); |
562 conf.port = atoi(port.ptr); |
562 conf.basedn = sstrdup_a(cfg->a, basedn).ptr; |
563 conf.basedn = cx_strdup_a(cfg->a, basedn).ptr; |
563 conf.binddn = sstrdup_a(cfg->a, binddn).ptr; |
564 conf.binddn = cx_strdup_a(cfg->a, binddn).ptr; |
564 conf.bindpw = sstrdup_a(cfg->a, basepw).ptr; |
565 conf.bindpw = cx_strdup_a(cfg->a, basepw).ptr; |
565 |
566 |
566 authdb = create_ldap_authdb(cfg, name.ptr, &conf); |
567 authdb = create_ldap_authdb(cfg, name.ptr, &conf); |
567 } else if(!sstrcmp(type, sstr("keyfile"))) { |
568 } else if(!cx_strcmp(type, cx_str("keyfile"))) { |
568 // we only need the file parameter |
569 // we only need the file parameter |
569 scstr_t file = serverconfig_directive_value(obj, SC("File")); |
570 cxstring file = serverconfig_directive_value(obj, cx_str("File")); |
570 if(file.length == 0) { |
571 if(file.length == 0) { |
571 log_ereport( |
572 log_ereport( |
572 LOG_MISCONFIG, |
573 LOG_MISCONFIG, |
573 "missing File parameter for keyfile authdb"); |
574 "missing File parameter for keyfile authdb"); |
574 return 1; |
575 return 1; |
592 ZERO(&lc, sizeof(ListenerConfig)); |
593 ZERO(&lc, sizeof(ListenerConfig)); |
593 lc.cfg = cfg; |
594 lc.cfg = cfg; |
594 lc.port = 8080; |
595 lc.port = 8080; |
595 lc.nacceptors = 1; |
596 lc.nacceptors = 1; |
596 |
597 |
597 scstr_t name = serverconfig_directive_value(obj, SC("Name")); |
598 cxstring name = serverconfig_directive_value(obj, cx_str("Name")); |
598 scstr_t port = serverconfig_directive_value(obj, SC("Port")); |
599 cxstring port = serverconfig_directive_value(obj, cx_str("Port")); |
599 scstr_t vs = serverconfig_directive_value(obj, SC("DefaultVS")); |
600 cxstring vs = serverconfig_directive_value(obj, cx_str("DefaultVS")); |
600 scstr_t thrp = serverconfig_directive_value(obj, SC("Threadpool")); |
601 cxstring thrp = serverconfig_directive_value(obj, cx_str("Threadpool")); |
601 scstr_t blck = serverconfig_directive_value(obj, SC("BlockingIO")); |
602 cxstring blck = serverconfig_directive_value(obj, cx_str("BlockingIO")); |
602 |
603 |
603 // TODO: use sstrdup_pool? |
604 // TODO: use cx_strdup_pool? |
604 int64_t port_value; |
605 int64_t port_value; |
605 if(!util_strtoint(port.ptr, &port_value)) { |
606 if(!util_strtoint(port.ptr, &port_value)) { |
606 log_ereport(LOG_MISCONFIG, "Listener: Invalid argument for parameter 'Port': '%s'", port.ptr); |
607 log_ereport(LOG_MISCONFIG, "Listener: Invalid argument for parameter 'Port': '%s'", port.ptr); |
607 return 1; |
608 return 1; |
608 } |
609 } |
609 if(port_value < 1 || port_value > 65535) { |
610 if(port_value < 1 || port_value > 65535) { |
610 log_ereport(LOG_MISCONFIG, "Listener: Port number out of range (1 .. 65535)"); |
611 log_ereport(LOG_MISCONFIG, "Listener: Port number out of range (1 .. 65535)"); |
611 return 1; |
612 return 1; |
612 } |
613 } |
613 |
614 |
614 lc.name = sstrdup(name); |
615 lc.name = cx_strdup(name); |
615 lc.port = port_value; |
616 lc.port = port_value; |
616 lc.vs = sstrdup(vs); |
617 lc.vs = cx_strdup(vs); |
617 lc.threadpool = sstrdup(thrp); |
618 lc.threadpool = cx_strdup(thrp); |
618 |
619 |
619 lc.blockingio = util_getboolean_s(blck, WS_FALSE); |
620 lc.blockingio = util_getboolean_s(blck, WS_FALSE); |
620 |
621 |
621 scstr_t ssl = serverconfig_directive_value(obj, SC("SSL")); |
622 cxstring ssl = serverconfig_directive_value(obj, cx_str("SSL")); |
622 if(util_getboolean_s(ssl, WS_FALSE)) { |
623 if(util_getboolean_s(ssl, WS_FALSE)) { |
623 scstr_t cert = serverconfig_directive_value(obj, SC("Cert")); |
624 cxstring cert = serverconfig_directive_value(obj, cx_str("Cert")); |
624 scstr_t privkey = serverconfig_directive_value(obj, SC("Key")); |
625 cxstring privkey = serverconfig_directive_value(obj, cx_str("Key")); |
625 scstr_t chain = serverconfig_directive_value(obj, SC("CertChain")); |
626 cxstring chain = serverconfig_directive_value(obj, cx_str("CertChain")); |
626 scstr_t disableprot = serverconfig_directive_value(obj, SC("SSLDisableProtocol")); |
627 cxstring disableprot = serverconfig_directive_value(obj, cx_str("SSLDisableProtocol")); |
627 |
628 |
628 WSBool config_ok = WS_TRUE; |
629 WSBool config_ok = WS_TRUE; |
629 // TODO: log error |
630 // TODO: log error |
630 if(!cert.ptr && !chain.ptr) { |
631 if(!cert.ptr && !chain.ptr) { |
631 log_ereport( |
632 log_ereport( |
658 HttpListener *listener = http_listener_create(&lc); |
659 HttpListener *listener = http_listener_create(&lc); |
659 if(!listener) { |
660 if(!listener) { |
660 return 1; |
661 return 1; |
661 } |
662 } |
662 |
663 |
663 listener->default_vs.vs_name = sstrdup_a(cfg->a, lc.vs).ptr; |
664 listener->default_vs.vs_name = cx_strdup_a(cfg->a, (cxstring){lc.vs.ptr, lc.vs.length}).ptr; |
664 cfg->listeners = ucx_list_append_a(cfg->a, cfg->listeners, listener); |
665 cxListAdd(cfg->listeners, listener); |
665 |
666 |
666 return 0; |
667 return 0; |
667 } |
668 } |
668 |
669 |
669 int cfg_handle_vs(ServerConfiguration *cfg, ConfigNode *obj) { |
670 int cfg_handle_vs(ServerConfiguration *cfg, ConfigNode *obj) { |
670 VirtualServer *vs = vs_new(); |
671 VirtualServer *vs = vs_new(); |
671 |
672 |
672 vs->name = sstrdup_a(cfg->a, serverconfig_directive_value(obj, SC("Name"))); |
673 vs->name = cx_strdup_a(cfg->a, serverconfig_directive_value(obj, cx_str("Name"))); |
673 vs->host = sstrdup_a(cfg->a, serverconfig_directive_value(obj, SC("Host"))); |
674 vs->host = cx_strdup_a(cfg->a, serverconfig_directive_value(obj, cx_str("Host"))); |
674 vs->document_root = sstrdup_a(cfg->a, serverconfig_directive_value(obj, SC("DocRoot"))); |
675 vs->document_root = cx_strdup_a(cfg->a, serverconfig_directive_value(obj, cx_str("DocRoot"))); |
675 |
676 |
676 scstr_t objfile = serverconfig_directive_value(obj, SC("ObjectFile")); |
677 cxstring objfile = serverconfig_directive_value(obj, cx_str("ObjectFile")); |
677 scstr_t aclfile = serverconfig_directive_value(obj, SC("ACLFile")); |
678 cxstring aclfile = serverconfig_directive_value(obj, cx_str("ACLFile")); |
678 |
679 |
679 // load the object config file |
680 // load the object config file |
680 sstr_t base = sstr("config/"); |
681 cxstring base = cx_str("config/"); |
681 sstr_t file = sstrcat(2, base, objfile); |
682 // cx_strcat with allocator because we want to keep the string |
682 // sstrcat with allocator because we want to keep the string |
683 cxmutstr file = cx_strcat_a(cfg->a, 2, base, objfile); |
683 file = sstrcat_a(cfg->a, 2, base, objfile); |
|
684 |
684 |
685 HTTPObjectConfig *httpobj = objconf_load(cfg, file); |
685 HTTPObjectConfig *httpobj = objconf_load(cfg, file); |
686 if(!httpobj) { |
686 if(!httpobj) { |
687 return -1; |
687 return -1; |
688 } |
688 } |
689 vs->objectfile = file; |
689 vs->objectfile = file; |
690 vs->objects = httpobj; |
690 vs->objects = httpobj; |
691 |
691 |
692 |
692 |
693 // load acl config file |
693 // load acl config file |
694 file = sstrcat(2, base, aclfile); |
694 cxmutstr acl_filepath = cx_strcat(2, base, aclfile); |
695 |
695 |
696 ACLData *acldata = acl_conf_load(cfg, file); |
696 ACLData *acldata = acl_conf_load(cfg, acl_filepath.ptr); |
|
697 free(acl_filepath.ptr); |
697 if(!acldata) { |
698 if(!acldata) { |
698 return -1; |
699 return -1; |
699 } |
700 } |
700 vs->acls = acldata; |
701 vs->acls = acldata; |
701 |
|
702 free(file.ptr); |
|
703 |
702 |
704 |
703 |
705 // set the access log for the virtual server |
704 // set the access log for the virtual server |
706 // TODO: don't always use the default |
705 // TODO: don't always use the default |
707 vs->log = cfg->default_log; |
706 vs->log = cfg->default_log; |
708 |
707 |
709 ucx_map_sstr_put(cfg->host_vs, vs->host, vs); |
708 cxMapPut(cfg->host_vs, cx_hash_key_bytes((unsigned const char*)vs->host.ptr, vs->host.length), vs); |
710 |
709 |
711 return 0; |
710 return 0; |
712 } |
711 } |
713 |
712 |
714 int cfg_handle_dav(ServerConfiguration *cfg, ConfigNode *obj) { |
713 int cfg_handle_dav(ServerConfiguration *cfg, ConfigNode *obj) { |
715 UcxList *backends = NULL; // list of ConfigArg* |
714 CxAllocator *a = pool_allocator(cfg->pool); |
716 UcxAllocator a = util_pool_allocator(cfg->pool); |
715 CxList *backends = cxPointerLinkedListCreate(a, cx_cmp_ptr); // list of ConfigParam* |
717 int init_error; |
716 int init_error; |
718 |
717 |
719 // parse args |
718 // parse args |
720 char *uri = NULL; |
719 char *uri = NULL; |
721 char *ppath = NULL; |
720 char *ppath = NULL; |
722 char *name = NULL; |
721 char *name = NULL; |
723 UCX_FOREACH(elm, obj->args) { |
722 for(ConfigParam *arg=obj->args;arg;arg=arg->next) { |
724 ConfigArg *arg = elm->data; |
723 cxstring arg_name = (cxstring){ arg->name.ptr, arg->name.length }; |
725 if(arg->name.ptr == NULL) { |
724 if(arg->name.ptr == NULL) { |
726 // default: uri |
725 // default: uri |
727 uri = arg->value.ptr; |
726 uri = arg->value.ptr; |
728 } else if(!sstrcasecmp(arg->name, SC("uri"))) { |
727 } else if(!cx_strcasecmp(arg_name, cx_str("uri"))) { |
729 uri = arg->value.ptr; |
728 uri = arg->value.ptr; |
730 } else if(!sstrcasecmp(arg->name, SC("ppath"))) { |
729 } else if(!cx_strcasecmp(arg_name, cx_str("ppath"))) { |
731 ppath = arg->value.ptr; |
730 ppath = arg->value.ptr; |
732 } else if(!sstrcasecmp(arg->name, SC("name"))) { |
731 } else if(!cx_strcasecmp(arg_name, cx_str("name"))) { |
733 name = arg->value.ptr; |
732 name = arg->value.ptr; |
734 } |
733 } |
735 } |
734 } |
736 if(!uri && !ppath && !name) { |
735 if(!uri && !ppath && !name) { |
737 return 1; |
736 return 1; |
738 } |
737 } |
739 |
738 |
740 // get a list of all DavBackends |
739 // get a list of all DavBackends |
741 UCX_FOREACH(elm, obj->children) { |
740 for(ConfigNode *node=obj->children_begin;node;node=node->next) { |
742 ConfigNode *node = elm->data; |
741 cxstring node_name = cx_strn(node->name.ptr, node->name.length); |
743 if(!sstrcasecmp(node->name, SC("DavBackend"))) { |
742 if(!cx_strcasecmp(node_name, cx_str("DavBackend"))) { |
744 if(node->type == CONFIG_NODE_DIRECTIVE) { |
743 if(node->type == CONFIG_NODE_DIRECTIVE) { |
745 if(ucx_list_size(node->args) == 1) { |
744 if(CFG_NUM_PARAMS(node->args) == 1) { |
746 ConfigArg *arg = node->args->data; |
745 cxListAdd(backends, node->args); |
747 backends = ucx_list_append(backends, arg); |
|
748 } else { |
746 } else { |
749 log_ereport(LOG_MISCONFIG, "DavBackend must have only one value"); |
747 log_ereport(LOG_MISCONFIG, "DavBackend must have only one value"); |
750 ucx_list_free(backends); |
748 cxListDestroy(backends); |
751 return 1; |
749 return 1; |
752 } |
750 } |
753 } else { |
751 } else { |
754 log_ereport(LOG_MISCONFIG, "DavBackend must be a directive"); |
752 log_ereport(LOG_MISCONFIG, "DavBackend must be a directive"); |
755 ucx_list_free(backends); |
753 cxListDestroy(backends); |
756 return 1; |
754 return 1; |
757 } |
755 } |
758 } |
756 } |
759 } |
757 } |
760 |
758 |
761 int ret = 0; |
759 int ret = 0; |
762 WebdavRepository *repository = pool_malloc(cfg->pool, sizeof(WebdavRepository)); |
760 WebdavRepository *repository = pool_malloc(cfg->pool, sizeof(WebdavRepository)); |
763 repository->vfs = NULL; |
761 repository->vfs = NULL; |
764 repository->vfsInitData = NULL; |
762 repository->vfsInitData = NULL; |
765 repository->davBackends = NULL; |
763 repository->davBackends = cxPointerLinkedListCreate(a, cx_cmp_ptr); // value type: WebdavBackendInitData* |
766 |
764 |
767 // initialize backends |
765 // initialize backends |
768 UCX_FOREACH(elm, backends) { |
766 CxIterator i = cxListIterator(backends, 0); |
|
767 cx_foreach(ConfigParam *, backendArg, i) { |
769 // the DavBackend value should contain the dav class name |
768 // the DavBackend value should contain the dav class name |
770 ConfigArg *backendArg = elm->data; |
769 |
771 |
770 WebdavType *dav = webdav_get_type((cxstring){backendArg->value.ptr, backendArg->value.length}); |
772 WebdavType *dav = webdav_get_type((scstr_t){backendArg->value.ptr, backendArg->value.length}); |
|
773 if(!dav) { |
771 if(!dav) { |
774 log_ereport(LOG_MISCONFIG, "Unknown webdav backend type '%s'", backendArg->value.ptr); |
772 log_ereport(LOG_MISCONFIG, "Unknown webdav backend type '%s'", backendArg->value.ptr); |
775 ret = 1; |
773 ret = 1; |
776 break; |
774 break; |
777 } |
775 } |
811 log_ereport(LOG_FAILURE, "Unknown vfs type '%s'", vfs_class.ptr); |
810 log_ereport(LOG_FAILURE, "Unknown vfs type '%s'", vfs_class.ptr); |
812 ret = 1; |
811 ret = 1; |
813 } |
812 } |
814 } |
813 } |
815 |
814 |
816 scstr_t object = serverconfig_directive_value(obj, SC("Object")); |
815 cxstring object = serverconfig_directive_value(obj, cx_str("Object")); |
817 if(object.length > 0) { |
816 if(object.length > 0) { |
818 repository->object = sstrdup_a(&a, object); |
817 repository->object = cx_strdup_a(a, object); |
819 if(repository->object.length != object.length) { |
818 if(repository->object.length != object.length) { |
820 // OOM |
819 // OOM |
821 log_ereport(LOG_FAILURE, "Cannot create webdav repository: OOM"); |
820 log_ereport(LOG_FAILURE, "Cannot create webdav repository: OOM"); |
822 ret = 1; |
821 ret = 1; |
823 } |
822 } |
824 } |
823 } |
825 |
824 |
826 if(!ret) { |
825 if(!ret) { |
827 if(name) { |
826 if(name) { |
828 ucx_map_cstr_put(cfg->dav, name, repository); |
827 cxMapPut(cfg->dav, cx_hash_key_str(name), repository); |
829 } else { |
828 } else { |
830 log_ereport(LOG_FAILURE, "TODO: location based dav repositories not implemented"); |
829 log_ereport(LOG_FAILURE, "TODO: location based dav repositories not implemented"); |
831 ret = 1; |
830 ret = 1; |
832 } |
831 } |
833 } |
832 } |
834 |
833 |
835 return ret; |
834 return ret; |
836 } |
835 } |
837 |
836 |
838 static int convert_objconf(ServerConfiguration *scfg, ObjectConfig *cfg, HTTPObjectConfig *conf, sstr_t file) { |
837 static int convert_objconf(ServerConfiguration *scfg, ObjectConfig *cfg, HTTPObjectConfig *conf, cxmutstr file) { |
839 pool_handle_t *pool = conf->pool; |
838 pool_handle_t *pool = conf->pool; |
840 |
839 |
841 UcxList *objlist = cfg->objects; |
840 CxList *objlist = cfg->objects; |
|
841 CxIterator iter = cxListIterator(objlist, 0); |
842 int i = 0; |
842 int i = 0; |
843 while(objlist != NULL) { |
843 cx_foreach(ConfigObject*, cob, iter) { |
844 ConfigObject *cob = objlist->data; |
|
845 |
|
846 // get name and ppath |
844 // get name and ppath |
847 char *name = NULL; |
845 char *name = NULL; |
848 char *ppath = NULL; |
846 char *ppath = NULL; |
849 if(cob->name.length > 0) { |
847 if(cob->name.length > 0) { |
850 name = sstrdup_pool(pool, cob->name).ptr; |
848 name = cx_strdup_pool(pool, cob->name).ptr; |
851 if(!name) return -1; |
849 if(!name) return -1; |
852 } |
850 } |
853 if(cob->ppath.length > 0) { |
851 if(cob->ppath.length > 0) { |
854 ppath = sstrdup_pool(pool, cob->ppath).ptr; |
852 ppath = cx_strdup_pool(pool, cob->ppath).ptr; |
855 if(!ppath) return -1; |
853 if(!ppath) return -1; |
856 } |
854 } |
857 |
855 |
858 // create and add object |
856 // create and add object |
859 httpd_object *obj = object_new(pool, name); |
857 httpd_object *obj = object_new(pool, name); |
951 free_object_config(cfg); |
947 free_object_config(cfg); |
952 |
948 |
953 return !ret ? conf : NULL; |
949 return !ret ? conf : NULL; |
954 } |
950 } |
955 |
951 |
956 int mime_conf_load(ServerConfiguration *cfg, sstr_t file) { |
952 int mime_conf_load(ServerConfiguration *cfg, cxmutstr file) { |
957 MimeConfig *mimecfg = load_mime_config(file.ptr); |
953 MimeConfig *mimecfg = load_mime_config(file.ptr); |
958 if(!mimecfg) { |
954 if(!mimecfg) { |
959 return -1; |
955 return -1; |
960 } |
956 } |
961 |
957 |
962 int ret = 0; |
958 int ret = 0; |
963 |
959 |
964 // cleanup in case of errors is done by the allocator |
960 // cleanup in case of errors is done by the allocator |
965 MimeMap *mimemap = almalloc(cfg->a, sizeof(MimeMap)); |
961 MimeMap *mimemap = cxMalloc(cfg->a, sizeof(MimeMap)); |
966 UcxMap *map = ucx_map_new_a(cfg->a, (mimecfg->ntypes * 3) / 2); |
962 CxMap *map = cxHashMapCreate(cfg->a, (mimecfg->ntypes * 3) / 2); |
967 |
963 |
968 if(mimemap && map) { |
964 if(mimemap && map) { |
969 mimemap->map = map; |
965 mimemap->map = map; |
970 |
966 |
971 // add ext type pairs |
967 // add ext type pairs |
972 UCX_FOREACH(md, mimecfg->directives) { |
968 for(MimeDirective *d=mimecfg->directives_begin;d;d=d->next) { |
973 MimeDirective *d = md->data; |
|
974 // add the type for each extension to the map |
969 // add the type for each extension to the map |
975 UCX_FOREACH(xl, d->exts) { |
970 for(int i=0;i<d->nextensions;i++) { |
976 sstr_t ext = sstr(xl->data); |
971 cxstring ext = d->extensions[i]; |
977 sstr_t value = sstrdup(d->type); |
972 cxmutstr value = cx_strdup(cx_strn(d->type.ptr, d->type.length)); |
978 if(ucx_map_sstr_put(map, ext, value.ptr)) { |
973 if(cxMapPut(map, cx_hash_key_bytes((const unsigned char *)ext.ptr, ext.length), value.ptr)) { |
979 log_ereport(LOG_CATASTROPHE, "OOM"); |
974 log_ereport(LOG_CATASTROPHE, "OOM"); |
980 ret = -1; |
975 ret = -1; |
981 break; |
976 break; |
982 } |
977 } |
983 } |
978 } |
996 return ret; |
991 return ret; |
997 } |
992 } |
998 |
993 |
999 |
994 |
1000 |
995 |
1001 ACLData* acl_conf_load(ServerConfiguration *cfg, sstr_t file) { |
996 ACLData* acl_conf_load(ServerConfiguration *cfg, const char *file) { |
1002 ACLFile *aclfile = load_acl_file(file.ptr); |
997 ACLFile *aclfile = load_acl_file(file); |
|
998 if(!aclfile) { |
|
999 log_ereport(LOG_FAILURE, "Cannot load acl file %s", file); |
|
1000 return NULL; |
|
1001 } |
1003 |
1002 |
1004 // TODO: malloc return checks |
1003 // TODO: malloc return checks |
1005 |
1004 |
1006 ACLData *acldata = acl_data_new(cfg->a); |
1005 ACLData *acldata = acl_data_new(cfg->a); |
1007 UCX_FOREACH(elm, aclfile->namedACLs) { |
1006 CxIterator iter = cxListIterator(aclfile->namedACLs, 0); |
1008 ACLConfig *ac = elm->data; |
1007 cx_foreach(ACLConfig *, ac, iter) { |
1009 ACLList *acl = acl_config_convert(cfg, ac); |
1008 ACLList *acl = acl_config_convert(cfg, ac); |
1010 log_ereport(LOG_VERBOSE, "add acl: %.*s", (int)ac->id.length, ac->id.ptr); |
1009 log_ereport(LOG_VERBOSE, "add acl: %.*s", (int)ac->id.length, ac->id.ptr); |
1011 ucx_map_sstr_put(acldata->namedACLs, ac->id, acl); |
1010 cxMapPut(acldata->namedACLs, cx_hash_key(ac->id.ptr, ac->id.length), acl); |
1012 } |
1011 } |
1013 free_acl_file(aclfile); |
1012 free_acl_file(aclfile); |
1014 |
1013 |
1015 return acldata; |
1014 return acldata; |
1016 } |
1015 } |
1017 |
1016 |
1018 ACLList* acl_config_convert(ServerConfiguration *cfg, ACLConfig *acl) { |
1017 ACLList* acl_config_convert(ServerConfiguration *cfg, ACLConfig *acl) { |
1019 UcxAllocator *a = cfg->a; |
1018 CxAllocator *a = cfg->a; |
1020 |
1019 |
1021 WSAcl *acllist = almalloc(cfg->a, sizeof(WSAcl)); |
1020 WSAcl *acllist = cxMalloc(cfg->a, sizeof(WSAcl)); |
1022 acllist->acl.check = (acl_check_f)wsacl_check; |
1021 acllist->acl.check = (acl_check_f)wsacl_check; |
1023 acllist->acl.authdb = NULL; |
1022 acllist->acl.authdb = NULL; |
1024 acllist->acl.authprompt = NULL; |
1023 acllist->acl.authprompt = NULL; |
1025 acllist->acl.isextern = 0; |
1024 acllist->acl.isextern = 0; |
1026 acllist->ace = NULL; |
1025 acllist->ace = NULL; |
1027 acllist->ece = NULL; |
1026 acllist->ece = NULL; |
1028 |
1027 |
1029 if(acl->type.ptr && !sstrcmp(acl->type, sstr("fs"))) { |
1028 if(acl->type.ptr && !cx_strcmp(cx_strn(acl->type.ptr, acl->type.length), cx_str("fs"))) { |
1030 acllist->acl.isextern = 1; |
1029 acllist->acl.isextern = 1; |
1031 } |
1030 } |
1032 |
1031 |
1033 size_t s = ucx_list_size(acl->entries); |
1032 size_t s = CFG_ACE_LIST_SIZE(acl->entries); |
1034 WSAce **tmp_aces = calloc(s, sizeof(WSAce*)); |
1033 WSAce **tmp_aces = calloc(s, sizeof(WSAce*)); |
1035 WSAce **tmp_eces = calloc(s, sizeof(WSAce*)); |
1034 WSAce **tmp_eces = calloc(s, sizeof(WSAce*)); |
1036 int ai = 0; |
1035 int ai = 0; |
1037 int ei = 0; |
1036 int ei = 0; |
1038 |
1037 |
1039 // convert entries |
1038 // convert entries |
1040 UCX_FOREACH(elm, acl->entries) { |
1039 for(ACEConfig *acecfg=acl->entries;acecfg;acecfg=acecfg->next) { |
1041 ACEConfig *acecfg = elm->data; |
|
1042 |
|
1043 // copy data |
1040 // copy data |
1044 WSAce *ace = almalloc(a, sizeof(WSAce)); |
1041 WSAce *ace = cxMalloc(a, sizeof(WSAce)); |
1045 ace->access_mask = acecfg->access_mask; |
1042 ace->access_mask = acecfg->access_mask; |
1046 ace->flags = acecfg->flags; |
1043 ace->flags = acecfg->flags; |
1047 ace->type = acecfg->type; |
1044 ace->type = acecfg->type; |
1048 ace->who = sstrdup_a(a, acecfg->who).ptr; |
1045 ace->who = cx_strdup_a(a, cx_strcast(acecfg->who)).ptr; |
1049 |
1046 |
1050 // add the entry to the correct array |
1047 // add the entry to the correct array |
1051 if(ace->type >= ACL_TYPE_AUDIT) { |
1048 if(ace->type >= ACL_TYPE_AUDIT) { |
1052 tmp_eces[ei] = ace; |
1049 tmp_eces[ei] = ace; |
1053 ei++; |
1050 ei++; |