-rw-r--r-- | lib/configuration.cc | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/lib/configuration.cc b/lib/configuration.cc index 4ee1526..6b21690 100644 --- a/lib/configuration.cc +++ b/lib/configuration.cc | |||
@@ -1,56 +1,57 @@ | |||
1 | #ifdef USE_PCH | 1 | #ifdef USE_PCH |
2 | #include "pch.h" | 2 | #include "pch.h" |
3 | #else | 3 | #else |
4 | #include <unistd.h> | 4 | #include <unistd.h> |
5 | #include <fnmatch.h> | 5 | #include <fnmatch.h> |
6 | #include <cassert> | 6 | #include <cassert> |
7 | #include <stdexcept> | 7 | #include <stdexcept> |
8 | using namespace std; | 8 | using namespace std; |
9 | #include <konforka/util.h> | ||
9 | #include <dotconf.h> | 10 | #include <dotconf.h> |
10 | #include "sitecing/configuration.h" | 11 | #include "sitecing/configuration.h" |
11 | #include "sitecing/sitecing_util.h" | 12 | #include "sitecing/sitecing_util.h" |
12 | #include "sitecing/scoreboard.h" | 13 | #include "sitecing/scoreboard.h" |
13 | #endif | 14 | #endif |
14 | 15 | ||
15 | namespace sitecing { | 16 | namespace sitecing { |
16 | 17 | ||
17 | configuration::configuration() | 18 | configuration::configuration() |
18 | : flags(0), autobuild(false) { } | 19 | : flags(0), autobuild(false) { } |
19 | configuration::configuration(const string& cfile,bool ab) | 20 | configuration::configuration(const string& cfile,bool ab) |
20 | : flags(0), autobuild(ab) { | 21 | : flags(0), autobuild(ab) { |
21 | parse(cfile); | 22 | parse(cfile); |
22 | } | 23 | } |
23 | 24 | ||
24 | enum dc_ctx { | 25 | enum dc_ctx { |
25 | DCC_ROOT = 1, | 26 | DCC_ROOT = 1, |
26 | DCC_PATH = 2, | 27 | DCC_PATH = 2, |
27 | DCC_SCRC = 4 | 28 | DCC_SCRC = 4 |
28 | }; | 29 | }; |
29 | struct dc_context { | 30 | struct dc_context { |
30 | dc_ctx ctx; | 31 | dc_ctx ctx; |
31 | configuration* cf; | 32 | configuration* cf; |
32 | list<config_options*> co; | 33 | list<config_options*> co; |
33 | }; | 34 | }; |
34 | 35 | ||
35 | static DOTCONF_CB(dco_root_source) { dc_context *dcc = (dc_context*)ctx; | 36 | static DOTCONF_CB(dco_root_source) { dc_context *dcc = (dc_context*)ctx; |
36 | dcc->cf->root_source = cmd->data.str; | 37 | dcc->cf->root_source = cmd->data.str; |
37 | dcc->cf->flags |= configuration::flag_root_source; | 38 | dcc->cf->flags |= configuration::flag_root_source; |
38 | return NULL; | 39 | return NULL; |
39 | } | 40 | } |
40 | static DOTCONF_CB(dco_root_intermediate) { dc_context *dcc = (dc_context*)ctx; | 41 | static DOTCONF_CB(dco_root_intermediate) { dc_context *dcc = (dc_context*)ctx; |
41 | dcc->cf->root_intermediate = cmd->data.str; | 42 | dcc->cf->root_intermediate = cmd->data.str; |
42 | dcc->cf->flags |= configuration::flag_root_intermediate; | 43 | dcc->cf->flags |= configuration::flag_root_intermediate; |
43 | return NULL; | 44 | return NULL; |
44 | } | 45 | } |
45 | static DOTCONF_CB(dco_root_so) { dc_context *dcc = (dc_context*)ctx; | 46 | static DOTCONF_CB(dco_root_so) { dc_context *dcc = (dc_context*)ctx; |
46 | dcc->cf->root_so = cmd->data.str; | 47 | dcc->cf->root_so = cmd->data.str; |
47 | dcc->cf->flags |= configuration::flag_root_so; | 48 | dcc->cf->flags |= configuration::flag_root_so; |
48 | return NULL; | 49 | return NULL; |
49 | } | 50 | } |
50 | static DOTCONF_CB(dco_listen_socket) { dc_context *dcc = (dc_context*)ctx; | 51 | static DOTCONF_CB(dco_listen_socket) { dc_context *dcc = (dc_context*)ctx; |
51 | dcc->cf->listen_socket = cmd->data.str; | 52 | dcc->cf->listen_socket = cmd->data.str; |
52 | dcc->cf->flags |= configuration::flag_listen_socket; | 53 | dcc->cf->flags |= configuration::flag_listen_socket; |
53 | return NULL; | 54 | return NULL; |
54 | } | 55 | } |
55 | static DOTCONF_CB(dco_rc_file_name) { dc_context *dcc = (dc_context*)ctx; | 56 | static DOTCONF_CB(dco_rc_file_name) { dc_context *dcc = (dc_context*)ctx; |
56 | dcc->cf->rc_file_name = cmd->data.str; | 57 | dcc->cf->rc_file_name = cmd->data.str; |
@@ -259,207 +260,207 @@ namespace sitecing { | |||
259 | if(stat(source_file.c_str(),&nst)) | 260 | if(stat(source_file.c_str(),&nst)) |
260 | return false; | 261 | return false; |
261 | if(st.st_mtime!=nst.st_mtime) | 262 | if(st.st_mtime!=nst.st_mtime) |
262 | return false; | 263 | return false; |
263 | return true; | 264 | return true; |
264 | } | 265 | } |
265 | 266 | ||
266 | loaded_options *configuration::lookup_loaded_options(const string& target) { | 267 | loaded_options *configuration::lookup_loaded_options(const string& target) { |
267 | // we assume 'target' is a directory with trailing slash appended | 268 | // we assume 'target' is a directory with trailing slash appended |
268 | string scrc = root_source+target; | 269 | string scrc = root_source+target; |
269 | if(flags&flag_rc_file_name) | 270 | if(flags&flag_rc_file_name) |
270 | scrc += rc_file_name; | 271 | scrc += rc_file_name; |
271 | else | 272 | else |
272 | scrc += ".scrc"; | 273 | scrc += ".scrc"; |
273 | // TODO: normalize me, anyway. | 274 | // TODO: normalize me, anyway. |
274 | if(access(scrc.c_str(),R_OK)) | 275 | if(access(scrc.c_str(),R_OK)) |
275 | return 0; // TODO FIXME: this approach leaves already loaded .scrcs around in case of removal | 276 | return 0; // TODO FIXME: this approach leaves already loaded .scrcs around in case of removal |
276 | loaded_specs_t::iterator i = loaded_specs.find(target); | 277 | loaded_specs_t::iterator i = loaded_specs.find(target); |
277 | if(i==loaded_specs.end() || !i->second.is_valid()) { | 278 | if(i==loaded_specs.end() || !i->second.is_valid()) { |
278 | if(i!=loaded_specs.end()) | 279 | if(i!=loaded_specs.end()) |
279 | loaded_specs.erase(i); | 280 | loaded_specs.erase(i); |
280 | pair<loaded_specs_t::iterator,bool> ii = loaded_specs.insert(loaded_specs_t::value_type(target,loaded_options())); | 281 | pair<loaded_specs_t::iterator,bool> ii = loaded_specs.insert(loaded_specs_t::value_type(target,loaded_options())); |
281 | assert(ii.first!=loaded_specs.end()); | 282 | assert(ii.first!=loaded_specs.end()); |
282 | ii.first->second.parse(this,scrc); | 283 | ii.first->second.parse(this,scrc); |
283 | i = ii.first; | 284 | i = ii.first; |
284 | } | 285 | } |
285 | assert(i!=loaded_specs.end()); | 286 | assert(i!=loaded_specs.end()); |
286 | return &(i->second); | 287 | return &(i->second); |
287 | } | 288 | } |
288 | 289 | ||
289 | config_options::action_handler_t *config_options::lookup_action_handler(const string& target) { | 290 | config_options::action_handler_t *config_options::lookup_action_handler(const string& target) { |
290 | for(action_handlers_t::iterator i=action_handlers.begin();i!=action_handlers.end();++i) { | 291 | for(action_handlers_t::iterator i=action_handlers.begin();i!=action_handlers.end();++i) { |
291 | if(i->regex.search(target)) | 292 | if(i->regex.search(target)) |
292 | return &*i; | 293 | return &*i; |
293 | } | 294 | } |
294 | return NULL; | 295 | return NULL; |
295 | } | 296 | } |
296 | 297 | ||
297 | string config_options::lookup_http_status_handler(const string& status) { | 298 | string config_options::lookup_http_status_handler(const string& status) { |
298 | http_status_handlers_t::const_iterator i = http_status_handlers.find(status); | 299 | http_status_handlers_t::const_iterator i = http_status_handlers.find(status); |
299 | string rv; | 300 | string rv; |
300 | if(i!=http_status_handlers.end()) | 301 | if(i!=http_status_handlers.end()) |
301 | rv = i->second; | 302 | rv = i->second; |
302 | return rv; | 303 | return rv; |
303 | } | 304 | } |
304 | 305 | ||
305 | string configuration::lookup_http_status_handler(const string& target,const string& status) { | 306 | string configuration::lookup_http_status_handler(const string& target,const string& status) { |
306 | string t = "/"; | 307 | string t = "/"; |
307 | t += normalize_path(target,strip_leading_slash); | 308 | t += konforka::normalize_path(target,konforka::strip_leading_slash); |
308 | string rv; | 309 | string rv; |
309 | for(;;) { | 310 | for(;;) { |
310 | if(t[t.length()-1]=='/') { | 311 | if(t[t.length()-1]=='/') { |
311 | loaded_options* lo = lookup_loaded_options(t); | 312 | loaded_options* lo = lookup_loaded_options(t); |
312 | if( lo && (lo->flags&config_options::flag_http_status_handlers) ) { | 313 | if( lo && (lo->flags&config_options::flag_http_status_handlers) ) { |
313 | rv = lo->lookup_http_status_handler(status); | 314 | rv = lo->lookup_http_status_handler(status); |
314 | if(!rv.empty()) | 315 | if(!rv.empty()) |
315 | return rv; | 316 | return rv; |
316 | } | 317 | } |
317 | } | 318 | } |
318 | specs_t::iterator i = specs.find(t); | 319 | specs_t::iterator i = specs.find(t); |
319 | if( i!=specs.end() && (i->second.flags&&config_options::flag_http_status_handlers) ) { | 320 | if( i!=specs.end() && (i->second.flags&&config_options::flag_http_status_handlers) ) { |
320 | rv = i->second.lookup_http_status_handler(status); | 321 | rv = i->second.lookup_http_status_handler(status); |
321 | if(!rv.empty()) | 322 | if(!rv.empty()) |
322 | return rv; | 323 | return rv; |
323 | } | 324 | } |
324 | if(t.empty()) | 325 | if(t.empty()) |
325 | return rv; | 326 | return rv; |
326 | string::size_type sl=t.rfind('/'); | 327 | string::size_type sl=t.rfind('/'); |
327 | if(sl==string::npos) { | 328 | if(sl==string::npos) { |
328 | t.erase(); | 329 | t.erase(); |
329 | }else{ | 330 | }else{ |
330 | if(sl==(t.length()-1)) | 331 | if(sl==(t.length()-1)) |
331 | t.erase(sl); | 332 | t.erase(sl); |
332 | else | 333 | else |
333 | t.erase(sl+1); | 334 | t.erase(sl+1); |
334 | } | 335 | } |
335 | } | 336 | } |
336 | } | 337 | } |
337 | 338 | ||
338 | config_options::action_handler_t *configuration::lookup_action_handler(const string& target) { | 339 | config_options::action_handler_t *configuration::lookup_action_handler(const string& target) { |
339 | string t = "/"; | 340 | string t = "/"; |
340 | t += normalize_path(target,strip_leading_slash); | 341 | t += konforka::normalize_path(target,konforka::strip_leading_slash); |
341 | for(;;) { | 342 | for(;;) { |
342 | if(t[t.length()-1]=='/') { | 343 | if(t[t.length()-1]=='/') { |
343 | loaded_options* lo = lookup_loaded_options(t); | 344 | loaded_options* lo = lookup_loaded_options(t); |
344 | if( lo && (lo->flags&config_options::flag_action_handlers) ) { | 345 | if( lo && (lo->flags&config_options::flag_action_handlers) ) { |
345 | config_options::action_handler_t *rv = lo->lookup_action_handler(target); | 346 | config_options::action_handler_t *rv = lo->lookup_action_handler(target); |
346 | if(rv) | 347 | if(rv) |
347 | return rv; | 348 | return rv; |
348 | } | 349 | } |
349 | } | 350 | } |
350 | specs_t::iterator i = specs.find(t); | 351 | specs_t::iterator i = specs.find(t); |
351 | if( i!=specs.end() && (i->second.flags&&config_options::flag_action_handlers) ) { | 352 | if( i!=specs.end() && (i->second.flags&&config_options::flag_action_handlers) ) { |
352 | config_options::action_handler_t *rv = i->second.lookup_action_handler(target); | 353 | config_options::action_handler_t *rv = i->second.lookup_action_handler(target); |
353 | if(rv) | 354 | if(rv) |
354 | return rv; | 355 | return rv; |
355 | } | 356 | } |
356 | if(t.empty()) | 357 | if(t.empty()) |
357 | return NULL; | 358 | return NULL; |
358 | string::size_type sl=t.rfind('/'); | 359 | string::size_type sl=t.rfind('/'); |
359 | if(sl==string::npos) { | 360 | if(sl==string::npos) { |
360 | t.erase(); | 361 | t.erase(); |
361 | }else{ | 362 | }else{ |
362 | if(sl==(t.length()-1)) | 363 | if(sl==(t.length()-1)) |
363 | t.erase(sl); | 364 | t.erase(sl); |
364 | else | 365 | else |
365 | t.erase(sl+1); | 366 | t.erase(sl+1); |
366 | } | 367 | } |
367 | } | 368 | } |
368 | } | 369 | } |
369 | 370 | ||
370 | config_options* configuration::lookup_config(const string& target,int flag) { | 371 | config_options* configuration::lookup_config(const string& target,int flag) { |
371 | string t = "/"; // always assume leading slash | 372 | string t = "/"; // always assume leading slash |
372 | t += normalize_path(target,strip_leading_slash); | 373 | t += konforka::normalize_path(target,konforka::strip_leading_slash); |
373 | // XXX: reconsider precedence | 374 | // XXX: reconsider precedence |
374 | for(;;) { | 375 | for(;;) { |
375 | if(t[t.length()-1]=='/') { | 376 | if(t[t.length()-1]=='/') { |
376 | loaded_options* lo = lookup_loaded_options(t); | 377 | loaded_options* lo = lookup_loaded_options(t); |
377 | if( lo && (lo->flags&flag)==flag ) | 378 | if( lo && (lo->flags&flag)==flag ) |
378 | return lo; | 379 | return lo; |
379 | } | 380 | } |
380 | specs_t::iterator i = specs.find(t); | 381 | specs_t::iterator i = specs.find(t); |
381 | if( i!=specs.end() && (i->second.flags&flag)==flag ) | 382 | if( i!=specs.end() && (i->second.flags&flag)==flag ) |
382 | return &(i->second); | 383 | return &(i->second); |
383 | if(t.empty()) | 384 | if(t.empty()) |
384 | return NULL; | 385 | return NULL; |
385 | string::size_type sl=t.rfind('/'); | 386 | string::size_type sl=t.rfind('/'); |
386 | if(sl==string::npos) { | 387 | if(sl==string::npos) { |
387 | t.erase(); | 388 | t.erase(); |
388 | }else{ | 389 | }else{ |
389 | if(sl==(t.length()-1)) | 390 | if(sl==(t.length()-1)) |
390 | t.erase(sl); | 391 | t.erase(sl); |
391 | else | 392 | else |
392 | t.erase(sl+1); | 393 | t.erase(sl+1); |
393 | } | 394 | } |
394 | } | 395 | } |
395 | } | 396 | } |
396 | 397 | ||
397 | bool config_options::match_autobuild_files(const char *fn,bool &rv) { | 398 | bool config_options::match_autobuild_files(const char *fn,bool &rv) { |
398 | for(list<string>::reverse_iterator i=auto_build_files.rbegin();i!=auto_build_files.rend();++i) { | 399 | for(list<string>::reverse_iterator i=auto_build_files.rbegin();i!=auto_build_files.rend();++i) { |
399 | const char *pat = i->c_str(); | 400 | const char *pat = i->c_str(); |
400 | bool plus = true; | 401 | bool plus = true; |
401 | if((*pat)=='+') | 402 | if((*pat)=='+') |
402 | pat++; | 403 | pat++; |
403 | else if((*pat)=='-') { | 404 | else if((*pat)=='-') { |
404 | plus = false; | 405 | plus = false; |
405 | pat++; | 406 | pat++; |
406 | } | 407 | } |
407 | if(!fnmatch(pat,fn,FNM_NOESCAPE|FNM_PATHNAME|FNM_PERIOD)) { | 408 | if(!fnmatch(pat,fn,FNM_NOESCAPE|FNM_PATHNAME|FNM_PERIOD)) { |
408 | rv = plus; | 409 | rv = plus; |
409 | return true; | 410 | return true; |
410 | } | 411 | } |
411 | } | 412 | } |
412 | return false; | 413 | return false; |
413 | } | 414 | } |
414 | 415 | ||
415 | bool configuration::match_autobuild_files(const string& target,const char *fn) { | 416 | bool configuration::match_autobuild_files(const string& target,const char *fn) { |
416 | string t = "/"; | 417 | string t = "/"; |
417 | t += normalize_path(target,strip_leading_slash|strip_trailing_slash); | 418 | t += konforka::normalize_path(target,konforka::strip_leading_slash|konforka::strip_trailing_slash); |
418 | t += "/"; | 419 | t += "/"; |
419 | bool rv = false; | 420 | bool rv = false; |
420 | for(;;) { | 421 | for(;;) { |
421 | if(t[t.length()-1]=='/') { | 422 | if(t[t.length()-1]=='/') { |
422 | loaded_options* lo = lookup_loaded_options(t); | 423 | loaded_options* lo = lookup_loaded_options(t); |
423 | if(lo && (lo->flags&config_options::flag_auto_build_files) && lo->match_autobuild_files(fn,rv) ) | 424 | if(lo && (lo->flags&config_options::flag_auto_build_files) && lo->match_autobuild_files(fn,rv) ) |
424 | return rv; | 425 | return rv; |
425 | } | 426 | } |
426 | specs_t::iterator i = specs.find(t); | 427 | specs_t::iterator i = specs.find(t); |
427 | if( i!=specs.end() && (i->second.flags&config_options::flag_auto_build_files) && i->second.match_autobuild_files(fn,rv) ) | 428 | if( i!=specs.end() && (i->second.flags&config_options::flag_auto_build_files) && i->second.match_autobuild_files(fn,rv) ) |
428 | return rv; | 429 | return rv; |
429 | if(t.empty()) | 430 | if(t.empty()) |
430 | return rv; | 431 | return rv; |
431 | string::size_type sl=t.rfind('/'); | 432 | string::size_type sl=t.rfind('/'); |
432 | if(sl==string::npos) { | 433 | if(sl==string::npos) { |
433 | t.erase(); | 434 | t.erase(); |
434 | }else{ | 435 | }else{ |
435 | if(sl==(t.length()-1)) | 436 | if(sl==(t.length()-1)) |
436 | t.erase(sl); | 437 | t.erase(sl); |
437 | else | 438 | else |
438 | t.erase(sl+1); | 439 | t.erase(sl+1); |
439 | } | 440 | } |
440 | } | 441 | } |
441 | } | 442 | } |
442 | 443 | ||
443 | void configuration::parse(const string& cfile) { | 444 | void configuration::parse(const string& cfile) { |
444 | struct dc_context dcc; | 445 | struct dc_context dcc; |
445 | dcc.cf = this; | 446 | dcc.cf = this; |
446 | dcc.ctx = DCC_ROOT; | 447 | dcc.ctx = DCC_ROOT; |
447 | dcc.co.push_front(&root_options()); | 448 | dcc.co.push_front(&root_options()); |
448 | configfile_t *cf = dotconf_create((char*)cfile.c_str(),dc_options,(context_t*)&dcc,CASE_INSENSITIVE); | 449 | configfile_t *cf = dotconf_create((char*)cfile.c_str(),dc_options,(context_t*)&dcc,CASE_INSENSITIVE); |
449 | if(!cf) | 450 | if(!cf) |
450 | throw konforka::exception(CODEPOINT,"failed to dotconf_create()"); | 451 | throw konforka::exception(CODEPOINT,"failed to dotconf_create()"); |
451 | cf->errorhandler = (dotconf_errorhandler_t) dc_error_handler; | 452 | cf->errorhandler = (dotconf_errorhandler_t) dc_error_handler; |
452 | cf->contextchecker = (dotconf_contextchecker_t) dc_context_checker; | 453 | cf->contextchecker = (dotconf_contextchecker_t) dc_context_checker; |
453 | if(!dotconf_command_loop(cf)) | 454 | if(!dotconf_command_loop(cf)) |
454 | throw konforka::exception(CODEPOINT,"failed to dotconf_command_loop()"); | 455 | throw konforka::exception(CODEPOINT,"failed to dotconf_command_loop()"); |
455 | dotconf_cleanup(cf); | 456 | dotconf_cleanup(cf); |
456 | } | 457 | } |
457 | 458 | ||
458 | void loaded_options::parse(configuration *config,const string& cfile) { | 459 | void loaded_options::parse(configuration *config,const string& cfile) { |
459 | struct dc_context dcc; | 460 | struct dc_context dcc; |
460 | dcc.cf = config; | 461 | dcc.cf = config; |
461 | dcc.ctx = DCC_SCRC; | 462 | dcc.ctx = DCC_SCRC; |
462 | dcc.co.push_front(this); | 463 | dcc.co.push_front(this); |
463 | configfile_t *cf = dotconf_create((char*)cfile.c_str(),dc_options,(context_t*)&dcc,CASE_INSENSITIVE); | 464 | configfile_t *cf = dotconf_create((char*)cfile.c_str(),dc_options,(context_t*)&dcc,CASE_INSENSITIVE); |
464 | if(!cf) | 465 | if(!cf) |
465 | throw konforka::exception(CODEPOINT,"failed to dotconf_create()"); | 466 | throw konforka::exception(CODEPOINT,"failed to dotconf_create()"); |